Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into modal-size

This commit is contained in:
bansarishukla
2019-11-15 09:49:32 +05:30
68 changed files with 671 additions and 169 deletions

View File

@ -0,0 +1,31 @@
<?php
namespace Laraspace\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class UpdateFinished
{
use Dispatchable;
public $new;
public $old;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($old, $new)
{
$this->old = $old;
$this->new = $new;
}
}

View File

@ -54,7 +54,7 @@ class AccessTokensController extends Controller
{ {
$request->validate([ $request->validate([
'username' => 'required|email', 'username' => 'required|email',
'password' => 'required|string', 'password' => 'required|string|min:8',
]); ]);
if ($this->hasTooManyLoginAttempts($request)) { if ($this->hasTooManyLoginAttempts($request)) {

View File

@ -35,10 +35,9 @@ class EnvironmentController extends Controller
{ {
$results = $this->EnvironmentManager->saveDatabaseVariables($request); $results = $this->EnvironmentManager->saveDatabaseVariables($request);
if(array_key_exists("success", $results)) { if(array_key_exists("success", $results)) {
Artisan::call('config:clear'); Artisan::call('config:clear');
Artisan::call('key:generate --force');
Artisan::call('migrate --seed'); Artisan::call('migrate --seed');
Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations']); Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations']);
@ -57,13 +56,30 @@ class EnvironmentController extends Controller
*/ */
public function saveMailEnvironment(MailEnvironmentRequest $request) public function saveMailEnvironment(MailEnvironmentRequest $request)
{ {
$setting = Setting::getSetting('profile_complete');
$results = $this->EnvironmentManager->saveMailVariables($request); $results = $this->EnvironmentManager->saveMailVariables($request);
Setting::setSetting('profile_complete', 4); if ($setting !== 'COMPLETED')
{
Setting::setSetting('profile_complete', 4);
}
return response()->json($results); return response()->json($results);
} }
public function getMailEnvironment()
{
$MailData = [
'mail_driver' => config('mail.driver'),
'mail_host' => config('mail.host'),
'mail_port' => config('mail.port'),
'mail_username' => config('mail.username'),
'mail_password' => config('mail.password'),
'mail_encryption' => config('mail.encryption')
];
return response()->json($MailData);
}
/** /**
* *

View File

@ -260,6 +260,7 @@ class InvoicesController extends Controller
'error' => 'invalid_due_amount' 'error' => 'invalid_due_amount'
]); ]);
} elseif ($invoice->due_amount != 0 && $invoice->paid_status == Invoice::STATUS_PAID) { } elseif ($invoice->due_amount != 0 && $invoice->paid_status == Invoice::STATUS_PAID) {
$invoice->status = $invoice->getPreviousStatus();
$invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID;
} }

View File

@ -203,7 +203,7 @@ class OnboardingController extends Controller
); );
} }
Setting::setSetting('version','1.0.0'); Setting::setSetting('version', config('crater.version'));
Artisan::call('passport:install --force'); Artisan::call('passport:install --force');

View File

@ -170,6 +170,7 @@ class PaymentController extends Controller
$invoice->status = Invoice::STATUS_COMPLETED; $invoice->status = Invoice::STATUS_COMPLETED;
$invoice->paid_status = Invoice::STATUS_PAID; $invoice->paid_status = Invoice::STATUS_PAID;
} else { } else {
$invoice->status = $invoice->getPreviousStatus();
$invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID;
} }
@ -211,16 +212,7 @@ class PaymentController extends Controller
$invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID;
} }
if ($invoice->due_date < Carbon::now()) { $invoice->status = $invoice->getPreviousStatus();
$invoice->status = Invoice::STATUS_OVERDUE;
} elseif ($invoice->viewed) {
$invoice->status = Invoice::STATUS_VIEWED;
} elseif ($invoice->sent) {
$invoice->status = Invoice::STATUS_SENT;
} else {
$invoice->status = Invoice::STATUS_DRAFT;
}
$invoice->save(); $invoice->save();
} }
@ -246,16 +238,7 @@ class PaymentController extends Controller
$invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID;
} }
if ($invoice->due_date < Carbon::now()) { $invoice->status = $invoice->getPreviousStatus();
$invoice->status = Invoice::STATUS_OVERDUE;
} elseif ($invoice->sent) {
$invoice->status = Invoice::STATUS_SENT;
} elseif ($invoice->viewed) {
$invoice->status = Invoice::STATUS_VIEWED;
} else {
$invoice->status = Invoice::STATUS_DRAFT;
}
$invoice->save(); $invoice->save();
} }

View File

@ -26,8 +26,7 @@ class ReportController extends Controller
$query->whereBetween( $query->whereBetween(
'invoice_date', 'invoice_date',
[$start->format('Y-m-d'), $end->format('Y-m-d')] [$start->format('Y-m-d'), $end->format('Y-m-d')]
) );
->where('paid_status', Invoice::STATUS_PAID);
}]) }])
->customer() ->customer()
->whereCompany($company->id) ->whereCompany($company->id)

View File

@ -0,0 +1,28 @@
<?php
namespace Laraspace\Http\Controllers;
use Illuminate\Http\Request;
use Laraspace\Space\Updater;
use Laraspace\Space\SiteApi;
class UpdateController extends Controller
{
public function update(Request $request)
{
set_time_limit(600); // 10 minutes
$json = Updater::update($request->installed, $request->version);
return response()->json($json);
}
public function checkLatestVersion(Request $request)
{
set_time_limit(600); // 10 minutes
$json = Updater::checkForUpdate();
return response()->json($json);
}
}

View File

@ -26,12 +26,16 @@ class CustomerRequest extends FormRequest
case 'POST': case 'POST':
return [ return [
'name' => 'required', 'name' => 'required',
'addresses.*.address_street_1' => 'max:255',
'addresses.*.address_street_2' => 'max:255',
'email' => 'email|nullable|unique:users,email', 'email' => 'email|nullable|unique:users,email',
]; ];
break; break;
case 'PUT': case 'PUT':
return [ return [
'name' => 'required', 'name' => 'required',
'addresses.*.address_street_1' => 'max:255',
'addresses.*.address_street_2' => 'max:255',
]; ];
break; break;
default: default:

View File

@ -27,13 +27,22 @@ class EstimatesRequest extends FormRequest
'expiry_date' => 'required', 'expiry_date' => 'required',
'estimate_number' => 'required|unique:estimates,estimate_number', 'estimate_number' => 'required|unique:estimates,estimate_number',
'user_id' => 'required', 'user_id' => 'required',
'discount' => 'required', 'discount' => 'required|digits_between:1,20',
'discount_val' => 'required|digits_between:1,20',
'sub_total' => 'required|digits_between:1,20',
'total' => 'required|digits_between:1,20',
'tax' => 'required|digits_between:1,20',
'estimate_template_id' => 'required', 'estimate_template_id' => 'required',
'items' => 'required|array', 'items' => 'required|array',
'items.*.description' => 'max:255',
'items.*' => 'required|max:255', 'items.*' => 'required|max:255',
'items.*.name' => 'required', 'items.*.name' => 'required',
'items.*.quantity' => 'required|numeric', 'items.*.quantity' => 'required|digits_between:1,20',
'items.*.price' => 'required|numeric', 'items.*.price' => 'required|digits_between:1,20',
'items.*.discount' => 'digits_between:1,20',
'items.*.discount_val' => 'digits_between:1,20',
'items.*.tax' => 'digits_between:1,20',
'items.*.total' => 'digits_between:1,20',
]; ];
if ($this->getMethod() == 'PUT') { if ($this->getMethod() == 'PUT') {

View File

@ -25,7 +25,7 @@ class ExpenseRequest extends FormRequest
return [ return [
'expense_date' => 'required', 'expense_date' => 'required',
'expense_category_id' => 'required', 'expense_category_id' => 'required',
'amount' => 'required' 'amount' => 'required|digits_between:1,20'
]; ];
} }
} }

View File

@ -27,13 +27,22 @@ class InvoicesRequest extends FormRequest
'due_date' => 'required', 'due_date' => 'required',
'invoice_number' => 'required|unique:invoices,invoice_number', 'invoice_number' => 'required|unique:invoices,invoice_number',
'user_id' => 'required', 'user_id' => 'required',
'discount' => 'required', 'discount' => 'required|digits_between:1,20',
'discount_val' => 'required|digits_between:1,20',
'sub_total' => 'required|digits_between:1,20',
'total' => 'required|digits_between:1,20',
'tax' => 'required|digits_between:1,20',
'invoice_template_id' => 'required', 'invoice_template_id' => 'required',
'items' => 'required|array', 'items' => 'required|array',
'items.*' => 'required|max:255', 'items.*' => 'required|max:255',
'items.*.description' => 'max:255',
'items.*.name' => 'required', 'items.*.name' => 'required',
'items.*.quantity' => 'required|numeric', 'items.*.quantity' => 'required|digits_between:1,20',
'items.*.price' => 'required|numeric', 'items.*.price' => 'required|digits_between:1,20',
'items.*.discount' => 'digits_between:1,20',
'items.*.discount_val' => 'digits_between:1,20',
'items.*.tax' => 'digits_between:1,20',
'items.*.total' => 'digits_between:1,20',
]; ];
if ($this->getMethod() == 'PUT') { if ($this->getMethod() == 'PUT') {

View File

@ -24,7 +24,7 @@ class ItemsRequest extends FormRequest
{ {
return [ return [
'name' => 'required', 'name' => 'required',
'price' => 'required', 'price' => 'required|digits_between:1,20',
]; ];
} }
} }

View File

@ -26,7 +26,7 @@ class PaymentRequest extends FormRequest
'payment_date' => 'required', 'payment_date' => 'required',
'payment_number' => 'required|unique:payments,payment_number', 'payment_number' => 'required|unique:payments,payment_number',
'user_id' => 'required', 'user_id' => 'required',
'amount' => 'required', 'amount' => 'required|digits_between:1,20',
]; ];
if ($this->getMethod() == 'PUT') { if ($this->getMethod() == 'PUT') {

View File

@ -31,6 +31,8 @@ class ProfileRequest extends FormRequest
return [ return [
'name' => 'required', 'name' => 'required',
'password' => 'required', 'password' => 'required',
'address_street_1' => 'max:255',
'address_street_2' => 'max:255',
'email' => [ 'email' => [
'required', 'required',
'email', 'email',
@ -41,6 +43,8 @@ class ProfileRequest extends FormRequest
case 'PUT': case 'PUT':
return [ return [
'name' => 'required', 'name' => 'required',
'address_street_1' => 'max:255',
'address_street_2' => 'max:255',
'email' => 'required|email' 'email' => 'required|email'
]; ];
break; break;

View File

@ -113,6 +113,19 @@ class Invoice extends Model
return $this->belongsTo(InvoiceTemplate::class); return $this->belongsTo(InvoiceTemplate::class);
} }
public function getPreviousStatus()
{
if ($this->due_date < Carbon::now()) {
return self::STATUS_OVERDUE;
} elseif ($this->viewed) {
return self::STATUS_VIEWED;
} elseif ($this->sent) {
return self::STATUS_SENT;
} else {
return self::STATUS_DRAFT;
}
}
private function strposX($haystack, $needle, $number) private function strposX($haystack, $needle, $number)
{ {
if ($number == '1') { if ($number == '1') {

View File

@ -60,7 +60,7 @@ class InvoiceItem extends Model
$query->whereBetween( $query->whereBetween(
'invoice_date', 'invoice_date',
[$start->format('Y-m-d'), $end->format('Y-m-d')] [$start->format('Y-m-d'), $end->format('Y-m-d')]
)->where('paid_status', Invoice::STATUS_PAID); );
}); });
} }

View File

@ -0,0 +1,24 @@
<?php
namespace Laraspace\Listeners\Updates;
class Listener
{
const VERSION = '';
/**
* Check if should listen.
*
* @param $event
* @return boolean
*/
protected function check($event)
{
// Do not apply to the same or newer versions
// if (version_compare($event->old, static::VERSION, '>=')) {
// return false;
// }
return true;
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Laraspace\Listeners\Updates\V10;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Laraspace\Listeners\Updates\Listener;
use Laraspace\Events\UpdateFinished;
use Illuminate\Support\Facades\Artisan;
use Laraspace\Setting;
class Version101 extends Listener
{
const VERSION = '1.0.1';
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle(UpdateFinished $event)
{
// if (!$this->check($event)) {
// return;
// }
Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]);
Setting::getSetting('version', self::VERSION);
}
}

View File

@ -4,6 +4,8 @@ namespace Laraspace\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Laraspace\Events\UpdateFinished;
use Laraspace\Listeners\Updates\V10\Version101;
class EventServiceProvider extends ServiceProvider class EventServiceProvider extends ServiceProvider
{ {
@ -13,8 +15,8 @@ class EventServiceProvider extends ServiceProvider
* @var array * @var array
*/ */
protected $listen = [ protected $listen = [
'Laraspace\Events\SomeEvent' => [ UpdateFinished::class=> [
'Laraspace\Listeners\EventListener', Version101::class,
], ],
Registered::class => [ Registered::class => [
SendEmailVerificationNotification::class, SendEmailVerificationNotification::class,

View File

@ -49,12 +49,20 @@ class EnvironmentManager
'DB_PASSWORD='.$request->database_password."\n\n"; 'DB_PASSWORD='.$request->database_password."\n\n";
if (! $this->checkDatabaseConnection($request)) { if (! $this->checkDatabaseConnection($request)) {
return [ return [
'error' => 'connection_failed' 'error' => 'connection_failed'
]; ];
} else {
if(count(DB::connection()->select('SHOW TABLES'))) {
return [
'error' => 'database_should_be_empty'
];
}
} }
try { try {
file_put_contents($this->envPath, str_replace( file_put_contents($this->envPath, str_replace(
$oldDatabaseData, $oldDatabaseData,
$newDatabaseData, $newDatabaseData,
@ -101,7 +109,7 @@ class EnvironmentManager
'MAIL_USERNAME='.$request->mail_username."\n". 'MAIL_USERNAME='.$request->mail_username."\n".
'MAIL_PASSWORD='.$request->mail_password."\n". 'MAIL_PASSWORD='.$request->mail_password."\n".
'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n"; 'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n";
// dd($newMailData);
try { try {
file_put_contents($this->envPath, str_replace( file_put_contents($this->envPath, str_replace(

36
app/Space/SiteApi.php Normal file
View File

@ -0,0 +1,36 @@
<?php
namespace Laraspace\Space;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Laraspace\Setting;
trait SiteApi
{
protected static function getRemote($url, $data = array())
{
$base = 'http://crater-main.test/';
$client = new Client(['verify' => false, 'base_uri' => $base]);
$headers['headers'] = array(
'Accept' => 'application/json',
'Referer' => url('/'),
'crater' => Setting::getSetting('version')
);
$data['http_errors'] = false;
$data = array_merge($data, $headers);
try {
$result = $client->get($url, $data);
} catch (RequestException $e) {
$result = $e;
}
return $result;
}
}

110
app/Space/Updater.php Normal file
View File

@ -0,0 +1,110 @@
<?php
namespace Laraspace\Space;
use File;
use ZipArchive;
use Artisan;
use GuzzleHttp\Exception\RequestException;
use Laraspace\Space\SiteApi;
use Laraspace\Events\UpdateFinished;
use Laraspace\Setting;
class Updater
{
use SiteApi;
public static function update($installed, $version)
{
$data = null;
$path = null;
$url = '/download/'.$version;
$response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]);
// Exception
if ($response instanceof RequestException) {
return [
'success' => false,
'errors' => 'Download Exception',
'data' => [
'path' => $path
]
];
}
if ($response && ($response->getStatusCode() == 200)) {
$data = $response->getBody()->getContents();
}
// Create temp directory
$path = 'temp-' . md5(mt_rand());
$path2 = 'temp2-' . md5(mt_rand());
$temp_path = storage_path('app/temp') . '/' . $path;
$temp_path2 = storage_path('app/temp') . '/' . $path2;
if (!File::isDirectory($temp_path)) {
File::makeDirectory($temp_path);
File::makeDirectory($temp_path2);
}
$file = $temp_path . '/upload.zip';
// Add content to the Zip file
$uploaded = is_int(file_put_contents($file, $data)) ? true : false;
if (!$uploaded) {
return false;
}
// Unzip the file
$zip = new ZipArchive();
if ($zip->open($file)) {
$zip->extractTo($temp_path2);
}
$zip->close();
// Delete zip file
File::delete($file);
if (!File::copyDirectory($temp_path2.'/crater', base_path())) {
return false;
}
// Delete temp directory
File::deleteDirectory($temp_path);
File::deleteDirectory($temp_path2);
try {
event(new UpdateFinished($installed, $version));
return [
'success' => true,
'errors' => false,
'data' => []
];
} catch (\Exception $e) {
return [
'success' => false,
'errors' => 'Update error',
'data' => []
];
}
}
public static function checkForUpdate()
{
$data = null;
$url = '/check/latest/download/'.Setting::getSetting('version');
$response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]);
if ($response && ($response->getStatusCode() == 200)) {
$data = $response->getBody()->getContents();
}
return json_decode($data);
}
}

View File

@ -216,7 +216,7 @@ class User extends Authenticatable implements HasMedia
$query->whereBetween( $query->whereBetween(
'invoice_date', 'invoice_date',
[$start->format('Y-m-d'), $end->format('Y-m-d')] [$start->format('Y-m-d'), $end->format('Y-m-d')]
)->where('paid_status', Invoice::STATUS_PAID); );
}); });
} }

14
config/crater.php Normal file
View File

@ -0,0 +1,14 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Crater Requirements
|--------------------------------------------------------------------------
|
*/
'version' => '1.0.0',
];

View File

@ -18,7 +18,7 @@ class CreateItemsTable extends Migration
$table->string('name'); $table->string('name');
$table->string('description')->nullable(); $table->string('description')->nullable();
$table->string('unit')->nullable(); $table->string('unit')->nullable();
$table->integer('price'); $table->unsignedBigInteger('price');
$table->integer('company_id')->unsigned()->nullable(); $table->integer('company_id')->unsigned()->nullable();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->timestamps(); $table->timestamps();

View File

@ -24,13 +24,13 @@ class CreateInvoicesTable extends Migration
$table->string('tax_per_item'); $table->string('tax_per_item');
$table->string('discount_per_item'); $table->string('discount_per_item');
$table->text('notes')->nullable(); $table->text('notes')->nullable();
$table->decimal('discount', 15, 0)->nullable();
$table->string('discount_type')->nullable(); $table->string('discount_type')->nullable();
$table->integer('discount_val')->nullable(); $table->unsignedBigInteger('discount')->nullable();
$table->integer('sub_total'); $table->unsignedBigInteger('discount_val')->nullable();
$table->integer('total'); $table->unsignedBigInteger('sub_total');
$table->integer('tax'); $table->unsignedBigInteger('total');
$table->integer('due_amount'); $table->unsignedBigInteger('tax');
$table->unsignedBigInteger('due_amount');
$table->boolean('sent')->default(false); $table->boolean('sent')->default(false);
$table->boolean('viewed')->default(false); $table->boolean('viewed')->default(false);
$table->string('unique_hash')->nullable(); $table->string('unique_hash')->nullable();

View File

@ -17,13 +17,13 @@ class CreateInvoiceItemsTable extends Migration
$table->increments('id'); $table->increments('id');
$table->string('name'); $table->string('name');
$table->string('description')->nullable(); $table->string('description')->nullable();
$table->integer('quantity');
$table->integer('price');
$table->string('discount_type'); $table->string('discount_type');
$table->integer('discount_val'); $table->unsignedBigInteger('quantity');
$table->decimal('discount', 15, 0); $table->unsignedBigInteger('price');
$table->integer('tax'); $table->unsignedBigInteger('discount_val');
$table->integer('total'); $table->unsignedBigInteger('discount');
$table->unsignedBigInteger('tax');
$table->unsignedBigInteger('total');
$table->integer('invoice_id')->unsigned(); $table->integer('invoice_id')->unsigned();
$table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade'); $table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
$table->integer('item_id')->unsigned()->nullable(); $table->integer('item_id')->unsigned()->nullable();

View File

@ -23,12 +23,12 @@ class CreateEstimatesTable extends Migration
$table->string('tax_per_item'); $table->string('tax_per_item');
$table->string('discount_per_item'); $table->string('discount_per_item');
$table->string('notes')->nullable(); $table->string('notes')->nullable();
$table->decimal('discount', 15, 0)->nullable();
$table->string('discount_type')->nullable(); $table->string('discount_type')->nullable();
$table->integer('discount_val')->nullable(); $table->unsignedBigInteger('discount')->nullable();
$table->integer('sub_total'); $table->unsignedBigInteger('discount_val')->nullable();
$table->integer('total'); $table->unsignedBigInteger('sub_total');
$table->integer('tax'); $table->unsignedBigInteger('total');
$table->unsignedBigInteger('tax');
$table->string('unique_hash')->nullable(); $table->string('unique_hash')->nullable();
$table->integer('user_id')->unsigned()->nullable(); $table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

View File

@ -17,13 +17,13 @@ class CreateEstimateItemsTable extends Migration
$table->increments('id'); $table->increments('id');
$table->string('name'); $table->string('name');
$table->string('description')->nullable(); $table->string('description')->nullable();
$table->integer('quantity');
$table->string('discount_type'); $table->string('discount_type');
$table->decimal('discount', 15, 0); $table->unsignedBigInteger('quantity');
$table->integer('discount_val'); $table->unsignedBigInteger('discount');
$table->integer('price'); $table->unsignedBigInteger('discount_val');
$table->integer('tax'); $table->unsignedBigInteger('price');
$table->integer('total'); $table->unsignedBigInteger('tax');
$table->unsignedBigInteger('total');
$table->integer('item_id')->unsigned()->nullable(); $table->integer('item_id')->unsigned()->nullable();
$table->foreign('item_id')->references('id')->on('items')->onDelete('cascade'); $table->foreign('item_id')->references('id')->on('items')->onDelete('cascade');
$table->integer('estimate_id')->unsigned(); $table->integer('estimate_id')->unsigned();

View File

@ -17,7 +17,7 @@ class CreateExpensesTable extends Migration
$table->increments('id'); $table->increments('id');
$table->date('expense_date'); $table->date('expense_date');
$table->string('attachment_receipt')->nullable(); $table->string('attachment_receipt')->nullable();
$table->integer('amount'); $table->unsignedBigInteger('amount');
$table->string('notes')->nullable(); $table->string('notes')->nullable();
$table->integer('expense_category_id')->unsigned(); $table->integer('expense_category_id')->unsigned();
$table->foreign('expense_category_id')->references('id')->on('expense_categories')->onDelete('cascade'); $table->foreign('expense_category_id')->references('id')->on('expense_categories')->onDelete('cascade');

View File

@ -19,7 +19,7 @@ class CreatePaymentsTable extends Migration
$table->string('payment_mode')->nullable(); $table->string('payment_mode')->nullable();
$table->date('payment_date'); $table->date('payment_date');
$table->text('notes')->nullable(); $table->text('notes')->nullable();
$table->decimal('amount', 15, 0); $table->unsignedBigInteger('amount');
$table->integer('user_id')->unsigned(); $table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('invoice_id')->unsigned()->nullable(); $table->integer('invoice_id')->unsigned()->nullable();

View File

@ -30,7 +30,7 @@ class CreateTaxesTable extends Migration
$table->integer('company_id')->unsigned()->nullable(); $table->integer('company_id')->unsigned()->nullable();
$table->foreign('company_id')->references('id')->on('companies'); $table->foreign('company_id')->references('id')->on('companies');
$table->string('name'); $table->string('name');
$table->decimal('amount', 15, 0); $table->unsignedBigInteger('amount');
$table->decimal('percent', 5, 2); $table->decimal('percent', 5, 2);
$table->tinyInteger('compound_tax')->default(0); $table->tinyInteger('compound_tax')->default(0);
$table->timestamps(); $table->timestamps();

View File

@ -13,19 +13,19 @@ class EstimateTemplateSeeder extends Seeder
public function run() public function run()
{ {
EstimateTemplate::create([ EstimateTemplate::create([
'name' => 'Estimate Template1', 'name' => 'Template 1',
'view' => 'estimate1', 'view' => 'estimate1',
'path' => '/assets/img/PDF/Template1.png' 'path' => '/assets/img/PDF/Template1.png'
]); ]);
EstimateTemplate::create([ EstimateTemplate::create([
'name' => 'Estimate Template2', 'name' => 'Template 2',
'view' => 'estimate2', 'view' => 'estimate2',
'path' => '/assets/img/PDF/Template2.png' 'path' => '/assets/img/PDF/Template2.png'
]); ]);
EstimateTemplate::create([ EstimateTemplate::create([
'name' => 'Estimate Template3', 'name' => 'Template 3',
'view' => 'estimate3', 'view' => 'estimate3',
'path' => '/assets/img/PDF/Template3.png' 'path' => '/assets/img/PDF/Template3.png'
]); ]);

View File

@ -13,19 +13,19 @@ class InvoiceTemplateSeeder extends Seeder
public function run() public function run()
{ {
InvoiceTemplate::create([ InvoiceTemplate::create([
'name' => 'Invoice Template1', 'name' => 'Template 1',
'view' => 'invoice1', 'view' => 'invoice1',
'path' => '/assets/img/PDF/Template1.png' 'path' => '/assets/img/PDF/Template1.png'
]); ]);
InvoiceTemplate::create([ InvoiceTemplate::create([
'name' => 'Invoice Template2', 'name' => ' Template 2',
'view' => 'invoice2', 'view' => 'invoice2',
'path' => '/assets/img/PDF/Template2.png' 'path' => '/assets/img/PDF/Template2.png'
]); ]);
InvoiceTemplate::create([ InvoiceTemplate::create([
'name' => 'Invoice Template3', 'name' => 'Template 3',
'view' => 'invoice3', 'view' => 'invoice3',
'path' => '/assets/img/PDF/Template3.png' 'path' => '/assets/img/PDF/Template3.png'
]); ]);

View File

@ -1,9 +1,29 @@
<template> <template>
<button :type="type" :class="btnClass" :disabled="disabled" @click="handleClick"> <button
<font-awesome-icon v-if="icon && !loading && !rightIcon" :class="iconClass" :icon="icon" class="vue-icon icon-left" /> :type="type"
<font-awesome-icon v-if="loading" :class="iconClass" icon="spinner" class="fa-spin"/> :class="btnClass"
:disabled="disabled || loading"
@click="handleClick"
>
<font-awesome-icon
v-if="icon && !loading && !rightIcon"
:class="iconClass"
:icon="icon"
class="vue-icon icon-left"
/>
<font-awesome-icon
v-if="loading"
:class="iconClass"
icon="spinner"
class="fa-spin"
/>
<slot /> <slot />
<font-awesome-icon v-if="icon && !loading && rightIcon" :class="iconClass" :icon="icon" class="vue-icon icon-right" /> <font-awesome-icon
v-if="icon && !loading && rightIcon"
:class="iconClass"
:icon="icon"
class="vue-icon icon-right"
/>
</button> </button>
</template> </template>

View File

@ -4,7 +4,7 @@
<input <input
ref="baseInput" ref="baseInput"
v-model="inputValue" v-model="inputValue"
:type="type" :type="toggleType"
:disabled="disabled" :disabled="disabled"
:readonly="readOnly" :readonly="readOnly"
:name="name" :name="name"
@ -19,6 +19,9 @@
@keydown="handleKeyDownEnter" @keydown="handleKeyDownEnter"
@blur="handleFocusOut" @blur="handleFocusOut"
> >
<div v-if="showPassword && isAlignLeftIcon" style="cursor: pointer" @click="showPass = !showPass" >
<font-awesome-icon :icon="!showPass ?'eye-slash': 'eye'" class="right-icon" />
</div>
<font-awesome-icon v-if="icon && !isAlignLeftIcon" :icon="icon" class="right-icon" /> <font-awesome-icon v-if="icon && !isAlignLeftIcon" :icon="icon" class="right-icon" />
</div> </div>
</template> </template>
@ -77,12 +80,17 @@ export default {
autocomplete: { autocomplete: {
type: String, type: String,
default: 'on' default: 'on'
},
showPassword: {
type: Boolean,
default: false
} }
}, },
data () { data () {
return { return {
inputValue: this.value, inputValue: this.value,
focus: false focus: false,
showPass: false
} }
}, },
computed: { computed: {
@ -94,6 +102,12 @@ export default {
return true return true
} }
return false return false
},
toggleType () {
if (this.showPass) {
return 'text'
}
return this.type
} }
}, },
watch: { watch: {

View File

@ -3,7 +3,7 @@
<form action="" @submit.prevent="submitCategoryData"> <form action="" @submit.prevent="submitCategoryData">
<div class="card-body"> <div class="card-body">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('expenses.category') }}<span class="required text-danger">*</span></label> <label class="col-sm-4 col-form-label input-label">{{ $t('expenses.category') }}<span class="required text-danger">*</span></label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
ref="name" ref="name"

View File

@ -7,7 +7,7 @@
<tab id="basic-home" :name="$t('customers.basic_info')"> <tab id="basic-home" :name="$t('customers.basic_info')">
<div class="basic-info"> <div class="basic-info">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.display_name') }} <span class="required">*</span></label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.display_name') }} <span class="required">*</span></label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
ref="name" ref="name"
@ -25,7 +25,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.primary_display_name') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.primary_display_name') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="formData.contact_name" v-model="formData.contact_name"
@ -34,7 +34,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('login.email') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('login.email') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
:invalid="$v.formData.email.$error" :invalid="$v.formData.email.$error"
@ -49,7 +49,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $tc('settings.currencies.currency') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $tc('settings.currencies.currency') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="currency" v-model="currency"
@ -64,7 +64,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.phone') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.phone') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
:invalid="$v.formData.phone.$error" :invalid="$v.formData.phone.$error"
@ -79,7 +79,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.website') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.website') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="formData.website" v-model="formData.website"
@ -100,7 +100,7 @@
<tab id="basic-profile" :name="$t('customers.billing_address')"> <tab id="basic-profile" :name="$t('customers.billing_address')">
<div class="basic-info"> <div class="basic-info">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.name') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.name') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="billing.name" v-model="billing.name"
@ -110,7 +110,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.phone') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.phone') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
:invalid="$v.billing.phone.$error" :invalid="$v.billing.phone.$error"
@ -126,7 +126,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.address') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.address') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-text-area <base-text-area
v-model="billing.address_street_1" v-model="billing.address_street_1"
@ -155,7 +155,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.country') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.country') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="billingCountry" v-model="billingCountry"
@ -171,7 +171,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.state') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.state') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="billingState" v-model="billingState"
@ -187,7 +187,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.city') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.city') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="billingCity" v-model="billingCity"
@ -213,7 +213,7 @@
</div> --> </div> -->
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.zip_code') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.zip_code') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="billing.zip" v-model="billing.zip"
@ -236,7 +236,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.name') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.name') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="shipping.name" v-model="shipping.name"
@ -246,7 +246,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.phone') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.phone') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
:invalid="$v.shipping.phone.$error" :invalid="$v.shipping.phone.$error"
@ -262,7 +262,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.address') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.address') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-text-area <base-text-area
v-model="shipping.address_street_1" v-model="shipping.address_street_1"
@ -291,7 +291,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.country') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.country') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="shippingCountry" v-model="shippingCountry"
@ -307,7 +307,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.state') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.state') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="shippingState" v-model="shippingState"
@ -323,7 +323,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.city') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.city') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="shippingCity" v-model="shippingCity"
@ -339,7 +339,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.zip_code') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.zip_code') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="shipping.zip" v-model="shipping.zip"

View File

@ -3,7 +3,7 @@
<form action="" @submit.prevent="submitItemData"> <form action="" @submit.prevent="submitItemData">
<div class="card-body"> <div class="card-body">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label"> <label class="col-sm-4 col-form-label input-label">
{{ $t('items.name') }}<span class="required">*</span> {{ $t('items.name') }}<span class="required">*</span>
</label> </label>
<div class="col-sm-7"> <div class="col-sm-7">
@ -22,7 +22,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('items.price') }}<span class="required">*</span></label> <label class="col-sm-4 col-form-label input-label">{{ $t('items.price') }}<span class="required">*</span></label>
<div class="col-sm-7"> <div class="col-sm-7">
<div class="base-input"> <div class="base-input">
<money <money
@ -41,7 +41,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('items.unit') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('items.unit') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="formData.unit" v-model="formData.unit"
@ -54,7 +54,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('items.description') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('items.description') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-text-area <base-text-area
v-model="formData.description" v-model="formData.description"
@ -121,7 +121,8 @@ export default {
{ name: 'kg', value: 'kg' }, { name: 'kg', value: 'kg' },
{ name: 'km', value: 'km' }, { name: 'km', value: 'km' },
{ name: 'lb', value: 'lb' }, { name: 'lb', value: 'lb' },
{ name: 'mg', value: 'mg' } { name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
], ],
formData: { formData: {
name: null, name: null,

View File

@ -611,8 +611,6 @@ export default {
estimate_viewed_desc: 'When your customer views the estimate sent via crater dashboard.', estimate_viewed_desc: 'When your customer views the estimate sent via crater dashboard.',
save: 'Save', save: 'Save',
email_save_message: 'Email saved successfully', email_save_message: 'Email saved successfully',
// invoice_viewed_message: 'Invoice viewed updated successfully',
// estimate_viewed_message: 'Estimate viewed updated successfully',
please_enter_email: 'Please Enter Email' please_enter_email: 'Please Enter Email'
}, },
tax_types: { tax_types: {
@ -622,7 +620,6 @@ export default {
add_new_tax: 'Add New Tax', add_new_tax: 'Add New Tax',
tax_settings: 'Tax Settings', tax_settings: 'Tax Settings',
tax_per_item: 'Tax Per Item', tax_per_item: 'Tax Per Item',
// tax_per_item_switch: 'Tax Per Item updated successfully',
tax_name: 'Tax Name', tax_name: 'Tax Name',
compound_tax: 'Compound Tax', compound_tax: 'Compound Tax',
percent: 'Percent', percent: 'Percent',
@ -660,7 +657,6 @@ export default {
preference: 'Preference | Preferences', preference: 'Preference | Preferences',
general_settings: 'Default preferences for the system.', general_settings: 'Default preferences for the system.',
updated_message: 'Preferences updated successfully', updated_message: 'Preferences updated successfully',
// set_discount_per_item_message: 'Discount set per item updated successfully',
select_language: 'select language', select_language: 'select language',
select_time_zone: 'select Time Zone', select_time_zone: 'select Time Zone',
select_date_formate: 'select Date Formate', select_date_formate: 'select Date Formate',
@ -740,7 +736,8 @@ export default {
migrate_failed: 'Migrate Failed', migrate_failed: 'Migrate Failed',
database_variables_save_error: 'Unable to connect to the DB with Provided Values.', database_variables_save_error: 'Unable to connect to the DB with Provided Values.',
mail_variables_save_error: 'Email configuration failed.', mail_variables_save_error: 'Email configuration failed.',
connection_failed: 'Database Connection Failed' connection_failed: 'Database connection failed',
database_should_be_empty: 'Database should be empty'
}, },
success: { success: {
mail_variables_save_successfully: 'Email configured successfully', mail_variables_save_successfully: 'Email configured successfully',

View File

@ -529,7 +529,8 @@ export default {
preferences: 'Preferencias', preferences: 'Preferencias',
notifications: 'Notificaciones', notifications: 'Notificaciones',
tax_types: 'Tipos de impuestos', tax_types: 'Tipos de impuestos',
expense_category: 'Categorías de gastos' expense_category: 'Categorías de gastos',
update_app: 'Actualizar aplicación'
}, },
title: 'Configuraciones', title: 'Configuraciones',
setting: 'Configuraciones | Configuraciones', setting: 'Configuraciones | Configuraciones',
@ -661,6 +662,11 @@ export default {
select_time_zone: 'selecciona la zona horaria', select_time_zone: 'selecciona la zona horaria',
select_date_formate: 'seleccione formato de fecha', select_date_formate: 'seleccione formato de fecha',
select_financial_year: 'seleccione año financiero' select_financial_year: 'seleccione año financiero'
},
update_app: {
title: 'Actualizar aplicación',
description: 'actualizar la descripción de la aplicación',
update: 'Actualizar'
} }
}, },
wizard: { wizard: {

View File

@ -529,7 +529,8 @@ export default {
preferences: 'Préférences', preferences: 'Préférences',
notifications: 'Les notifications', notifications: 'Les notifications',
tax_types: 'Types de taxe', tax_types: 'Types de taxe',
expense_category: 'Catégories de dépenses' expense_category: 'Catégories de dépenses',
update_app: "Mise à jour de l'application"
}, },
title: 'Paramètres', title: 'Paramètres',
setting: 'Paramètres | Paramètres', setting: 'Paramètres | Paramètres',
@ -664,6 +665,11 @@ export default {
select_time_zone: 'sélectionnez le fuseau horaire', select_time_zone: 'sélectionnez le fuseau horaire',
select_date_formate: 'sélectionnez Date Formate', select_date_formate: 'sélectionnez Date Formate',
select_financial_year: 'sélectionner lexercice' select_financial_year: 'sélectionner lexercice'
},
update_app: {
title: "Mise à jour de l'application",
description: "mettre à jour la description de l'application",
update: 'Mise à jour'
} }
}, },
wizard: { wizard: {

View File

@ -168,7 +168,7 @@
> >
<table-column :label="$t('dashboard.recent_invoices_card.due_on')" show="formattedDueDate" /> <table-column :label="$t('dashboard.recent_invoices_card.due_on')" show="formattedDueDate" />
<table-column :label="$t('dashboard.recent_invoices_card.customer')" show="user.name" /> <table-column :label="$t('dashboard.recent_invoices_card.customer')" show="user.name" />
<table-column :label="$t('dashboard.recent_invoices_card.amount_due')" sort-as="due_amount"> <table-column :label="$t('dashboard.recent_invoices_card.amount_due')" show="due_amount" sort-as="due_amount">
<template slot-scope="row"> <template slot-scope="row">
<span>{{ $t('dashboard.recent_invoices_card.amount_due') }}</span> <span>{{ $t('dashboard.recent_invoices_card.amount_due') }}</span>
<div v-html="$utils.formatMoney(row.due_amount, row.user.currency)"/> <div v-html="$utils.formatMoney(row.due_amount, row.user.currency)"/>
@ -242,7 +242,7 @@
> >
<table-column :label="$t('dashboard.recent_estimate_card.date')" show="formattedExpiryDate" /> <table-column :label="$t('dashboard.recent_estimate_card.date')" show="formattedExpiryDate" />
<table-column :label="$t('dashboard.recent_estimate_card.customer')" show="user.name" /> <table-column :label="$t('dashboard.recent_estimate_card.customer')" show="user.name" />
<table-column :label="$t('dashboard.recent_estimate_card.amount_due')" sort-as="total"> <table-column :label="$t('dashboard.recent_estimate_card.amount_due')" show="total" sort-as="total">
<template slot-scope="row"> <template slot-scope="row">
<span>{{ $t('dashboard.recent_estimate_card.amount_due') }}</span> <span>{{ $t('dashboard.recent_estimate_card.amount_due') }}</span>
<div v-html="$utils.formatMoney(row.total, row.user.currency)"/> <div v-html="$utils.formatMoney(row.total, row.user.currency)"/>

View File

@ -553,6 +553,8 @@ export default {
if (response.data) { if (response.data) {
this.selectCustomer(response.data.estimate.user_id) this.selectCustomer(response.data.estimate.user_id)
this.newEstimate = response.data.estimate this.newEstimate = response.data.estimate
this.newEstimate.estimate_date = moment(response.data.estimate.estimate_date, 'YYYY-MM-DD').toString()
this.newEstimate.expiry_date = moment(response.data.estimate.expiry_date, 'YYYY-MM-DD').toString()
this.discountPerItem = response.data.discount_per_item this.discountPerItem = response.data.discount_per_item
this.taxPerItem = response.data.tax_per_item this.taxPerItem = response.data.tax_per_item
this.selectedCurrency = this.defaultCurrency this.selectedCurrency = this.defaultCurrency

View File

@ -554,6 +554,8 @@ export default {
if (response.data) { if (response.data) {
this.selectCustomer(response.data.invoice.user_id) this.selectCustomer(response.data.invoice.user_id)
this.newInvoice = response.data.invoice this.newInvoice = response.data.invoice
this.newInvoice.invoice_date = moment(response.data.invoice.invoice_date, 'YYYY-MM-DD').toString()
this.newInvoice.due_date = moment(response.data.invoice.due_date, 'YYYY-MM-DD').toString()
this.discountPerItem = response.data.discount_per_item this.discountPerItem = response.data.discount_per_item
this.taxPerItem = response.data.tax_per_item this.taxPerItem = response.data.tax_per_item
this.selectedCurrency = this.defaultCurrency this.selectedCurrency = this.defaultCurrency

View File

@ -112,7 +112,8 @@ export default {
{ name: 'kg', value: 'kg' }, { name: 'kg', value: 'kg' },
{ name: 'km', value: 'km' }, { name: 'km', value: 'km' },
{ name: 'lb', value: 'lb' }, { name: 'lb', value: 'lb' },
{ name: 'mg', value: 'mg' } { name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
], ],
formData: { formData: {
name: '', name: '',

View File

@ -245,7 +245,8 @@ export default {
{ name: 'kg', value: 'kg' }, { name: 'kg', value: 'kg' },
{ name: 'km', value: 'km' }, { name: 'km', value: 'km' },
{ name: 'lb', value: 'lb' }, { name: 'lb', value: 'lb' },
{ name: 'mg', value: 'mg' } { name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
], ],
isRequestOngoing: true, isRequestOngoing: true,
filtersApplied: false, filtersApplied: false,

View File

@ -66,8 +66,9 @@
<base-input <base-input
:invalid="$v.mailConfigData.mail_password.$error" :invalid="$v.mailConfigData.mail_password.$error"
v-model.trim="mailConfigData.mail_password" v-model.trim="mailConfigData.mail_password"
type="mail_password" type="password"
name="name" name="name"
show-password
@input="$v.mailConfigData.mail_password.$touch()" @input="$v.mailConfigData.mail_password.$touch()"
/> />
<div v-if="$v.mailConfigData.mail_password.$error"> <div v-if="$v.mailConfigData.mail_password.$error">
@ -141,12 +142,12 @@ export default {
data () { data () {
return { return {
mailConfigData: { mailConfigData: {
mail_driver: 'smtp', mail_driver: '',
mail_host: 'mailtrap.io', mail_host: '',
mail_port: 2525, mail_port: null,
mail_username: 'cc3c64516febd4', mail_username: '',
mail_password: 'e6a0176301f587', mail_password: '',
mail_encryption: 'tls' mail_encryption: ''
}, },
loading: false, loading: false,
mail_drivers: [] mail_drivers: []
@ -176,18 +177,22 @@ export default {
} }
}, },
mounted () { mounted () {
// this.getMailDrivers() this.loadData()
}, },
methods: { methods: {
async getMailDrivers () { async loadData () {
this.loading = true this.loading = true
let response = await window.axios.get('/api/admin/onboarding/environment/mail') let mailDrivers = await window.axios.get('/api/settings/environment/mail')
let mailData = await window.axios.get('/api/settings/environment/mail-env')
if (response.data) { if (mailDrivers.data) {
this.mail_drivers = response.data this.mail_drivers = mailDrivers.data
this.loading = false
} }
if (mailData.data) {
this.mailConfigData = mailData.data
}
this.loading = false
}, },
async saveEmailConfig () { async saveEmailConfig () {
this.$v.mailConfigData.$touch() this.$v.mailConfigData.$touch()
@ -196,7 +201,7 @@ export default {
} }
this.loading = true this.loading = true
try { try {
let response = await window.axios.post('/api/admin/onboarding/environment/mail', this.mailConfigData) let response = await window.axios.post('/api/settings/environment/mail', this.mailConfigData)
if (response.data.success) { if (response.data.success) {
window.toastr['success'](this.$t('wizard.success.' + response.data.success)) window.toastr['success'](this.$t('wizard.success.' + response.data.success))
} else { } else {

View File

@ -97,7 +97,6 @@
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label">{{ $t('wizard.database.password') }}</label> <label class="form-label">{{ $t('wizard.database.password') }}</label>
<span class="text-danger"> *</span>
<base-input <base-input
v-model.trim="databaseData.database_password" v-model.trim="databaseData.database_password"
type="password" type="password"
@ -154,7 +153,7 @@ export default {
database_name: null, database_name: null,
database_username: null, database_username: null,
database_password: null, database_password: null,
app_url: null app_url: window.location.origin
}, },
loading: false, loading: false,
connections: [ connections: [
@ -207,8 +206,8 @@ export default {
} }
this.loading = false this.loading = false
} catch (e) { } catch (e) {
console.log(e) console.log(e.response)
window.toastr['error']('Something went wrong') window.toastr['error'](e.response.data.message)
} }
} }
} }

View File

@ -61,7 +61,8 @@
<base-input <base-input
:invalid="$v.mailConfigData.mail_password.$error" :invalid="$v.mailConfigData.mail_password.$error"
v-model.trim="mailConfigData.mail_password" v-model.trim="mailConfigData.mail_password"
type="mail_password" type="password"
show-password
name="name" name="name"
@input="$v.mailConfigData.mail_password.$touch()" @input="$v.mailConfigData.mail_password.$touch()"
/> />

View File

@ -67,8 +67,8 @@ export default {
data () { data () {
return { return {
loading: false, loading: false,
tab: 'step_1', tab: 'step_3',
step: 1 step: 3
} }
}, },
created () { created () {

View File

@ -35,7 +35,7 @@
</div> </div>
</div> </div>
<base-button <base-button
v-if="requirements" v-if="hasNext"
:loading="loading" :loading="loading"
class="pull-right mt-4" class="pull-right mt-4"
icon="arrow-right" icon="arrow-right"
@ -46,7 +46,7 @@
{{ $t('wizard.continue') }} {{ $t('wizard.continue') }}
</base-button> </base-button>
<base-button <base-button
v-else v-if="!requirements"
:loading="loading" :loading="loading"
class="pull-right mt-4" class="pull-right mt-4"
color="theme" color="theme"
@ -74,6 +74,20 @@ export default {
isShow: true isShow: true
} }
}, },
computed: {
hasNext () {
if (this.requirements) {
let isRequired = true
for (const key in this.requirements) {
if (!this.requirements[key]) {
isRequired = false
}
}
return this.requirements && this.phpSupportInfo.supported && isRequired
}
return false
}
},
methods: { methods: {
listToggle () { listToggle () {
this.isShow = !this.isShow this.isShow = !this.isShow

View File

@ -51,6 +51,7 @@ import {
faEllipsisH, faEllipsisH,
faCopy, faCopy,
faPaperPlane, faPaperPlane,
faEyeSlash,
faSyncAlt faSyncAlt
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons' import { far } from '@fortawesome/free-regular-svg-icons'
@ -109,6 +110,7 @@ library.add(
faFilePdf, faFilePdf,
faEnvelope, faEnvelope,
faEye, faEye,
faEyeSlash,
faShare, faShare,
faEllipsisH, faEllipsisH,
faCopy, faCopy,

View File

@ -19,3 +19,19 @@
} }
} }
@media(max-width: $x-small-breakpoint ) {
.base-modal {
.category-modal {
.input-label {
text-align: left;
}
}
}
}

View File

@ -34,3 +34,20 @@
} }
} }
@media(max-width: $x-small-breakpoint ) {
.base-modal {
.customer-modal {
.input-label {
text-align: left;
}
}
}
}

View File

@ -19,3 +19,20 @@
} }
} }
@media(max-width: $x-small-breakpoint ) {
.base-modal {
.item-modal {
.input-label {
text-align: left;
}
}
}
}

View File

@ -58,6 +58,7 @@
.content { .content {
display: flex; display: flex;
flex:1;
flex-direction: column; flex-direction: column;
label { label {
@ -445,6 +446,9 @@
.estimate-amount { .estimate-amount {
font-size: 18px; font-size: 18px;
color: #55547A; color: #55547A;
display: flex;
justify-content: center;
align-items: center;
} }
.total { .total {
@ -491,7 +495,6 @@
font-weight: 300; font-weight: 300;
font-size: 12px; font-size: 12px;
padding-top: 2px; padding-top: 2px;
padding-left: 10px;
textarea { textarea {

View File

@ -58,6 +58,7 @@
.content { .content {
display: flex; display: flex;
flex: 1;
flex-direction: column; flex-direction: column;
label { label {
@ -445,6 +446,9 @@
.invoice-amount { .invoice-amount {
font-size: 18px; font-size: 18px;
color: #55547A; color: #55547A;
display: flex;
justify-content: center;
align-items: center;
} }
.total { .total {

View File

@ -263,7 +263,7 @@
} }
tr.main-table-header th { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 0.620315px solid #E8E8E8;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 12px; font-size: 12px;

View File

@ -264,7 +264,7 @@
} }
tr.main-table-header th { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 0.620315px solid #E8E8E8;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 12px; font-size: 12px;

View File

@ -1,6 +1,8 @@
<div class="notes"> @if ($estimate->notes != '' && $estimate->notes != null)
<div class="notes-label"> <div class="notes">
Notes <div class="notes-label">
Notes
</div>
{{$estimate->notes}}
</div> </div>
{{$estimate->notes}} @endif
</div>

View File

@ -1,27 +1,32 @@
<table width="100%" class="table2" cellspacing="0" border="0"> <table width="100%" class="table2" cellspacing="0" border="0">
<tr class="main-table-header"> <tr class="main-table-header">
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">#</th>
@if($estimate->discount_per_item === 'NO') @if($estimate->discount_per_item === 'NO')
<th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> <th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
@else @else
<th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> <th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
@endif @endif
<th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th> <th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th>
<th width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</th> <th width="18%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 40px">Price</th>
@if($estimate->discount_per_item === 'YES') @if($estimate->discount_per_item === 'YES')
<th width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</th> <th width="10%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-left: 10px">Discount</th>
@endif @endif
<th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th> <th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th>
</tr> </tr>
@php
$index = 1
@endphp
@foreach ($estimate->items as $item) @foreach ($estimate->items as $item)
<tr class="item-details"> <tr class="item-details">
<td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px; vertical-align: top;">{{$index}}</td>
<td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px"> <td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px">
<span>{{ $item->name }}</span><br> <span>{{ $item->name }}</span><br>
<span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span> <span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span>
</td> </td>
<td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td>
<td class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 40px">{{$item->price/100}}</td>
@if($estimate->discount_per_item === 'YES') @if($estimate->discount_per_item === 'YES')
<td class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px"> <td class="inv-item items" style="text-align: right; color: #040405; padding-left: 10px">
@if($item->discount_type === 'fixed') @if($item->discount_type === 'fixed')
{{$item->discount_val/100}} {{$item->discount_val/100}}
@endif @endif
@ -30,12 +35,15 @@
@endif @endif
</td> </td>
@endif @endif
<td class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td> <td class="inv-item items" style="text-align: right; color: #040405;">{{$item->total/100}}</td>
</tr> </tr>
@php
$index += 1
@endphp
@endforeach @endforeach
</table> </table>
<table width="100%" style="margin-left:420px" cellspacing="0px" border="0" class="table3"> <table width="100%" cellspacing="0px" style="margin-left:420px" border="0" class="table3 @if(count($estimate->items) > 12) page-break @endif">
<tr> <tr>
<td class="no-borde" style="color: #55547A; padding-left:10px; font-size:12px;">Subtotal</td> <td class="no-borde" style="color: #55547A; padding-left:10px; font-size:12px;">Subtotal</td>
<td class="no-border items" <td class="no-border items"

View File

@ -11,6 +11,7 @@
html { html {
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
margin-top: 50px;
} }
table { table {
@ -35,7 +36,7 @@
width: 100%; width: 100%;
height: 90px; height: 90px;
left: 0px; left: 0px;
top: 0px; top: -50px;
} }
.header-logo { .header-logo {
@ -71,7 +72,7 @@
.wrapper { .wrapper {
display: block; display: block;
padding-top: 60px; padding-top: 16px;
padding-bottom: 60px; padding-bottom: 60px;
} }
@ -251,6 +252,7 @@
page-break-after: auto; page-break-after: auto;
} }
.table2 hr { .table2 hr {
height:0.1px; height:0.1px;
} }
@ -263,7 +265,7 @@
} }
tr.main-table-header th { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 0.620315px solid #E8E8E8;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 12px; font-size: 12px;
@ -380,8 +382,8 @@
</td> </td>
</tr> </tr>
</table> </table>
<hr class="header-line" style="border: 0.620315px solid #E8E8E8;"/>
</div> </div>
<hr class="header-line" />
<div class="wrapper"> <div class="wrapper">
<div class="address"> <div class="address">
<div class="company"> <div class="company">

View File

@ -264,7 +264,7 @@
} }
tr.main-table-header th { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 0.620315px solid #E8E8E8;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 12px; font-size: 12px;

View File

@ -1,6 +1,8 @@
<div class="notes"> @if ($invoice->notes != '' && $invoice->notes != null)
<div class="notes-label"> <div class="notes">
Notes <div class="notes-label">
Notes
</div>
{{$invoice->notes}}
</div> </div>
{{$invoice->notes}} @endif
</div>

View File

@ -1,27 +1,32 @@
<table width="100%" class="table2" cellspacing="0" border="0"> <table width="100%" class="table2" cellspacing="0" border="0">
<tr class="main-table-header"> <tr class="main-table-header">
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">#</th>
@if($invoice->discount_per_item === 'NO') @if($invoice->discount_per_item === 'NO')
<th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> <th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
@else @else
<th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> <th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
@endif @endif
<th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th> <th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th>
<th width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</th> <th width="18%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 40px">Price</th>
@if($invoice->discount_per_item === 'YES') @if($invoice->discount_per_item === 'YES')
<th width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</th> <th width="10%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-left: 10px">Discount</th>
@endif @endif
<th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th> <th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th>
</tr> </tr>
@php
$index = 1
@endphp
@foreach ($invoice->items as $item) @foreach ($invoice->items as $item)
<tr class="item-details"> <tr class="item-details">
<td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px; vertical-align: top;">{{$index}}</td>
<td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px"> <td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px">
<span>{{ $item->name }}</span><br> <span>{{ $item->name }}</span><br>
<span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span> <span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span>
</td> </td>
<td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td>
<td class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 40px">{{$item->price/100}}</td>
@if($invoice->discount_per_item === 'YES') @if($invoice->discount_per_item === 'YES')
<td class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px"> <td class="inv-item items" style="text-align: right; color: #040405; padding-left: 10px">
@if($item->discount_type === 'fixed') @if($item->discount_type === 'fixed')
{{$item->discount_val/100}} {{$item->discount_val/100}}
@endif @endif
@ -30,8 +35,11 @@
@endif @endif
</td> </td>
@endif @endif
<td class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td> <td class="inv-item items" style="text-align: right; color: #040405;">{{$item->total/100}}</td>
</tr> </tr>
@php
$index += 1
@endphp
@endforeach @endforeach
</table> </table>

View File

@ -106,6 +106,8 @@ Route::group(['middleware' => 'redirect-if-installed'], function () {
'uses' => 'OnboardingController@companySettings' 'uses' => 'OnboardingController@companySettings'
]); ]);
}); });
// App version // App version
// ---------------------------------- // ----------------------------------
@ -120,6 +122,18 @@ Route::group(['middleware' => 'api'], function () {
'middleware' => 'admin' 'middleware' => 'admin'
], function () { ], function () {
// Auto update routes
//----------------------------------
Route::post('/update', [
'as' => 'auto.update',
'uses' => 'UpdateController@update'
]);
Route::get('/check/update', [
'as' => 'check.update',
'uses' => 'UpdateController@checkLatestVersion'
]);
Route::get('/bootstrap', [ Route::get('/bootstrap', [
'as' => 'bootstrap', 'as' => 'bootstrap',
'uses' => 'UsersController@getBootstrap' 'uses' => 'UsersController@getBootstrap'
@ -323,6 +337,21 @@ Route::group(['middleware' => 'api'], function () {
'uses' => 'CompanyController@updateSetting' 'uses' => 'CompanyController@updateSetting'
]); ]);
Route::get('/environment/mail', [
'as' => 'admin.environment.mail',
'uses' => 'EnvironmentController@getMailDrivers'
]);
Route::get('/environment/mail-env', [
'as' => 'admin.mail.env',
'uses' => 'EnvironmentController@getMailEnvironment'
]);
Route::post('/environment/mail', [
'as' => 'admin.environment.mail.save',
'uses' => 'EnvironmentController@saveMailEnvironment'
]);
}); });
}); });