Compare commits

...

97 Commits
3.0.0 ... 3.1.0

Author SHA1 Message Date
2b03bc798e new build 310 2020-05-21 11:26:26 +05:30
482556d378 Merge branch 'resend-email' into 'master'
Add Resend Email Option

See merge request mohit.panjvani/crater-web!236
2020-05-21 05:51:36 +00:00
deb525af6e build 310 2020-05-19 13:22:33 +05:30
cb2bfbb91c Add steps for update app 2020-05-19 07:50:58 +00:00
654395a175 Add steps for update app 2020-05-19 07:50:58 +00:00
e31b60bc48 Refactor Self Update Endpoints and Add Update Console Command 2020-05-17 07:04:43 +00:00
183953f4c4 Refactor Self Update Endpoints and Add Update Console Command 2020-05-17 07:04:43 +00:00
a24d8d3ebc fix updater issue 2020-05-13 16:50:45 +05:30
4ca574c581 fix migration errors 2020-05-13 12:47:06 +05:30
c7ce8c87dd new build 2020-05-13 11:31:37 +05:30
f64d546672 refactor 310 update listener 2020-05-13 11:12:33 +05:30
d4a1f1a784 fix item selection and item loader 2020-05-12 13:23:06 +05:30
e07532961e reset items on selection 2020-05-12 13:11:29 +05:30
450c265ded Merge branch 'refactor-report-pdfs' into 'master'
Refactor report pdfs

See merge request mohit.panjvani/crater-web!233
2020-05-11 15:48:49 +00:00
f8502c3ca8 Merge branch 'customer-delete' into 'master'
Customer delete label

See merge request mohit.panjvani/crater-web!237
2020-05-11 15:47:33 +00:00
899da6990d Merge branch 'new-issues' into 'master'
New issues

See merge request mohit.panjvani/crater-web!239
2020-05-11 15:47:03 +00:00
e7675f938e refactor estimate to invoice endpoint 2020-05-11 19:05:50 +05:30
b08138e9e0 refactor estimate to invoice endpoint 2020-05-11 18:34:20 +05:30
5df4abdc4b add aws-sdk-php package 2020-05-11 18:15:36 +05:30
a2fa8afa72 fix translation issue 2020-05-11 18:09:34 +05:30
7670cd67dc Merge branch 'template-refactor' into 'master'
refactor invoice2

See merge request mohit.panjvani/crater-web!238
2020-05-11 12:24:22 +00:00
8446ac2b27 refactor invoice2 2020-05-11 16:19:02 +05:30
63a80e44d5 Customer delete label 2020-05-11 14:33:11 +05:30
076df75322 Merge branch 'template-refactor' into 'master'
Template refactor

See merge request mohit.panjvani/crater-web!232
2020-05-11 07:03:45 +00:00
11db99da73 refactor invoice 1 style 2020-05-09 18:50:58 +05:30
050dca5a50 Add copy pdf url option 2020-05-09 14:37:22 +05:30
3c096f1386 Add Resend Email Option 2020-05-09 14:22:13 +05:30
0f3e8fce3b refactor heading text in payment 2020-05-08 20:55:00 +05:30
325f90bba5 Fix issues on invoice template 2020-05-08 18:49:02 +05:30
a739a938fc Fix estimate template issues 2020-05-08 16:52:48 +05:30
b30e3a9b11 merge with github 2020-05-08 11:11:57 +05:30
fc1a7c7438 refactor reports pdfs 2020-05-07 18:59:50 +05:30
6046113cb1 Refactor Invoice and Payment templates 2020-05-07 16:42:04 +05:30
611ffafec5 refactor sales customers pdf 2020-05-06 20:41:15 +05:30
c497b906df refactor taxt report pdf 2020-05-06 20:32:10 +05:30
c68fce19f9 refactor expenses pdf 2020-05-06 19:02:02 +05:30
f8913531b6 refactor profit loss pdfs 2020-05-06 18:09:28 +05:30
30f76e2088 Refactor Estimate templates 2020-05-06 18:02:27 +05:30
39556892cd refactor sales customers 2020-05-05 20:58:20 +05:30
2fd66bf748 refactor sales items and customer pdfs 2020-05-05 20:49:51 +05:30
d4f1428d5f refactor sales customers pdf template 2020-05-05 20:03:51 +05:30
189141c84d Refactor estimate pdf template 2020-05-05 18:21:25 +05:30
f8ccfece09 update templates 2020-05-05 13:12:26 +05:30
9a7c926d53 fix 310 update issues 2020-05-02 18:53:51 +05:30
c5c1674153 Merge branch 'master' 2020-05-02 13:37:36 +05:30
8562ee5414 Merge branch 'settings-customization-payments' into 'master'
Payments and UnitItems in doubles issue fixed...

See merge request mohit.panjvani/crater-web!218
2020-04-27 16:09:25 +00:00
06c66a756c Payments and UnitItems in doubles issue fixed... 2020-04-27 18:54:24 +05:30
b66d07d21b Merge pull request #201 from rexlManu/master
Updated German Language
2020-04-27 12:14:23 +05:30
05001b6a79 Merge pull request #170 from RobinDev/patch-1
Update french language
2020-04-21 14:52:02 +05:30
f02f4ba9d3 Updated German Language 2020-04-21 07:31:33 +02:00
fbace98aac add missing translation 2020-04-20 21:12:03 +02:00
8f0af3dcd6 Merge branch 'master' of https://github.com/bytefury/crater 2020-04-20 11:23:00 +05:30
e8e44c5dc8 Merge pull request #180 from alessandrofuda/master
IT Italian translation
2020-04-18 13:38:21 +05:30
ac33164342 Merge branch '3.1.0' into 'master'
add listener 310

See merge request mohit.panjvani/crater-web!202
2020-04-18 07:29:08 +00:00
5c7c0d84ea Merge branch 'refactor-crater-3.0.0' into 'master'
Refactor line-chart

See merge request mohit.panjvani/crater-web!203
2020-04-18 07:15:52 +00:00
7ca725ac37 refactor line-chart 2020-04-17 19:53:08 +05:30
510a4b3dbb add listener 310 2020-04-17 19:05:10 +05:30
0f130ab1b8 Update fr langugage 2020-04-17 09:57:38 +02:00
25114009e3 remove unused components and update eslint + prettier config 2020-03-30 11:40:45 +05:30
79c16d74ce IT Italian translation 2020-03-20 18:18:27 +01:00
742e1e445a Merge branch 'expense-refactor' into 'master'
add customer in expense

See merge request mohit.panjvani/crater-web!172
2020-03-20 07:12:39 +00:00
386f96d60e Merge branch 'version301' into 'master'
add new minor version update 3.0.1

See merge request mohit.panjvani/crater-web!169
2020-03-20 07:12:27 +00:00
82d85af672 refactor and merge backend 2020-03-18 18:21:53 +05:30
4d1b267688 Merge branch 'expense-refactor' of https://gitlab.com/mohit.panjvani/crater-web into expense-refactor 2020-03-18 17:41:15 +05:30
bc99ad63a6 add user to expense 2020-03-18 17:40:03 +05:30
4bb44f8c93 add customer filter on index 2020-03-18 17:19:09 +05:30
c72265ed50 add languages 2020-03-17 19:38:59 +05:30
b8958c9eb6 add customer in expense 2020-03-17 19:20:42 +05:30
e33e314cb7 new frontend build 2020-03-09 15:20:59 +05:30
84cebee9da Merge branch 'master' of https://github.com/bytefury/crater 2020-03-09 15:19:54 +05:30
34d3cf7ae8 Merge branch 'item-refactor' into 'master'
refactor item search problem

See merge request mohit.panjvani/crater-web!171
2020-03-09 09:49:26 +00:00
93d0da836a Merge pull request #172 from digitalsign/master
Change project name in composer.json
2020-02-26 14:35:21 +05:30
fd51276948 Change project name in composer.json 2020-02-26 13:31:57 +08:00
d6274854ba refactor search problem 2020-02-19 19:10:43 +05:30
ea4bd1a31d Merge pull request #154 from lukasmu/bugfix/expenses-note
Fixed small bug that might occur when an expense is updated
2020-02-09 12:01:43 +05:30
286e047963 Merge pull request #129 from deanhouseholder/master
Detect if no .env file exists and add it on composer commands.
2020-02-09 12:01:25 +05:30
be16f48f3d Merge pull request #153 from MakerLab-Dev/patch-3
Improved error handling
2020-02-09 12:00:23 +05:30
ebea1e0813 add new minor version update 3.0.1 2020-02-07 17:20:32 +05:30
cc8d08f829 Merge pull request #142 from miraro3/master
Added Kyrgyzstani som
2020-02-07 16:42:15 +05:30
aacffc22eb fix merge conflict 2020-02-03 21:15:07 +05:30
d71ca4ffb9 Fixed small bug that might occur when an expense is updated
Previoulsy a string with contents "null" is transmitted and saved to the database when updating an expense with an empty note. This fix prevents that.
Please note that this fix still needs to be compiled with npm.
2020-02-01 14:52:07 +01:00
186004f7f8 fix merge conflicts 2020-01-31 14:28:16 +05:30
c2eb22d666 Merge pull request #137 from MakerLab-Dev/patch-1
cross-env should only be in devDependencies
2020-01-31 01:26:32 +05:30
af189b15b6 Small fix 2020-01-30 20:48:16 +01:00
1c19be85c3 Improved error handling 2020-01-30 20:47:51 +01:00
4bb4362d23 Removed unnecessary notification
Removed unnecessary notification as the improved error handler will show it
2020-01-30 20:45:39 +01:00
f6f66b3ae6 Merge pull request #152 from mdpoulter/email-subject
More descriptive email fields.
2020-01-31 00:21:29 +05:30
b4ccecbcf1 Merge pull request #149 from proea/master
Fix for "Empty PDF rendered in Docker #69"
2020-01-31 00:11:51 +05:30
92f1f196bb Update Dockerfile 2020-01-27 22:38:47 +03:00
ee14070a7b Update Dockerfile
slight change
2020-01-27 22:37:41 +03:00
8ce7e14a02 Add name in From field. 2020-01-27 20:37:25 +02:00
3401ca049e Make viewed emails more descriptive. 2020-01-27 14:47:02 +02:00
5dcc7b9efd Add more descriptive subject lines. 2020-01-27 14:45:40 +02:00
406d098172 Update Dockerfile
Generation does not work due to:
iconv(): Wrong charset, conversion from `UTF-8' to `UTF-8//IGNORE' is not allowed

Installing the library gnu-libiconv will solve the problem
2020-01-26 23:18:15 +03:00
f68e86e4cf Added Kyrgyzstani som 2020-01-20 22:37:03 +01:00
0990ce4678 cross-env should only be in devDependencies 2020-01-18 16:29:48 +01:00
353c2479f1 Detect if no .env file exists and add it on composer commands. 2020-01-06 10:55:34 -07:00
94 changed files with 7420 additions and 10442 deletions

View File

@ -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
}
}]
}
}

5
.prettierrc.json Normal file
View File

@ -0,0 +1,5 @@
{
"semi": false,
"singleQuote": true,
"tabWidth": 2
}

View File

@ -23,9 +23,11 @@ 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 && \
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
@ -49,4 +51,3 @@ RUN touch database/database.sqlite && \
EXPOSE 9000
CMD ["php-fpm", "--nodaemonize"]

View File

@ -0,0 +1,189 @@
<?php
namespace Crater\Console\Commands;
use Illuminate\Console\Command;
use Crater\Space\Updater;
use Crater\Setting;
class UpdateCommand extends Command
{
public $installed;
public $version;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'crater:update';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Automatically update your crater app';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*/
public function handle()
{
set_time_limit(3600); // 1 hour
$this->installed = $this->getInstalledVersion();
$this->version = $this->getLatestVersion();
if (!$this->version) {
$this->info('No Update Available! You are already on the latest version.');
return;
}
if (!$this->confirm("Do you wish to update to {$this->version}?")) {
return;
}
if (!$path = $this->download()) {
return;
}
if (!$path = $this->unzip($path)) {
return;
}
if (!$this->copyFiles($path)) {
return;
}
if (!$this->migrateUpdate()) {
return;
}
if (!$this->finish()) {
return;
}
$this->info('Successfully updated to ' . $this->version);
}
public function getInstalledVersion()
{
return Setting::getSetting('version');
}
public function getLatestVersion()
{
$this->info('Your currently installed version is ' . $this->installed);
$this->line('');
$this->info('Checking for update...');
try {
$response = Updater::checkForUpdate($this->installed);
if ($response->success) {
return $response->version->version;
}
return false;
} catch (\Exception $e) {
$this->error($e->getMessage());
return false;
}
}
public function download()
{
$this->info('Downloading update...');
try {
$path = Updater::download($this->version);
if (!is_string($path)) {
$this->error('Download exception');
return false;
}
} catch (\Exception $e) {
$this->error($e->getMessage());
return false;
}
return $path;
}
public function unzip($path)
{
$this->info('Unzipping update package...');
try {
$path = Updater::unzip($path);
if (!is_string($path)) {
$this->error('Unzipping exception');
return false;
}
} catch (\Exception $e) {
$this->error($e->getMessage());
return false;
}
return $path;
}
public function copyFiles($path)
{
$this->info('Copying update files...');
try {
Updater::copyFiles($path);
} catch (\Exception $e) {
$this->error($e->getMessage());
return false;
}
return true;
}
public function migrateUpdate()
{
$this->info('Running Migrations...');
try {
Updater::migrateUpdate();
} catch (\Exception $e) {
$this->error($e->getMessage());
return false;
}
return true;
}
public function finish()
{
$this->info('Finishing update...');
try {
Updater::finishUpdate($this->installed, $this->version);
} catch (\Exception $e) {
$this->error($e->getMessage());
return false;
}
return true;
}
}

View File

@ -12,7 +12,8 @@ class Kernel extends ConsoleKernel
* @var array
*/
protected $commands = [
Commands\ResetApp::class
Commands\ResetApp::class,
Commands\UpdateCommand::class
];
/**

View File

@ -25,7 +25,7 @@ class UpdateFinished
*/
public function __construct($old, $new)
{
$this->old = $old;
$this->new = $new;
$this->old = $old;
$this->new = $new;
}
}

View File

@ -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'));

View File

@ -143,13 +143,14 @@ class CompanyController extends Controller
$currency = CompanySetting::getSetting('currency', $request->header('company'));
$fiscal_year = CompanySetting::getSetting('fiscal_year', $request->header('company'));
$languages = [
$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"],
];
return response()->json([

View File

@ -175,12 +175,6 @@ class EstimatesController extends Controller
]);
}
if (!config('mail.from.name')) {
return response()->json([
'error' => 'from_email_does_not_exist'
]);
}
\Mail::to($email)->send(new EstimatePdf($data));
}
@ -343,12 +337,6 @@ class EstimatesController extends Controller
]);
}
if (!config('mail.from.name')) {
return response()->json([
'error' => 'from_email_does_not_exist'
]);
}
\Mail::to($email)->send(new EstimatePdf($data));
if ($estimate->status == Estimate::STATUS_DRAFT) {
@ -397,12 +385,12 @@ class EstimatesController extends Controller
public function estimateToInvoice(Request $request, $id)
{
$estimate = Estimate::with(['items', 'items.taxes', 'user', 'estimateTemplate', 'taxes'])->find($id);
$invoice_date = Carbon::parse($estimate->estimate_date);
$invoice_date = Carbon::now();
$invoice_prefix = CompanySetting::getSetting(
'invoice_prefix',
$request->header('company')
);
$due_date = Carbon::parse($estimate->estimate_date)->addDays(7);
$due_date = Carbon::now()->addDays(7);
$tax_per_item = CompanySetting::getSetting(
'tax_per_item',
$request->header('company')

View File

@ -1,4 +1,5 @@
<?php
namespace Crater\Http\Controllers;
use Crater\Expense;
@ -24,9 +25,11 @@ class ExpensesController extends Controller
$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 +37,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'))
)
@ -53,9 +61,13 @@ class ExpensesController extends Controller
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
]);
}
@ -72,6 +84,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;
@ -104,10 +117,12 @@ class ExpensesController extends Controller
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function edit(Request $request,$id)
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([
@ -132,6 +147,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();
@ -181,11 +197,11 @@ class ExpensesController extends Controller
{
$data = json_decode($request->attachment_receipt);
if($data) {
if ($data) {
$expense = Expense::find($id);
if($expense) {
if($request->type === 'edit') {
if ($expense) {
if ($request->type === 'edit') {
$expense->clearMediaCollection('receipts');
}
@ -205,15 +221,15 @@ 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);
$imagePath = null;
if($expense) {
if ($expense) {
$media = $expense->getFirstMedia('receipts');
if($media) {
if ($media) {
$imagePath = $media->getPath();
} else {
return response()->json([
@ -224,7 +240,7 @@ class ExpensesController extends Controller
$type = \File::mimeType($imagePath);
$image = 'data:'.$type.';base64,'.base64_encode(file_get_contents($imagePath));
$image = 'data:' . $type . ';base64,' . base64_encode(file_get_contents($imagePath));
return response()->json([
'image' => $image,
@ -239,7 +255,7 @@ class ExpensesController extends Controller
* @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();
@ -249,17 +265,10 @@ class ExpensesController extends Controller
->first();
$imagePath = null;
if($expense) {
if ($expense) {
$media = $expense->getFirstMedia('receipts');
if($media) {
if ($media) {
$imagePath = $media->getPath();
$filename = $media->getPath();
$type = \File::mimeType($imagePath);
$headers = array(
'Content-Type' => $type,
);
$response = \Response::download($imagePath, $media->file_name);
ob_end_clean();
return $response;
@ -271,4 +280,3 @@ class ExpensesController extends Controller
]);
}
}

View File

@ -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;
@ -175,13 +175,7 @@ class InvoicesController extends Controller
]);
}
if (!config('mail.from.name')) {
return response()->json([
'error' => 'from_email_does_not_exist'
]);
}
\Mail::to($email)->send(new invoicePdf($data));
\Mail::to($email)->send(new InvoicePdf($data));
}
$invoice = Invoice::with(['items', 'user', 'invoiceTemplate', 'taxes'])->find($invoice->id);
@ -410,13 +404,7 @@ class InvoicesController extends Controller
]);
}
if (!config('mail.from.name')) {
return response()->json([
'error' => 'from_email_does_not_exist'
]);
}
\Mail::to($email)->send(new invoicePdf($data));
\Mail::to($email)->send(new InvoicePdf($data));
if ($invoice->status == Invoice::STATUS_DRAFT) {
$invoice->status = Invoice::STATUS_SENT;

View File

@ -50,7 +50,8 @@ class OnboardingController extends Controller
["code"=>"es", "name" => "Spanish"],
["code"=>"ar", "name" => "العربية"],
["code"=>"de", "name" => "German"],
["code"=>"pt-br", "name" => "Portuguese (Brazilian)"]
["code"=>"pt-br", "name" => "Portuguese (Brazilian)"],
["code"=>"it", "name" => "Italian"],
];
$fiscal_years = [
['key' => 'january-december' , 'value' => '1-12'],

View File

@ -305,10 +305,6 @@ class PaymentController extends Controller
$data['user'] = User::find($userId)->toArray();
$data['company'] = Company::find($payment->company_id);
$email = $data['user']['email'];
$notificationEmail = CompanySetting::getSetting(
'notification_email',
$request->header('company')
);
if (!$email) {
return response()->json([
@ -316,13 +312,7 @@ class PaymentController extends Controller
]);
}
if (!$notificationEmail) {
return response()->json([
'error' => 'notification_email_does_not_exist'
]);
}
\Mail::to($email)->send(new PaymentPdf($data, $notificationEmail));
\Mail::to($email)->send(new PaymentPdf($data));
return response()->json([
'success' => true

View File

@ -2,23 +2,81 @@
namespace Crater\Http\Controllers;
use Crater\Setting;
use Illuminate\Http\Request;
use Crater\Space\Updater;
use Crater\Space\SiteApi;
use Illuminate\Support\Facades\Artisan;
class UpdateController extends Controller
{
public function update(Request $request)
public function download(Request $request)
{
set_time_limit(600); // 10 minutes
$request->validate([
'version' => 'required',
]);
$json = Updater::update($request->installed, $request->version);
$path = Updater::download($request->version);
return response()->json($json);
return response()->json([
'success' => true,
'path' => $path
]);
}
public function unzip(Request $request)
{
$request->validate([
'path' => 'required',
]);
try {
$path = Updater::unzip($request->path);
return response()->json([
'success' => true,
'path' => $path
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'error' => $e->getMessage()
], 500);
}
}
public function copyFiles(Request $request)
{
$request->validate([
'path' => 'required',
]);
$path = Updater::copyFiles($request->path);
return response()->json([
'success' => true,
'path' => $path
]);
}
public function migrate(Request $request)
{
Updater::migrateUpdate();
return response()->json([
'success' => true
]);
}
public function finishUpdate(Request $request)
{
$request->validate([
'installed' => 'required',
'version' => 'required',
]);
$json = Updater::finishUpdate($request->installed, $request->version);
return response()->json($json);
@ -28,7 +86,7 @@ class UpdateController extends Controller
{
set_time_limit(600); // 10 minutes
$json = Updater::checkForUpdate();
$json = Updater::checkForUpdate(Setting::getSetting('version'));
return response()->json($json);
}

View File

@ -0,0 +1,52 @@
<?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;
use Crater\Setting;
use Crater\Currency;
use Schema;
use Artisan;
class Version310 extends Listener
{
const VERSION = '3.1.0';
/**
* Handle the event.
*
* @param UpdateFinished $event
* @return void
*/
public function handle(UpdateFinished $event)
{
if ($this->isListenerFired($event)) {
return;
}
Currency::firstOrCreate(
[
'name' => 'Kyrgyzstani som',
'code' => 'KGS'
],
[
'name' => 'Kyrgyzstani som',
'code' => 'KGS',
'symbol' => 'С̲ ',
'precision' => '2',
'thousand_separator' => '.',
'decimal_separator' => ','
]
);
Artisan::call('migrate', ['--force' => true]);
// Update Crater app version
Setting::setSetting('version', static::VERSION);
}
}

View File

@ -29,6 +29,9 @@ class EstimatePdf extends Mailable
*/
public function build()
{
return $this->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]);
}
}

View File

@ -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]);
}
}

View File

@ -6,7 +6,7 @@ use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class invoicePdf extends Mailable
class InvoicePdf extends Mailable
{
use Queueable, SerializesModels;
@ -29,6 +29,9 @@ class invoicePdf extends Mailable
*/
public function build()
{
return $this->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]);
}
}

View File

@ -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]);
}
}

View File

@ -13,17 +13,14 @@ class PaymentPdf 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;
}
/**
@ -33,6 +30,9 @@ class PaymentPdf extends Mailable
*/
public function build()
{
return $this->from($this->notificationEmail)->markdown('emails.send.payment', ['data', $this->data]);
$company = $this->data['company']['name'];
return $this->subject("Payment from $company")
->markdown('emails.send.payment', ['data', $this->data]);
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace Crater\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@ -11,6 +12,7 @@ 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\Version310;
class EventServiceProvider extends ServiceProvider
{
@ -20,13 +22,14 @@ class EventServiceProvider extends ServiceProvider
* @var array
*/
protected $listen = [
UpdateFinished::class=> [
UpdateFinished::class => [
Version110::class,
Version200::class,
Version201::class,
Version202::class,
Version210::class,
Version300::class,
Version310::class,
],
Registered::class => [
SendEmailVerificationNotification::class,

View File

@ -2,31 +2,45 @@
namespace Crater\Space;
use File;
use ZipArchive;
use Artisan;
use GuzzleHttp\Exception\RequestException;
use Crater\Space\SiteApi;
use Crater\Events\UpdateFinished;
use Crater\Setting;
use Illuminate\Http\Request;
use ZipArchive;
class Updater
{
use SiteApi;
public static function update($installed, $version)
public static function checkForUpdate($installed_version)
{
$data = null;
if(env('APP_ENV') === 'development')
{
$url = 'https://craterapp.com/downloads/check/latest/'. $installed_version . '?type=update&is_dev=1';
} else {
$url = 'https://craterapp.com/downloads/check/latest/'. $installed_version . '?type=update';
}
$response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]);
if ($response && ($response->getStatusCode() == 200)) {
$data = $response->getBody()->getContents();
}
return json_decode($data);
}
public static function download($new_version)
{
$data = null;
$path = null;
if(env('APP_ENV') === 'development')
{
$url = 'https://craterapp.com/downloads/file/'.$version.'?type=update&is_dev=1';
if (env('APP_ENV') === 'development') {
$url = 'https://craterapp.com/downloads/file/' . $new_version . '?type=update&is_dev=1';
} else {
$url = 'https://craterapp.com/downloads/file/'.$version.'?type=update';
$url = 'https://craterapp.com/downloads/file/' . $new_version . '?type=update';
}
$response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]);
// Exception
@ -45,66 +59,68 @@ class Updater
}
// Create temp directory
$path = 'temp-' . md5(mt_rand());
$path2 = 'temp2-' . md5(mt_rand());
$temp_path = storage_path('app') . '/' . $path;
$temp_path2 = storage_path('app') . '/' . $path2;
$temp_dir = storage_path('app/temp-' . md5(mt_rand()));
if (!File::isDirectory($temp_path)) {
File::makeDirectory($temp_path);
File::makeDirectory($temp_path2);
if (!File::isDirectory($temp_dir)) {
File::makeDirectory($temp_dir);
}
try {
$zip_file_path = $temp_dir . '/upload.zip';
$file = $temp_path . '/upload.zip';
// Add content to the Zip file
$uploaded = is_int(file_put_contents($zip_file_path, $data)) ? true : false;
// 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);
return [
'success' => true,
'error' => false,
'data' => []
];
} catch (\Exception $e) {
if (File::isDirectory($temp_path)) {
// Delete temp directory
File::deleteDirectory($temp_path);
File::deleteDirectory($temp_path2);
}
return [
'success' => false,
'error' => 'Update error',
'data' => []
];
if (!$uploaded) {
return false;
}
return $zip_file_path;
}
public static function unzip($zip_file_path)
{
if(!file_exists($zip_file_path)) {
throw new \Exception('Zip file not found');
}
$temp_extract_dir = storage_path('app/temp2-' . md5(mt_rand()));
if (!File::isDirectory($temp_extract_dir)) {
File::makeDirectory($temp_extract_dir);
}
// Unzip the file
$zip = new ZipArchive();
if ($zip->open($zip_file_path)) {
$zip->extractTo($temp_extract_dir);
}
$zip->close();
// Delete zip file
File::delete($zip_file_path);
return $temp_extract_dir;
}
public static function copyFiles($temp_extract_dir)
{
if (!File::copyDirectory($temp_extract_dir . '/Crater', base_path())) {
return false;
}
// Delete temp directory
File::deleteDirectory($temp_extract_dir);
return true;
}
public static function migrateUpdate()
{
Artisan::call('migrate --force');
return true;
}
public static function finishUpdate($installed, $version)
@ -118,22 +134,4 @@ class Updater
];
}
public static function checkForUpdate()
{
$data = null;
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]);
if ($response && ($response->getStatusCode() == 200)) {
$data = $response->getBody()->getContents();
}
return json_decode($data);
}
}

View File

@ -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;
@ -105,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);

View File

@ -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"
@ -9,6 +9,7 @@
"type": "project",
"require": {
"php": "^7.2",
"aws/aws-sdk-php": "^3.137",
"barryvdh/laravel-dompdf": "^0.8.1",
"doctrine/dbal": "^2.10",
"fideloper/proxy": "^4.0",
@ -53,11 +54,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",

1719
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,6 @@ return [
|
*/
'version' => '3.0.0',
'version' => '3.1.0',
];

View File

@ -13,13 +13,15 @@ class CreateUnitsTable extends Migration
*/
public function up()
{
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')->onDelete('cascade');
$table->timestamps();
});
if (!Schema::hasTable('units')) {
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')->onDelete('cascade');
$table->timestamps();
});
}
}
/**

View File

@ -13,13 +13,15 @@ class CreatePaymentMethodsTable extends Migration
*/
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();
});
if (!Schema::hasTable('payment_methods')) {
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();
});
}
}
/**

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddUserIdToExpensesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('expenses', function (Blueprint $table) {
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('expenses', function (Blueprint $table) {
$table->dropColumn('paid');
});
}
}

View File

@ -532,6 +532,14 @@ class CurrenciesTableSeeder extends Seeder
'thousand_separator' => '.',
'decimal_separator' => ','
],
[
'name' => 'Kyrgyzstani som',
'code' => 'KGS',
'symbol' => 'С̲ ',
'precision' => '2',
'thousand_separator' => '.',
'decimal_separator' => ','
],
];
foreach ($currencies as $currency) {

5005
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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,18 +32,12 @@
"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",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/assets/js/app.js": "/assets/js/app.js?id=397e57d36ef22a2e14fc",
"/assets/css/crater.css": "/assets/css/crater.css?id=616996a79c1df69d18de"
"/assets/js/app.js": "/assets/js/app.js?id=2521d0dcc4cb4e4975a5",
"/assets/css/crater.css": "/assets/css/crater.css?id=84a4eeb53b0e6a937e44"
}

View File

@ -88,17 +88,27 @@ window.axios.interceptors.request.use(function (config) {
global.axios.interceptors.response.use(undefined, function (err) {
// Do something with request error
return new Promise((resolve, reject) => {
if (!err.response) {
window.toastr['error']('Network error: Please check your internet connection or wait until servers are back online')
console.log('Network error: Please check your internet connection.')
} else {
console.log(err.response)
if (err.response.data.error === 'invalid_credentials') {
window.toastr['error']('Invalid Credentials')
}
if (err.response.data && (err.response.statusText === 'Unauthorized' || err.response.data === ' Unauthorized.')) {
// Unauthorized and log out
window.toastr['error']((err.response.data.message) ? err.response.data.message : 'Unauthorized')
store.dispatch('auth/logout', true)
} else if (err.response.data.errors) {
// Show a notification per error
const errors = JSON.parse(JSON.stringify(err.response.data.errors))
for (const i in errors) {
window.toastr['error'](errors[i])
}
} else {
throw err
// Unknown error
window.toastr['error']((err.response.data.message) ? err.response.data.message : 'Unknown error occurred')
}
})
}
return Promise.reject(err)
})
/**

View File

@ -1,69 +0,0 @@
<template>
<div class="graph-container">
<canvas
id="graph"
ref="graph"
/>
</div>
</template>
<script>
import Chart from 'chart.js'
export default {
props: {
labels: {
type: Array,
require: true,
default: Array
},
values: {
type: Array,
require: true,
default: Array
}
},
mounted () {
let context = this.$refs.graph.getContext('2d')
let options = {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
}
}
let data = {
labels: this.labels,
datasets: [
{
label: 'My First dataset',
backgroundColor: 'rgba(79, 196, 127,0.2)',
borderColor: 'rgba(79, 196, 127,1)',
borderWidth: 1,
hoverBackgroundColor: 'rgba(79, 196, 127,0.4)',
hoverBorderColor: 'rgba(79, 196, 127,1)',
data: this.values
}
]
}
this.myBarChart = new Chart(context, {
type: 'bar',
data: data,
options: options
})
},
beforeDestroy () {
this.myBarChart.destroy()
}
}
</script>
<style scoped>
.graph-container {
height: 300px;
}
</style>

View File

@ -1,71 +0,0 @@
<template>
<div class="graph-container">
<canvas
id="graph"
ref="graph"/>
</div>
</template>
<script>
import Chart from 'chart.js'
export default {
props: {
labels: {
type: Array,
require: true,
default: Array
},
values: {
type: Array,
require: true,
default: Array
},
bgColors: {
type: Array,
require: true,
default: Array
},
hoverBgColors: {
type: Array,
require: true,
default: Array
}
},
mounted () {
let context = this.$refs.graph.getContext('2d')
let options = {
responsive: true,
maintainAspectRatio: false
}
let data = {
labels: this.labels,
datasets: [
{
data: this.values,
backgroundColor: this.bgColors,
hoverBackgroundColor: this.hoverBgColors
}
]
}
this.myDoughnutChart = new Chart(context, {
type: 'doughnut',
data: data,
options: options
})
},
beforeDestroy () {
this.myDoughnutChart.destroy()
}
}
</script>
<style scoped>
.graph-container {
height: 300px;
}
</style>

View File

@ -1,8 +1,6 @@
<template>
<div class="graph-container">
<canvas
id="graph"
ref="graph" />
<canvas id="graph" ref="graph" />
</div>
</template>
@ -16,58 +14,56 @@ export default {
labels: {
type: Array,
require: true,
default: Array
default: Array,
},
values: {
type: Array,
require: true,
default: Array
default: Array,
},
invoices: {
type: Array,
require: true,
default: Array
default: Array,
},
expenses: {
type: Array,
require: true,
default: Array
default: Array,
},
receipts: {
type: Array,
require: true,
default: Array
default: Array,
},
income: {
type: Array,
require: true,
default: Array
default: Array,
},
formatMoney: {
type: Function,
require: false,
default: Function
default: Function,
},
FormatGraphMoney: {
type: Function,
require: false,
default: Function
}
default: Function,
},
},
computed: {
...mapGetters('currency', [
'defaultCurrency'
])
...mapGetters('currency', ['defaultCurrency']),
},
watch: {
labels (val) {
labels(val) {
this.update()
}
},
},
mounted () {
mounted() {
let self = this
let context = this.$refs.graph.getContext('2d')
let options = {
@ -77,13 +73,16 @@ export default {
enabled: true,
callbacks: {
label: function (tooltipItem, data) {
return self.FormatGraphMoney(tooltipItem.value, self.defaultCurrency)
}
}
return self.FormatGraphMoney(
tooltipItem.value * 100,
self.defaultCurrency
)
},
},
},
legend: {
display: false
}
display: false,
},
}
let data = {
labels: this.labels,
@ -107,7 +106,7 @@ export default {
pointHoverBorderWidth: 2,
pointRadius: 4,
pointHitRadius: 10,
data: this.invoices
data: this.invoices.map((invoice) => invoice / 100),
},
{
label: 'Receipts',
@ -128,7 +127,7 @@ export default {
pointHoverBorderWidth: 2,
pointRadius: 4,
pointHitRadius: 10,
data: this.receipts
data: this.receipts.map((receipt) => receipt / 100),
},
{
label: 'Expenses',
@ -149,7 +148,7 @@ export default {
pointHoverBorderWidth: 2,
pointRadius: 4,
pointHitRadius: 10,
data: this.expenses
data: this.expenses.map((expense) => expense / 100),
},
{
label: 'Net Income',
@ -170,34 +169,40 @@ export default {
pointHoverBorderWidth: 2,
pointRadius: 4,
pointHitRadius: 10,
data: this.income
}
]
data: this.income.map((_i) => _i / 100),
},
],
}
this.myLineChart = new Chart(context, {
type: 'line',
data: data,
options: options
options: options,
})
},
methods: {
update () {
update() {
this.myLineChart.data.labels = this.labels
this.myLineChart.data.datasets[0].data = this.invoices
this.myLineChart.data.datasets[1].data = this.receipts
this.myLineChart.data.datasets[2].data = this.expenses
this.myLineChart.data.datasets[3].data = this.income
this.myLineChart.data.datasets[0].data = this.invoices.map(
(invoice) => invoice / 100
)
this.myLineChart.data.datasets[1].data = this.receipts.map(
(receipt) => receipt / 100
)
this.myLineChart.data.datasets[2].data = this.expenses.map(
(expense) => expense / 100
)
this.myLineChart.data.datasets[3].data = this.income.map((_i) => _i / 100)
this.myLineChart.update({
lazy: true
lazy: true,
})
},
beforeDestroy () {
beforeDestroy() {
this.myLineChart.destroy()
}
}
},
},
}
</script>

View File

@ -1,72 +0,0 @@
<template>
<div class="graph-container">
<canvas
id="graph"
ref="graph" />
</div>
</template>
<script>
import Chart from 'chart.js'
export default {
props: {
labels: {
type: Array,
require: true,
default: Array
},
values: {
type: Array,
require: true,
default: Array
},
bgColors: {
type: Array,
require: true,
default: Array
},
hoverBgColors: {
type: Array,
require: true,
default: Array
}
},
mounted () {
let context = this.$refs.graph.getContext('2d')
let options = {
responsive: true,
maintainAspectRatio: false
}
let data = {
labels: this.labels,
datasets: [
{
data: this.values,
backgroundColor: this.bgColors,
hoverBackgroundColor: this.hoverBgColors
}
]
}
this.pieChart = new Chart(context, {
type: 'pie',
data: data,
options: options
})
},
beforeDestroy () {
this.pieChart.destroy()
}
}
</script>
<style scoped>
.graph-container {
height: 300px;
}
</style>

View File

@ -1,95 +0,0 @@
<template>
<div class="graph-container easy-pie-chart">
<svg width="100%" height="100%" viewBox="0 0 34 34" class="donut">
<circle :stroke-width="strokeWidth" class="donut-segment" cx="17" cy="17" r="15.91549430918954" fill="transparent" :stroke="strokeColor" stroke-dasharray="100 0" />
<circle :stroke-width="strokeWidth" :stroke="color" :stroke-dasharray="successProgress" class="donut-segment" cx="17" cy="17" r="15.91549430918954" fill="transparent" />
<!-- <g class="chart-text">
<text :style="'fill:' + color" x="48%" y="50%" class="chart-number" >
{{ progress }}
</text>
<text :style="'fill:' + color" x="73%" y="50%" class="chart-label" >
%
</text>
</g> -->
</svg>
</div>
</template>
<script>
export default {
props: {
values: {
type: Number,
require: true,
default: 100
},
strokeWidth: {
type: Number,
require: false,
default: 1.2
},
strokeColor: {
type: String,
require: true,
default: '#eeeeee'
},
color: {
type: String,
require: true,
default: '#007dcc'
}
},
data () {
return {
progress: 0
}
},
watch: {
values (newvalue, oldvalue) {
if (newvalue !== oldvalue) {
this.setProgress()
}
}
},
computed: {
successProgress () {
return this.progress + ' ' + (100 - this.progress)
},
remainProgress () {
return 100 - this.progress + ' ' + this.progress
},
},
mounted () {
this.setProgress()
},
methods: {
setProgress () {
let self = this
for (let i = 0; i < this.values; i++) {
setTimeout(function () {
++self.progress
}, 15 * i)
}
}
}
}
</script>
<style scoped>
.chart-text {
font: 6px "Montserrat", Arial, sans-serif;
fill: #000;
-moz-transform: translateY(0.25em);
-ms-transform: translateY(0.25em);
-webkit-transform: translateY(0.25em);
transform: translateY(0.5em);
}
.chart-number {
font-size: 8px;
line-height: 1;
text-anchor: middle;
}
.chart-label {
font-size: 5px;
text-transform: uppercase;
text-anchor: middle;
}
</style>

View File

@ -1,16 +1,16 @@
export default {
toggleSidebar () {
toggleSidebar() {
let icon = document.getElementsByClassName('hamburger')[0]
document.body.classList.toggle('sidebar-open')
icon.classList.toggle('is-active')
},
addClass (el, className) {
addClass(el, className) {
if (el.classList) el.classList.add(className)
else el.className += ' ' + className
},
hasClass (el, className) {
hasClass(el, className) {
const hasClass = el.classList
? el.classList.contains(className)
: new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className)
@ -18,33 +18,38 @@ export default {
return hasClass
},
reset (prefix) {
reset(prefix) {
let regx = new RegExp('\\b' + prefix + '(.*)?\\b', 'g')
document.body.className = document.body.className.replace(regx, '')
},
setLayout (layoutName) {
setLayout(layoutName) {
this.reset('layout-')
document.body.classList.add('layout-' + layoutName)
},
setSkin (skinName) {
setSkin(skinName) {
this.reset('skin-')
document.body.classList.add('skin-' + skinName)
},
setLogo (logoSrc) {
setLogo(logoSrc) {
document.getElementById('logo-desk').src = logoSrc
},
formatMoney (amount, currency = 0) {
formatMoney(amount, currency = 0) {
if (!currency) {
currency = {precision: 2, thousand_separator: ',', decimal_separator: '.', symbol: '$'}
currency = {
precision: 2,
thousand_separator: ',',
decimal_separator: '.',
symbol: '$',
}
}
amount = amount / 100
let {precision, decimal_separator, thousand_separator, symbol} = currency
let { precision, decimal_separator, thousand_separator, symbol } = currency
try {
precision = Math.abs(precision)
@ -52,25 +57,44 @@ export default {
const negativeSign = amount < 0 ? '-' : ''
let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(precision)).toString()
let j = (i.length > 3) ? i.length % 3 : 0
let i = parseInt(
(amount = Math.abs(Number(amount) || 0).toFixed(precision))
).toString()
let j = i.length > 3 ? i.length % 3 : 0
let moneySymbol = `<span style="font-family: sans-serif">${symbol}</span>`
return moneySymbol + ' ' + negativeSign + (j ? i.substr(0, j) + thousand_separator : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator) + (precision ? decimal_separator + Math.abs(amount - i).toFixed(precision).slice(2) : '')
return (
moneySymbol +
' ' +
negativeSign +
(j ? i.substr(0, j) + thousand_separator : '') +
i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator) +
(precision
? decimal_separator +
Math.abs(amount - i)
.toFixed(precision)
.slice(2)
: '')
)
} catch (e) {
console.log(e)
}
},
formatGraphMoney (amount, currency = 0) {
formatGraphMoney(amount, currency = 0) {
if (!currency) {
currency = {precision: 2, thousand_separator: ',', decimal_separator: '.', symbol: '$'}
currency = {
precision: 2,
thousand_separator: ',',
decimal_separator: '.',
symbol: '$',
}
}
amount = amount / 100
let {precision, decimal_separator, thousand_separator, symbol} = currency
let { precision, decimal_separator, thousand_separator, symbol } = currency
try {
precision = Math.abs(precision)
@ -78,25 +102,76 @@ export default {
const negativeSign = amount < 0 ? '-' : ''
let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(precision)).toString()
let j = (i.length > 3) ? i.length % 3 : 0
let i = parseInt(
(amount = Math.abs(Number(amount) || 0).toFixed(precision))
).toString()
let j = i.length > 3 ? i.length % 3 : 0
let moneySymbol = `${symbol}`
return moneySymbol + ' ' + negativeSign + (j ? i.substr(0, j) + thousand_separator : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator) + (precision ? decimal_separator + Math.abs(amount - i).toFixed(precision).slice(2) : '')
return (
moneySymbol +
' ' +
negativeSign +
(j ? i.substr(0, j) + thousand_separator : '') +
i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator) +
(precision
? decimal_separator +
Math.abs(amount - i)
.toFixed(precision)
.slice(2)
: '')
)
} catch (e) {
console.log(e)
}
},
checkValidUrl (url) {
let pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
checkValidUrl(url) {
let pattern = new RegExp(
'^(https?:\\/\\/)?' + // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
'(\\#[-a-z\\d_]*)?$', 'i') // fragment locator
'(\\#[-a-z\\d_]*)?$',
'i'
) // fragment locator
return !!pattern.test(url)
}
},
fallbackCopyTextToClipboard(text) {
var textArea = document.createElement('textarea')
textArea.value = text
// Avoid scrolling to bottom
textArea.style.top = '0'
textArea.style.left = '0'
textArea.style.position = 'fixed'
document.body.appendChild(textArea)
textArea.focus()
textArea.select()
try {
var successful = document.execCommand('copy')
var msg = successful ? 'successful' : 'unsuccessful'
console.log('Fallback: Copying text command was ' + msg)
} catch (err) {
console.error('Fallback: Oops, unable to copy', err)
}
document.body.removeChild(textArea)
},
copyTextToClipboard(text) {
if (!navigator.clipboard) {
this.fallbackCopyTextToClipboard(text)
return
}
navigator.clipboard.writeText(text).then(
function () {
return true
},
function (err) {
return false
}
)
},
}

View File

@ -62,14 +62,14 @@
"four_zero_four": "404",
"you_got_lost": "عفواً! يبدو أنك قد تهت!",
"go_home": "عودة إلى الرئيسية",
"setting_updated": "تم تحديث الإعدادات بنجاح",
"select_state": "اختر الولاية/المنطقة",
"select_country": "اختر الدولة",
"select_city": "اختر المدينة",
"street_1": "عنوان الشارع 1",
"street_2": "عنوان الشارع 2",
"action_failed": "فشلت العملية"
"action_failed": "فشلت العملية",
"retry": "أعد المحاولة"
},
"dashboard": {
"select_year": "اختر السنة",
@ -155,7 +155,7 @@
"select_a_customer": "اختر العميل",
"type_or_click": "اكتب أو اضغط للاختيار",
"confirm_delete": "لن تكون قادراً على استرجاع هذا العميل | لن تكون قادراً على استرجاع هؤلاء العملاء",
"confirm_delete": "لن تتمكن من استرداد هذا العميل وجميع الفواتير والتقديرات والمدفوعات ذات الصلة. | لن تتمكن من استرداد هؤلاء العملاء وجميع الفواتير والتقديرات والمدفوعات ذات الصلة.",
"created_message": "تم إنشاء العملاء بنجاح",
"updated_message": "تم تحديث العملاء بنجاح",
"deleted_message": "تم حذف العملاء بنجاح | تم حذف العميل بنجاح"
@ -370,7 +370,7 @@
"description": "الوصف",
"quantity": "الكمية",
"price": "السعر",
"discount": "الخصم",
"discount": "الخصم",
"total": "الإجمالي",
"total_discount": "إجمالي الخصم",
"sub_total": "حاصل الجمع",
@ -412,6 +412,8 @@
"title": "النفقات",
"expenses_list": "قائمة النفقات",
"expense_title": "Title",
"select_a_customer": "حدد عميلاً",
"customer": "العميل",
"contact": "تواصل",
"category": "الفئة",
"from_date": "من تاريخ",
@ -601,65 +603,65 @@
"updated_message": "تم تحديث معلومات الشركة بنجاح"
},
"customization": {
"customization": "التخصيص",
"save": "حفظ",
"addresses": {
"title": "العنوان",
"section_description": "يمكنك ضبط عنوان إرسال فواتير العملاء وتنسيق عنوان شحن العملاء (معروض في PDF فقط).",
"customer_billing_address": "عنوان فواتير العميل",
"customer_shipping_address": "عنوان الشحن للعميل",
"company_address": "عنوان الشركة",
"insert_fields": "أضف حقل",
"contact": "تواصل",
"address": "العنوان",
"display_name": "الاسم الظاهر",
"primary_contact_name": "مسؤول التواصل الرئيسي",
"email": "البريد الإلكتروني",
"website": "موقع الإنترنت",
"name": "الاسم",
"country": "الدولة",
"state": "الولاية/المنطقة",
"city": "المدينة",
"company_name": "اسم الشركة",
"address_street_1": "عنوان الشارع 1",
"address_street_2": "عنوان الشارع 2",
"phone": "الهاتف",
"zip_code": "الرمز البريدي",
"address_setting_updated": "تم تحديث العنوان بنجاح"
},
"updated_message": "تم تحديث معلومات الشركة بنجاح",
"customization": "التخصيص",
"save": "حفظ",
"addresses": {
"title": "العنوان",
"section_description": "يمكنك ضبط عنوان إرسال فواتير العملاء وتنسيق عنوان شحن العملاء (معروض في PDF فقط).",
"customer_billing_address": "عنوان فواتير العميل",
"customer_shipping_address": "عنوان الشحن للعميل",
"company_address": "عنوان الشركة",
"insert_fields": "أضف حقل",
"contact": "تواصل",
"address": "العنوان",
"display_name": "الاسم الظاهر",
"primary_contact_name": "مسؤول التواصل الرئيسي",
"email": "البريد الإلكتروني",
"website": "موقع الإنترنت",
"name": "الاسم",
"country": "الدولة",
"state": "الولاية/المنطقة",
"city": "المدينة",
"company_name": "اسم الشركة",
"address_street_1": "عنوان الشارع 1",
"address_street_2": "عنوان الشارع 2",
"phone": "الهاتف",
"zip_code": "الرمز البريدي",
"address_setting_updated": "تم تحديث العنوان بنجاح"
},
"updated_message": "تم تحديث معلومات الشركة بنجاح",
"invoices": {
"title": "الفواتير",
"notes": "ملاحظات",
"invoice_prefix": "بادئة رقم الفاتورة",
"invoice_settings": "إعدادات الفاتورة",
"autogenerate_invoice_number": "ترقيم آلي للفاتورة",
"invoice_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام الفاتورة تلقائيًا في كل مرة تقوم فيها بإنشاء فاتورة جديدة.",
"enter_invoice_prefix": "أدخل بادئة رقم الفاتورة",
"terms_and_conditions": "الأحكام والشروط",
"invoice_setting_updated": "تم تحديث إعداد الفاتورة بنجاح"
},
"invoices": {
"title": "الفواتير",
"notes": "ملاحظات",
"invoice_prefix": "بادئة رقم الفاتورة",
"invoice_settings": "إعدادات الفاتورة",
"autogenerate_invoice_number": "ترقيم آلي للفاتورة",
"invoice_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام الفاتورة تلقائيًا في كل مرة تقوم فيها بإنشاء فاتورة جديدة.",
"enter_invoice_prefix": "أدخل بادئة رقم الفاتورة",
"terms_and_conditions": "الأحكام والشروط",
"invoice_setting_updated": "تم تحديث إعداد الفاتورة بنجاح"
},
"estimates": {
"title": "التقديرات",
"estimate_prefix": "بادئة رقم التقدير",
"estimate_settings": "إعدادت التقدير",
"autogenerate_estimate_number": "ترقيم آلي للتقدير",
"estimate_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام التقديرات تلقائيًا في كل مرة تقوم فيها بإنشاء تقدير جديد.",
"enter_estimate_prefix": "أدخل بادئة رقم التقدير",
"estimate_setting_updated": "تم تحديث إعدادات التقدير بنجاح"
},
"estimates": {
"title": "التقديرات",
"estimate_prefix": "بادئة رقم التقدير",
"estimate_settings": "إعدادت التقدير",
"autogenerate_estimate_number": "ترقيم آلي للتقدير",
"estimate_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام التقديرات تلقائيًا في كل مرة تقوم فيها بإنشاء تقدير جديد.",
"enter_estimate_prefix": "أدخل بادئة رقم التقدير",
"estimate_setting_updated": "تم تحديث إعدادات التقدير بنجاح"
},
"payments": {
"title": "المدفوعات",
"payment_prefix": "بادئة رقم الدفعة",
"payment_settings": "إعدادات الدفعة",
"autogenerate_payment_number": "ترقيم آلي للمدفوعات",
"payment_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام الدفعة تلقائيًا في كل مرة تقوم فيها بإنشاء دفعة جديدة.",
"enter_payment_prefix": "أدخل بادئة رقم الدفعة",
"payment_setting_updated": "تم تحديث إعدادات الدفعة بنجاح"
}
"payments": {
"title": "المدفوعات",
"payment_prefix": "بادئة رقم الدفعة",
"payment_settings": "إعدادات الدفعة",
"autogenerate_payment_number": "ترقيم آلي للمدفوعات",
"payment_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام الدفعة تلقائيًا في كل مرة تقوم فيها بإنشاء دفعة جديدة.",
"enter_payment_prefix": "أدخل بادئة رقم الدفعة",
"payment_setting_updated": "تم تحديث إعدادات الدفعة بنجاح"
}
},
"account_settings": {
"profile_picture": "صورة الملف الشخصي",
@ -750,7 +752,14 @@
"progress_text": "سوف يستغرق التحديث بضع دقائق. يرجى عدم تحديث الشاشة أو إغلاق النافذة قبل انتهاء التحديث",
"update_success": "تم تحديث النظام! يرجى الانتظار حتى يتم إعادة تحميل نافذة المتصفح تلقائيًا.",
"latest_message": "لا يوجد تحديثات متوفرة! لديك حالياً أحدث نسخة.",
"current_version": "النسخة الحالية"
"current_version": "النسخة الحالية",
"download_zip_file": "تنزيل ملف ZIP",
"unzipping_package": "حزمة فك الضغط",
"copying_files": "نسخ الملفات",
"running_migrations": "إدارة عمليات الترحيل",
"finishing_update": "تحديث التشطيب",
"update_failed": "فشل التحديث",
"update_failed_text": "آسف! فشل التحديث الخاص بك في: {step} خطوة"
}
},
"wizard": {
@ -804,22 +813,22 @@
"permission_desc": "فيما يلي قائمة أذونات المجلد المطلوبة حتى يعمل التطبيق. في حالة فشل فحص الإذن ، تأكد من تحديث أذونات المجلد."
},
"mail": {
"host": "خادم البريد",
"port": "منفذ البريد",
"driver": "مشغل البريد",
"secret": "سري",
"mailgun_secret": "الرمز السري لـ Mailgun",
"mailgun_domain": "المجال",
"mailgun_endpoint": "النهاية الطرفية لـ Mailgun",
"ses_secret": "SES الرمز السري",
"ses_key": "SES مفتاح",
"password": "كلمة مرور البريد الالكتروني",
"username": "اسم المستخدم للبريد الإلكتروني",
"mail_config": "إعدادات البريد الالكتروني",
"from_name": "اسم المرسل",
"from_mail": "عنوان البريد الالكتروني للمرسل",
"encryption": "صيغة ا لتشفير",
"mail_config_desc": "أدناه هو نموذج لتكوين برنامج تشغيل البريد الإلكتروني لإرسال رسائل البريد الإلكتروني من التطبيق. يمكنك أيضًا تهيئة موفري الجهات الخارجية مثل Sendgrid و SES إلخ."
"host": "خادم البريد",
"port": "منفذ البريد",
"driver": "مشغل البريد",
"secret": "سري",
"mailgun_secret": "الرمز السري لـ Mailgun",
"mailgun_domain": "المجال",
"mailgun_endpoint": "النهاية الطرفية لـ Mailgun",
"ses_secret": "SES الرمز السري",
"ses_key": "SES مفتاح",
"password": "كلمة مرور البريد الالكتروني",
"username": "اسم المستخدم للبريد الإلكتروني",
"mail_config": "إعدادات البريد الالكتروني",
"from_name": "اسم المرسل",
"from_mail": "عنوان البريد الالكتروني للمرسل",
"encryption": "صيغة ا لتشفير",
"mail_config_desc": "أدناه هو نموذج لتكوين برنامج تشغيل البريد الإلكتروني لإرسال رسائل البريد الإلكتروني من التطبيق. يمكنك أيضًا تهيئة موفري الجهات الخارجية مثل Sendgrid و SES إلخ."
},
"req": {
"system_req": "متطلبات النظام",

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@
},
"general": {
"view_pdf": "View PDF",
"copy_pdf_url": "Copy PDF Url",
"download_pdf": "Download PDF",
"save": "Save",
"cancel": "Cancel",
@ -70,14 +71,14 @@
"go_home": "Go Home",
"test_mail_conf": "Test Mail Configuration",
"send_mail_successfully": "Mail sent successfully",
"setting_updated": "Setting updated successfully",
"select_state": "Select state",
"select_country": "Select Country",
"select_city": "Select City",
"street_1": "Street 1",
"street_2": "Street 2",
"action_failed": "Action Failed"
"action_failed": "Action Failed",
"retry": "Retry"
},
"dashboard": {
"select_year": "Select year",
@ -163,7 +164,7 @@
"select_a_customer": "Select a customer",
"type_or_click": "Type or click to select",
"confirm_delete": "You will not be able to recover this Customer | You will not be able to recover these Customers",
"confirm_delete": "You will not be able to recover this customer and all the related Invoices, Estimates and Payments. | You will not be able to recover these customers and all the related Invoices, Estimates and Payments.",
"created_message": "Customer created successfully",
"updated_message": "Customer updated successfully",
"deleted_message": "Customer deleted successfully | Customers deleted successfully"
@ -230,6 +231,7 @@
"convert_to_invoice": "Convert to Invoice",
"mark_as_sent": "Mark as Sent",
"send_estimate": "Send Estimate",
"resend_estimate": "Resend Estimate",
"record_payment": "Record Payment",
"add_estimate": "Add Estimate",
"save_estimate": "Save Estimate",
@ -316,6 +318,7 @@
"notes": "Notes",
"view": "View",
"send_invoice": "Send Invoice",
"resend_invoice": "Resend Invoice",
"invoice_template": "Invoice Template",
"template": "Template",
"mark_as_sent": "Mark as sent",
@ -426,7 +429,9 @@
"expenses": {
"title": "Expenses",
"expenses_list": "Expenses List",
"select_a_customer": "Select a customer",
"expense_title": "Title",
"customer": "Customer",
"contact": "Contact",
"category": "Category",
"from_date": "From Date",
@ -616,85 +621,85 @@
"updated_message": "Company information updated successfully"
},
"customization": {
"customization": "customization",
"save": "Save",
"addresses": {
"title": "Addresses",
"section_description": "You can set Customer Billing Address and Customer Shipping Address Format (Displayed in PDF only). ",
"customer_billing_address": "Customer Billing Address",
"customer_shipping_address": "Customer Shipping Address",
"company_address": "Company Address",
"insert_fields": "Insert Fields",
"contact": "Contact",
"address": "Address",
"display_name": "Display Name",
"primary_contact_name": "Primary Contact Name",
"email": "Email",
"website": "Website",
"name": "Name",
"country": "Country",
"state": "State",
"city": "City",
"company_name": "Company Name",
"address_street_1": "Address Street 1",
"address_street_2": "Address Street 2",
"phone": "Phone",
"zip_code": "Zip Code",
"address_setting_updated": "Address Setting updated successfully"
},
"updated_message": "Company information updated successfully",
"customization": "customization",
"save": "Save",
"addresses": {
"title": "Addresses",
"section_description": "You can set Customer Billing Address and Customer Shipping Address Format (Displayed in PDF only). ",
"customer_billing_address": "Customer Billing Address",
"customer_shipping_address": "Customer Shipping Address",
"company_address": "Company Address",
"insert_fields": "Insert Fields",
"contact": "Contact",
"address": "Address",
"display_name": "Display Name",
"primary_contact_name": "Primary Contact Name",
"email": "Email",
"website": "Website",
"name": "Name",
"country": "Country",
"state": "State",
"city": "City",
"company_name": "Company Name",
"address_street_1": "Address Street 1",
"address_street_2": "Address Street 2",
"phone": "Phone",
"zip_code": "Zip Code",
"address_setting_updated": "Address Setting updated successfully"
},
"updated_message": "Company information updated successfully",
"invoices": {
"title": "Invoices",
"notes": "Notes",
"invoice_prefix": "Invoice Prefix",
"invoice_settings": "Invoice Settings",
"autogenerate_invoice_number": "Auto-generate Invoice Number",
"invoice_setting_description": "Disable this, If you don't wish to auto-generate invoice numbers each time you create a new invoice.",
"enter_invoice_prefix": "Enter invoice prefix",
"terms_and_conditions": "Terms and Conditions",
"invoice_setting_updated": "Invoice Setting updated successfully"
},
"invoices": {
"title": "Invoices",
"notes": "Notes",
"invoice_prefix": "Invoice Prefix",
"invoice_settings": "Invoice Settings",
"autogenerate_invoice_number": "Auto-generate Invoice Number",
"invoice_setting_description": "Disable this, If you don't wish to auto-generate invoice numbers each time you create a new invoice.",
"enter_invoice_prefix": "Enter invoice prefix",
"terms_and_conditions": "Terms and Conditions",
"invoice_setting_updated": "Invoice Setting updated successfully"
},
"estimates": {
"title": "Estimates",
"estimate_prefix": "Estimate Prefix",
"estimate_settings": "Estimate Settings",
"autogenerate_estimate_number": "Auto-generate Estimate Number",
"estimate_setting_description": "Disable this, If you don't wish to auto-generate estimate numbers each time you create a new estimate.",
"enter_estimate_prefix": "Enter estmiate prefix",
"estimate_setting_updated": "Estimate Setting updated successfully"
},
"estimates": {
"title": "Estimates",
"estimate_prefix": "Estimate Prefix",
"estimate_settings": "Estimate Settings",
"autogenerate_estimate_number": "Auto-generate Estimate Number",
"estimate_setting_description": "Disable this, If you don't wish to auto-generate estimate numbers each time you create a new estimate.",
"enter_estimate_prefix": "Enter estmiate prefix",
"estimate_setting_updated": "Estimate Setting updated successfully"
},
"payments": {
"title": "Payments",
"payment_prefix": "Payment Prefix",
"payment_settings": "Payment Settings",
"autogenerate_payment_number": "Auto-generate Payment Number",
"payment_setting_description": "Disable this, If you don't wish to auto-generate payment numbers each time you create a new payment.",
"enter_payment_prefix": "Enter Payment Prefix",
"payment_setting_updated": "Payment Setting updated successfully",
"payment_mode": "Payment Mode",
"add_payment_mode": "Add Payment Mode",
"mode_name": "Mode Name",
"payment_mode_added": "Payment Mode Added",
"payment_mode_updated": "Payment Mode Updated",
"payment_mode_confirm_delete":"You will not be able to recover this Payment Mode",
"already_in_use": "Payment Mode is already in use",
"deleted_message": "Payment Mode deleted successfully"
},
"payments": {
"title": "Payments",
"payment_prefix": "Payment Prefix",
"payment_settings": "Payment Settings",
"autogenerate_payment_number": "Auto-generate Payment Number",
"payment_setting_description": "Disable this, If you don't wish to auto-generate payment numbers each time you create a new payment.",
"enter_payment_prefix": "Enter Payment Prefix",
"payment_setting_updated": "Payment Setting updated successfully",
"payment_mode": "Payment Mode",
"add_payment_mode": "Add Payment Mode",
"mode_name": "Mode Name",
"payment_mode_added": "Payment Mode Added",
"payment_mode_updated": "Payment Mode Updated",
"payment_mode_confirm_delete": "You will not be able to recover this Payment Mode",
"already_in_use": "Payment Mode is already in use",
"deleted_message": "Payment Mode deleted successfully"
},
"items": {
"title": "Items",
"units": "units",
"add_item_unit": "Add Item Unit",
"unit_name": "Unit Name",
"item_unit_added": "Item Unit Added",
"item_unit_updated": "Item Unit Updated",
"item_unit_confirm_delete":"You will not be able to recover this Item unit",
"already_in_use": "Item Unit is already in use",
"deleted_message": "Item Unit deleted successfully"
}
"items": {
"title": "Items",
"units": "units",
"add_item_unit": "Add Item Unit",
"unit_name": "Unit Name",
"item_unit_added": "Item Unit Added",
"item_unit_updated": "Item Unit Updated",
"item_unit_confirm_delete": "You will not be able to recover this Item unit",
"already_in_use": "Item Unit is already in use",
"deleted_message": "Item Unit deleted successfully"
}
},
"account_settings": {
"profile_picture": "Profile Picture",
@ -785,7 +790,14 @@
"progress_text": "It will just take a few minutes. Please do not refresh the screen or close the window before the update finishes",
"update_success": "App has been updated! Please wait while your browser window gets reloaded automatically.",
"latest_message": "No update available! You are on the latest version.",
"current_version": "Current Version"
"current_version": "Current Version",
"download_zip_file": "Download ZIP file",
"unzipping_package": "Unzipping Package",
"copying_files": "Copying Files",
"running_migrations": "Running Migrations",
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step"
}
},
"wizard": {

View File

@ -62,14 +62,14 @@
"four_zero_four": "404",
"you_got_lost": "Whoops! ¡Te perdiste!",
"go_home": "Volver al Inicio",
"setting_updated": "Configuración actualizada con éxito",
"select_state": "Seleccionar estado",
"select_country": "Seleccionar país",
"select_city": "Seleccionar ciudad",
"street_1": "Calle 1",
"street_2": "Calle 2",
"action_failed": "Accion Fallida"
"action_failed": "Accion Fallida",
"retry": "Procesar de nuevo"
},
"dashboard": {
"select_year": "Seleccionar año",
@ -155,7 +155,7 @@
"select_a_customer": "Selecciona un cliente",
"type_or_click": "Escriba o haga clic para seleccionar",
"confirm_delete": "No podrá recuperar este cliente | No podrá recuperar estos clientes",
"confirm_delete": "No podrá recuperar este cliente y todas las facturas, estimaciones y pagos relacionados. | No podrá recuperar estos clientes y todas las facturas, estimaciones y pagos relacionados.",
"created_message": "Cliente creado con éxito",
"updated_message": "Cliente actualizado con éxito",
"deleted_message": "Cliente eliminado correctamente | Clientes eliminados exitosamente"
@ -412,6 +412,8 @@
"expenses_list": "Lista de gastos",
"expense_title": "Título",
"contact": "Contacto",
"customer": "Cliente",
"select_a_customer": "Selecciona un cliente",
"category": "Categoría",
"from_date": "Desde la fecha",
"to_date": "Hasta la fecha",
@ -600,65 +602,65 @@
"updated_message": "Información de la empresa actualizada con éxito"
},
"customization": {
"customization": "Personalización",
"save": "Guardar",
"addresses": {
"title": "Direcciones",
"section_description": "Puede configurar la Dirección de facturación del cliente y el Formato de dirección de envío del cliente (solo se muestra en PDF).",
"customer_billing_address": "Dirección de facturación del cliente",
"customer_shipping_address": "Dirección de envío del cliente",
"company_address": "Dirección de la compañia",
"insert_fields": "Insertar campos",
"contact": "Contacto",
"address": "Dirección",
"display_name": "Nombre para mostrar",
"primary_contact_name": "Nombre de contacto principal",
"email": "Email",
"website": "Sitio web",
"name": "Nombre",
"country": "País",
"state": "Estado",
"city": "Ciudad",
"company_name": "Nombre de la compañia",
"address_street_1": "Dirección de la calle 1",
"address_street_2": "Dirección de la calle 2",
"phone": "Telefono",
"zip_code": "Codigo postal",
"address_setting_updated": "Configuración de dirección actualizada correctamente"
},
"updated_message": "Información de la empresa actualizada con éxito",
"customization": "Personalización",
"save": "Guardar",
"addresses": {
"title": "Direcciones",
"section_description": "Puede configurar la Dirección de facturación del cliente y el Formato de dirección de envío del cliente (solo se muestra en PDF).",
"customer_billing_address": "Dirección de facturación del cliente",
"customer_shipping_address": "Dirección de envío del cliente",
"company_address": "Dirección de la compañia",
"insert_fields": "Insertar campos",
"contact": "Contacto",
"address": "Dirección",
"display_name": "Nombre para mostrar",
"primary_contact_name": "Nombre de contacto principal",
"email": "Email",
"website": "Sitio web",
"name": "Nombre",
"country": "País",
"state": "Estado",
"city": "Ciudad",
"company_name": "Nombre de la compañia",
"address_street_1": "Dirección de la calle 1",
"address_street_2": "Dirección de la calle 2",
"phone": "Telefono",
"zip_code": "Codigo postal",
"address_setting_updated": "Configuración de dirección actualizada correctamente"
},
"updated_message": "Información de la empresa actualizada con éxito",
"invoices": {
"title": "Facturas",
"notes": "Notas",
"invoice_prefix": "Prefijo de las facturas",
"invoice_settings": "Ajustes de facturas",
"autogenerate_invoice_number": "Autogenerar número de factura",
"invoice_setting_description": "Desactive esto, si no desea generar automáticamente números de factura cada vez que cree una nueva factura.",
"enter_invoice_prefix": "Introduzca el prefijo de factura",
"terms_and_conditions": "Términos y Condiciones",
"invoice_setting_updated": "Configuración de factura actualizada correctamente"
},
"invoices": {
"title": "Facturas",
"notes": "Notas",
"invoice_prefix": "Prefijo de las facturas",
"invoice_settings": "Ajustes de facturas",
"autogenerate_invoice_number": "Autogenerar número de factura",
"invoice_setting_description": "Desactive esto, si no desea generar automáticamente números de factura cada vez que cree una nueva factura.",
"enter_invoice_prefix": "Introduzca el prefijo de factura",
"terms_and_conditions": "Términos y Condiciones",
"invoice_setting_updated": "Configuración de factura actualizada correctamente"
},
"estimates": {
"title": "Estimaciones",
"estimate_prefix": "Prefijo de los presupuestos",
"estimate_settings": "Ajustes de presupuestos",
"autogenerate_estimate_number": "Autogenerar número de presupuesto",
"estimate_setting_description": "Desactive esto, si no desea generar automáticamente números de presupuesto cada vez que cree un nuevo presupuesto.",
"enter_estimate_prefix": "Introduzca el prefijo de presupuesto",
"estimate_setting_updated": "Configuración de presupuestos actualizada correctamente"
},
"estimates": {
"title": "Estimaciones",
"estimate_prefix": "Prefijo de los presupuestos",
"estimate_settings": "Ajustes de presupuestos",
"autogenerate_estimate_number": "Autogenerar número de presupuesto",
"estimate_setting_description": "Desactive esto, si no desea generar automáticamente números de presupuesto cada vez que cree un nuevo presupuesto.",
"enter_estimate_prefix": "Introduzca el prefijo de presupuesto",
"estimate_setting_updated": "Configuración de presupuestos actualizada correctamente"
},
"payments": {
"title": "Payments",
"payment_prefix": "Prefijo de los pagos",
"payment_settings": "Ajustes de pagos",
"autogenerate_payment_number": "Autogenerar número de pago",
"payment_setting_description": "Desactive esto, si no desea generar automáticamente números de pago cada vez que cree un nuevo pago.",
"enter_payment_prefix": "Introduzca el prefijo de pago",
"payment_setting_updated": "Configuración de pagos actualizada correctamente"
}
"payments": {
"title": "Payments",
"payment_prefix": "Prefijo de los pagos",
"payment_settings": "Ajustes de pagos",
"autogenerate_payment_number": "Autogenerar número de pago",
"payment_setting_description": "Desactive esto, si no desea generar automáticamente números de pago cada vez que cree un nuevo pago.",
"enter_payment_prefix": "Introduzca el prefijo de pago",
"payment_setting_updated": "Configuración de pagos actualizada correctamente"
}
},
"account_settings": {
"profile_picture": "Foto de perfil",
@ -749,7 +751,14 @@
"progress_text": "Solo tomará unos minutos. No actualice la pantalla ni cierre la ventana antes de que finalice la actualización.",
"update_success": "¡La aplicación ha sido actualizada! Espere mientras la ventana de su navegador se vuelve a cargar automáticamente.",
"latest_message": "¡Actualización no disponible! Estás en la última versión.",
"current_version": "Versión actual"
"current_version": "Versión actual",
"download_zip_file": "Descargar archivo ZIP",
"unzipping_package": "Descomprimir paquete",
"copying_files": "Copiando documentos",
"running_migrations": "Ejecutar migraciones",
"finishing_update": "Actualización final",
"update_failed": "Actualización fallida",
"update_failed_text": "¡Lo siento! Su actualización falló el: {step} paso"
}
},
"wizard": {

View File

@ -17,6 +17,7 @@
"save": "Sauvegarder",
"cancel": "Annuler",
"update": "Mise à jour",
"deselect": "Retirer",
"download": "Télécharger",
"from_date": "A partir de la date",
"to_date": "À ce jour",
@ -28,7 +29,7 @@
"filter": "Filtre",
"delete": "Effacer",
"edit": "Modifier",
"view": "Vue",
"view": "Voir",
"add_new_item": "Ajoute un nouvel objet",
"clear_all": "Tout effacer",
"showing": "Montrant",
@ -62,14 +63,21 @@
"four_zero_four": "404",
"you_got_lost": "Oups! Vous vous êtes perdus!",
"go_home": "Rentrer chez soi",
"test_mail_conf": "Tester la configuration",
"send_mail_successfully": "Mail envoyé avec succès",
"setting_updated": "Réglage mis à jour avec succès",
"select_state": "Sélectionnez l'état",
"select_country": "Choisissez le pays",
"select_city": "Sélectionnez une ville",
"street_1": "Rue 1",
"street_2": "Rue # 2",
"action_failed": "Action : échoué"
"action_failed": "Action : échoué",
"sort_by": "Trier par",
"ascending": "Ascendant",
"descending": "Descendant",
"subject": "matière",
"message": "Message",
"retry": "Réessayez"
},
"dashboard": {
"select_year": "Sélectionnez l'année",
@ -160,7 +168,7 @@
"select_a_customer": "Sélectionnez un client",
"type_or_click": "Tapez ou cliquez pour sélectionner",
"confirm_delete": "Vous ne pourrez pas récupérer ce client | Vous ne pourrez pas récupérer ces clients",
"confirm_delete": "Vous ne pourrez pas récupérer ce client et toutes les factures, devis et paiements associés. | Vous ne serez pas en mesure de récupérer ces clients et toutes les factures, devis et paiements associés.",
"created_message": "Client créé avec succès",
"updated_message": "Client mis à jour avec succès",
"deleted_message": "Client supprimé avec succès | Les clients supprimés avec succès"
@ -202,24 +210,24 @@
"all": "Tout",
"paid": "Payé",
"unpaid": "Non payé",
"customer": "CLIENT CLIENT",
"ref_no": "REF NO.",
"number": "NOMBRE",
"customer": "Client",
"ref_no": "Réf.",
"number": "N°",
"amount_due": "MONTANT DÛ",
"partially_paid": "Partiellement payé",
"total": "Totale",
"total": "Total",
"discount": "Remise",
"sub_total": "Total partiel",
"estimate_number": "Numéro destimation",
"estimate_number": "N°",
"ref_number": "Numéro de ref",
"contact": "Contact",
"add_item": "Ajouter un article",
"date": "Date",
"due_date": "Date déchéance",
"due_date": "Date d'échéance",
"expiry_date": "Date dexpiration",
"status": "Statut",
"add_tax": "Ajouter une taxe",
"amount": "Montante",
"amount": "Montant",
"action": "action",
"notes": "Remarques",
"tax": "Impôt",
@ -227,7 +235,7 @@
"convert_to_invoice": "Convertir en facture",
"mark_as_sent": "Marquer comme envoyé",
"send_estimate": "Envoyer un devis",
"record_payment": "Record de paiement",
"record_payment": "Enregistrer un paiement",
"add_estimate": "Ajouter un devis",
"save_estimate": "Sauvegarder le devis",
"confirm_conversion": "Vous souhaitez convertir ce devis en facture?",
@ -269,14 +277,17 @@
"quantity": "Quantité",
"price": "Prix",
"discount": "Remise",
"total": "Totale",
"total": "Total",
"total_discount": "Remise totale",
"sub_total": "Total partiel",
"tax": "Impôt",
"amount": "Montante",
"amount": "Montant",
"select_an_item": "Tapez ou cliquez pour sélectionner un élément",
"type_item_description": "Type Item Description (optionnel)"
}
},
"no_matching_estimates": "Aucune estimation correspondante!",
"user_email_does_not_exist": "L'e-mail de l'utilisateur n'existe pas",
"something_went_wrong": "quelque chose a mal tourné"
},
"invoices": {
"title": "Factures",
@ -287,13 +298,13 @@
"all": "Toute",
"paid": "Payé",
"unpaid": "Non payé",
"customer": "CLIENTE CLIENT",
"paid_status": "Statut payé",
"customer": "CLIENT",
"paid_status": "Paiement",
"ref_no": "REF NO.",
"number": "NOMBRE",
"number": "N°",
"amount_due": "MONTANT DÛ",
"partially_paid": "Partiellement payé",
"total": "Totale Total",
"total": "Total",
"discount": "Remise",
"sub_total": "Total partiel",
"invoice": "Facture | Factures",
@ -302,21 +313,23 @@
"contact": "Contact",
"add_item": "Ajouter un article",
"date": "Date",
"due_date": "Date déchéance",
"due_date": "Date d'échéance",
"status": "Statut",
"add_tax": "Ajouter une taxe",
"amount": "Montante Montant",
"amount": "Montant",
"action": "action",
"notes": "Remarques",
"view": "Vue",
"view": "Voir",
"send_invoice": "Envoyer une facture",
"cloned_successfully": "Facture clonée avec succès",
"clone_invoice": "Cloner",
"invoice_template": "Modèle de facture",
"template": "Modèle",
"mark_as_sent": "Marquer comme envoyé",
"invoice_mark_as_sent": "Cette facture sera marquée comme envoyé",
"confirm_send": "Cette facture sera envoyée par courrier électronique au client.",
"invoice_date": "Date de facturation",
"record_payment": "Record de paiement",
"record_payment": "Enregister un paiement",
"add_new_invoice": "Ajouter une nouvelle facture",
"update_expense": "Frais de mise à jour",
"edit_invoice": "Modifier la facture",
@ -335,11 +348,11 @@
"quantity": "Quantité",
"price": "Prix",
"discount": "Remise",
"total": "Totale Total",
"total": "Total",
"total_discount": "Remise totale",
"sub_total": "Total partiel",
"tax": "Impôt",
"amount": "Montante Montant",
"amount": "Montant",
"select_an_item": "Tapez ou cliquez pour sélectionner un élément",
"type_item_description": "Type Item Description (optionnel)"
},
@ -349,7 +362,12 @@
"updated_message": "Facture mise à jour avec succès",
"deleted_message": "La Facture a été supprimée ! | Les Factures ont été supprimées !",
"marked_as_sent_message": "Facture supprimée avec succès | Factures supprimées avec succès",
"invalid_due_amount_message": "Le paiement entré est supérieur au montant total dû pour cette facture. Veuillez vérifier et réessayer"
"invalid_due_amount_message": "Le paiement entré est supérieur au montant total dû pour cette facture. Veuillez vérifier et réessayer",
"confirm_send_invoice": "Cette facture sera envoyée par email au client",
"no_matching_invoices": "Aucune facture correspondante!",
"confirm_clone": "Cette facture sera clonée dans une nouvelle facture",
"user_email_does_not_exist": "L'e-mail de l'utilisateur n'existe pas",
"something_went_wrong": "quelque chose a mal tourné"
},
"credit_notes": {
"title": "Notes de crédit",
@ -357,7 +375,7 @@
"credit_notes": "Notes de crédit",
"contact": "Contact",
"date": "Date",
"amount": "Montante Montant",
"amount": "Montant Montant",
"action": "action",
"credit_number": "Numéro de crédit",
"notes": "Remarques",
@ -368,7 +386,7 @@
"quantity": "Quantité",
"price": "Prix",
"discount": "Remise",
"total": "Totale Total",
"total": "Total",
"total_discount": "Remise totale",
"sub_total": "Total partiel",
"tax": "Impôt"
@ -377,12 +395,12 @@
"payments": {
"title": "Paiements",
"payments_list": "Liste de paiements",
"record_payment": "Record de paiement",
"customer": "Client Client",
"record_payment": "Enregistrer un paiement",
"customer": "Client",
"date": "Date",
"amount": "Montant Montant",
"amount": "Montant",
"action": "action",
"payment_number": "Numéro de paiement",
"payment_number": "N°",
"payment_mode": "Mode de paiement",
"invoice": "Facture dachat",
"note": "Remarque",
@ -391,6 +409,7 @@
"edit_payment": "Modifier le paiement",
"view_payment": "Voir le paiement",
"add_new_payment": "Ajouter un nouveau paiement",
"send_payment_receipt": "Envoyer le reçu",
"save_payment": "Enregistrer le paiement",
"update_payment": "Mettre à jour le paiement",
"payment": "Paiement | Paiements",
@ -403,13 +422,19 @@
"created_message": "Paiement créé avec succès",
"updated_message": "Paiement mis à jour avec succès",
"deleted_message": "Paiement supprimé avec succès | Paiements supprimés avec succès",
"invalid_amount_message": "Le montant du paiement est invalide"
"invalid_amount_message": "Le montant du paiement est invalide",
"confirm_send_payment": "Ce paiement sera envoyé par e-mail au client",
"send_payment_successfully": "Paiement envoyé avec succès",
"user_email_does_not_exist": "L'e-mail de l'utilisateur n'existe pas",
"something_went_wrong": "quelque chose a mal tourné"
},
"expenses": {
"title": "Dépenses",
"expenses_list": "Liste des dépenses",
"expense_title": "Titre",
"contact": "Contact",
"customer": "Client Client",
"select_a_customer": "Sélectionnez un client",
"category": "Catégorie",
"from_date": "A partir de la date",
"to_date": "À ce jour",
@ -423,7 +448,7 @@
"date": "Date de dépense",
"add_expense": "Ajouter une dépense",
"add_new_expense": "Ajouter une nouvelle dépense",
"save_expense": "Économiser des dépenses",
"save_expense": "Enregistrer la dépense",
"update_expense": "Frais de mise à jour",
"download_receipt": "Télécharger le reçu",
"edit_expense": "Modifier les dépenses",
@ -447,7 +472,8 @@
"new_category": "Nouvelle catégorie",
"category": "Catégorie | Les catégories",
"select_a_category": "choisissez une catégorie"
}
},
"customer": "Client"
},
"login": {
"email": "Email",
@ -460,7 +486,8 @@
"enter_email": "Entrer email",
"enter_password": "Entrer le mot de passe",
"retype_password": "Retaper le mot de passe",
"login_placeholder": "mail@example.com"
"login_placeholder": "mail@example.com",
"password_reset_successfully": "Réinitialisation du mot de passe réussie"
},
"reports": {
"title": "rapport",
@ -499,7 +526,7 @@
"invoice": "Facture d'achat",
"invoice_date": "Date de facturation",
"due_date": "Date déchéance",
"amount": "Montante ",
"amount": "Montant ",
"contact_name": "Nom du contact",
"status": "Statut"
},
@ -507,7 +534,7 @@
"estimate": "Devis",
"estimate_date": "Date du devis",
"due_date": "Date d'échéance",
"estimate_number": "Numéro d'estimation",
"estimate_number": "N°",
"ref_number": "Numéro de ref",
"amount": "Montant",
"contact_name": "Nom du contact",
@ -527,6 +554,7 @@
"menu_title": {
"account_settings": "Paramètres du compte",
"company_information": "Informations sur la société",
"customization": "Personnalisation",
"preferences": "Préférences",
"notifications": "Les notifications",
"tax_types": "Types de taxe",
@ -591,10 +619,90 @@
"state": "Etat",
"city": "Ville",
"address": "Adresse",
"zip": "Zip",
"save": "sauver",
"zip": "Code postal",
"save": "Sauvegarder",
"updated_message": "Informations sur la société mises à jour avec succès"
},
"customization": {
"customization": "Personnalisation",
"save": "Sauvegarder",
"addresses": {
"title": "Adresses",
"section_description": "You can set Customer Billing Address and Customer Shipping Address Format (Displayed in PDF only). ",
"customer_billing_address": "Adresse de paiement",
"customer_shipping_address": "Adresse de livraison",
"company_address": "Adresse de l'entreprise",
"insert_fields": "Ajouter des champs",
"contact": "Contact",
"address": "Addresse",
"display_name": "Nom",
"primary_contact_name": "Nom du contact principal",
"email": "Email",
"website": "Website",
"name": "Nom",
"country": "Pays",
"state": "State",
"city": "Ville",
"company_name": "Nom de l'entreprise",
"address_street_1": "Rue",
"address_street_2": "Complément",
"phone": "Téléphone",
"zip_code": "Code postal",
"address_setting_updated": "Adresse mise à jour avec succès"
},
"updated_message": "Informations de l'entreprise mises à jour",
"invoices": {
"title": "Factures",
"notes": "Notes",
"invoice_prefix": "Préfixe",
"invoice_settings": "Paramètre",
"autogenerate_invoice_number": "Générer automatiquement le numéro de facture",
"invoice_setting_description": "Désactivez cette option si vous ne souhaitez pas générer automatiquement les numéros de facture à chaque fois que vous en créez une nouvelle.",
"enter_invoice_prefix": "Ajouter le préfixe de facture",
"terms_and_conditions": "Termes et conditions",
"invoice_setting_updated": "Paramètres de facturation mis à jour"
},
"estimates": {
"title": "Devis",
"estimate_prefix": "Préfixe",
"estimate_settings": "Paramètre",
"autogenerate_estimate_number": "Générer automatiquement le numéro de devis",
"estimate_setting_description": "Désactivez cette option si vous ne souhaitez pas générer automatiquement les numéros de devis à chaque fois que vous en créez un nouveau.",
"estimate_setting_updated": "Paramètres de devis mis à jour"
},
"payments": {
"title": "Paiements",
"payment_prefix": "Préfixe",
"payment_settings": "Paramètre",
"autogenerate_payment_number": "Générer automatiquement le numéro de paiement",
"payment_setting_description": "Désactivez cette option si vous ne souhaitez pas générer automatiquement les numéros de paiement à chaque fois que vous en créez un nouveau.",
"payment_setting_updated": "Les paramètres de paiement ont bien été mis à jour",
"payment_mode": "Mode de paiement",
"add_payment_mode": "Ajouter un mode de paiement",
"mode_name": "Nom",
"payment_mode_added": "Mode de paiement ajouté",
"payment_mode_updated": "Mode de paiement mis à jour",
"payment_mode_confirm_delete": "Êtes-vous sur de supprimer ce mode de paiement ?",
"already_in_use": "Ce mode de paiement existe déjà.",
"deleted_message": "Mode de paiement supprimé avec succès"
},
"items": {
"title": "Articles",
"units": "Unités",
"add_item_unit": "Ajouter une unité",
"unit_name": "Nom",
"item_unit_added": "Unité ajouté",
"item_unit_updated": "Unité mis à jour",
"item_unit_confirm_delete": "Êtes-vous sur de supprimer cette unité ?",
"already_in_use": "Cette unité existe déjà",
"deleted_message": "Unité supprimé avec succès"
}
},
"account_settings": {
"profile_picture": "Image de profil",
"name": "Nom",
@ -602,7 +710,7 @@
"password": "Mot de passe",
"confirm_password": "Confirmez le mot de passe",
"account_settings": "Paramètres du compte",
"save": "sauver",
"save": "Sauvegarder",
"section_description": "Vous pouvez mettre à jour votre nom, votre email et votre mot de passe en utilisant le formulaire ci-dessous.",
"updated_message": "Paramètres du compte mis à jour avec succès"
},
@ -617,10 +725,10 @@
"email": "Envoyer des notifications à",
"description": "Quelles notifications par courrier électronique souhaitez-vous recevoir lorsque quelque chose change?",
"invoice_viewed": "Facture consultée",
"invoice_viewed_desc": "Lorsque votre client visualise la facture envoyée via le tableau de bord du cratère.",
"estimate_viewed": "Estimation vue",
"estimate_viewed_desc": "Lorsque votre client visualise le devis envoyé via le tableau de bord du cratère.",
"save": "sauver",
"invoice_viewed_desc": "Lorsque le client visualise la facture envoyée via le tableau de bord de Neptune.",
"estimate_viewed": "Devis consulté",
"estimate_viewed_desc": "Lorsque le client visualise le devis envoyé via le tableau de bord de Neptune.",
"save": "Sauvegarder",
"email_save_message": "Email enregistré avec succès",
"invoice_viewed_message": "Facture consultée",
"estimate_viewed_message": "Estimation vue",
@ -650,7 +758,7 @@
"description": "Des catégories sont requises pour ajouter des entrées de dépenses. Vous pouvez ajouter ou supprimer ces catégories selon vos préférences.",
"add_new_category": "Ajouter une nouvelle catégorie",
"category_name": "Nom de catégorie",
"category_description": "La description",
"category_description": "Description",
"created_message": "Catégorie de dépenses créée avec succès",
"deleted_message": "La catégorie de dépenses a été supprimée avec succès",
"updated_message": "Catégorie de dépenses mise à jour avec succès",
@ -666,7 +774,7 @@
"discount_setting": "Réglage de remise",
"discount_per_item": "Remise par article",
"discount_setting_description": "Activez cette option si vous souhaitez ajouter une remise à des postes de facture individuels. Par défaut, les remises sont ajoutées directement à la facture.",
"save": "sauver",
"save": "Sauvegarder",
"preference": "Préférence | Préférences",
"general_settings": "Préférences par défaut pour le système.",
"updated_message": "Préférences mises à jour avec succès",
@ -687,7 +795,14 @@
"progress_text": "Cela ne prendra que quelques minutes. S'il vous plaît ne pas actualiser l'écran ou fermer la fenêtre avant la fin de la mise à jour",
"update_success": "App a été mis à jour! Veuillez patienter pendant le rechargement automatique de la fenêtre de votre navigateur.",
"latest_message": "Pas de mise a jour disponible! Vous êtes sur la dernière version.",
"current_version": "Version actuelle"
"current_version": "Version actuelle",
"download_zip_file": "Télécharger le fichier ZIP",
"unzipping_package": "Dézipper le package",
"copying_files": "Copie de fichiers",
"running_migrations": "Exécution de migrations",
"finishing_update": "Mise à jour de finition",
"update_failed": "Mise à jour a échoué",
"update_failed_text": "Désolé! Votre mise à jour a échoué à: {step} étape"
}
},
"wizard": {
@ -772,7 +887,8 @@
"success": {
"mail_variables_save_successfully": "Email configuré avec succès",
"database_variables_save_successfully": "Base de données configurée avec succès."
}
},
"skip": "sauter"
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2020",
@ -781,7 +897,6 @@
"small_businesses": "Petites entreprises ",
"crater_help": "Crater vous aide à suivre vos dépenses, à enregistrer vos paiements et à générer de belles",
"invoices_and_estimates": "factures et devis avec possibilité de choisir plusieurs modèles."
},
"validation": {
"invalid_url": "URL invalide (ex: http://www.crater.com)",
@ -812,6 +927,7 @@
"maximum_options_error": "Maximum de {max} options sélectionnées. Commencez par supprimer une option sélectionnée pour en sélectionner une autre.",
"notes_maxlength": "Les notes ne doivent pas dépasser 255 caractères.",
"address_maxlength": "L'adresse ne doit pas dépasser 255 caractères.",
"ref_number_maxlength": "Le numéro de référence ne doit pas dépasser 255 caractères."
"ref_number_maxlength": "Le numéro de référence ne doit pas dépasser 255 caractères.",
"email_already_taken": "Un compte est déjà associé à cette adresse e-mail."
}
}

View File

@ -6,6 +6,7 @@ import es from './es.json'
import ar from './ar.json'
import de from './de.json'
import pt_BR from './pt-br.json'
import it from './it.json'
Vue.use(VueI18n)
@ -17,8 +18,9 @@ const i18n = new VueI18n({
es,
ar,
de,
pt_BR
}
pt_BR,
it,
},
})
export default i18n

View File

@ -0,0 +1,929 @@
{
"_comment": "Italian - IT translation - by Alessandro Fuda - Milan, Italy - 20/03/2020 - Coronavirus's times But towards spring :-) ",
"navigation": {
"dashboard": "Dashboard",
"customers": "Clienti",
"items": "Commesse",
"invoices": "Fatture",
"expenses": "Spese",
"estimates": "Preventivi",
"payments": "Pagamenti",
"reports": "Reports",
"settings": "Configurazione",
"logout": "Logout"
},
"general": {
"view_pdf": "Vedi PDF",
"download_pdf": "Download PDF",
"save": "Salva",
"cancel": "Elimina",
"update": "Aggiorna",
"deselect": "Deseleziona",
"download": "Download",
"from_date": "Dalla Data",
"to_date": "Alla Data",
"from": "Da",
"to": "A",
"sort_by": "Ordina per",
"ascending": "Crescente",
"descending": "Decrescente",
"subject": "Oggetto",
"message": "Messaggio",
"go_back": "Torna indietro",
"back_to_login": "Torna al Login?",
"home": "Home",
"filter": "Filtro",
"delete": "Elimina",
"edit": "Modifica",
"view": "Visualizza",
"add_new_item": "Aggiungi nuova Commessa",
"clear_all": "Pulisci tutto",
"showing": "Showing",
"of": "di",
"actions": "Azioni",
"subtotal": "SUBTOTALE",
"discount": "SCONTO",
"fixed": "Fissato",
"percentage": "Percentuale",
"tax": "TASSA",
"total_amount": "AMMONTARE TOTALE",
"bill_to": "Fattura a",
"ship_to": "Invia a",
"due": "Dovuto",
"draft": "Bozza",
"sent": "Inviata",
"all": "Tutte",
"select_all": "Seleziona tutto",
"choose_file": "Clicca per selezionare un file",
"choose_template": "Scegli un modello",
"choose": "Scegli",
"remove": "Rimuovi",
"powered_by": "Prodotto da",
"bytefury": "Bytefury",
"select_a_status": "Seleziona uno Stato",
"select_a_tax": "Seleziona una Tassa",
"search": "Cerca",
"are_you_sure": "Sei sicuro/a?",
"list_is_empty": "La lista è vuota.",
"no_tax_found": "Nessuna Tassa trovata!",
"four_zero_four": "404",
"you_got_lost": "Hoops! Ti sei perso",
"go_home": "Vai alla Home",
"test_mail_conf": "Configurazione della mail di test",
"send_mail_successfully": "Mail inviata con successo",
"setting_updated": "Configurazioni aggiornate con successo",
"select_state": "Seleziona lo Stato",
"select_country": "Seleziona Paese",
"select_city": "Seleziona Città",
"street_1": "Indirizzo 1",
"street_2": "Indirizzo 2",
"action_failed": "Errore",
"retry": "Retry"
},
"dashboard": {
"select_year": "Seleziona anno",
"cards": {
"due_amount": "Somma dovuta",
"customers": "Clienti",
"invoices": "Fatture",
"estimates": "Preventivi"
},
"chart_info": {
"total_sales": "Vendite",
"total_receipts": "Ricevute",
"total_expense": "Uscite",
"net_income": "Guadagno netto",
"year": "Seleziona anno"
},
"weekly_invoices": {
"title": "Fatture a settimana"
},
"monthly_chart": {
"title": "Entrate & Uscite"
},
"recent_invoices_card": {
"title": "Fatture insolute",
"due_on": "Data di scadenza",
"customer": "Cliente",
"amount_due": "Ammontare dovuto",
"actions": "Azioni",
"view_all": "Vedi tutto"
},
"recent_estimate_card": {
"title": "Preventivi recenti",
"date": "Data",
"customer": "Cliente",
"amount_due": "Ammontare dovuto",
"actions": "Azioni",
"view_all": "Vedi tutto"
}
},
"tax_types": {
"name": "Nome",
"description": "Descrizione",
"percent": "Percento",
"compound_tax": "Tassa composta"
},
"customers": {
"title": "Clienti",
"add_customer": "Aggiungi cliente",
"contacts_list": "Lista clienti",
"name": "Nome",
"display_name": "Mostra nome",
"primary_contact_name": "Riferimento",
"contact_name": "Nome Contatto",
"amount_due": "Ammontare dovuto",
"email": "Email",
"address": "Indirizzo",
"phone": "Telefono",
"website": "Sito web",
"country": "Paese",
"state": "Stato",
"city": "Città",
"zip_code": "Codice Postale",
"added_on": "Aggiunto il",
"action": "Azione",
"password": "Password",
"street_number": "Numero Civico",
"primary_currency": "Valùta Principale",
"add_new_customer": "Aggiungi nuovo Cliente",
"save_customer": "Salva Cliente",
"update_customer": "Aggiorna Cliente",
"customer": "Cliente | Clienti",
"new_customer": "Nuovo cliente",
"edit_customer": "Modifica Cliente",
"basic_info": "Informazioni",
"billing_address": "Indirizzo di Fatturazione",
"shipping_address": "Indirizzo di Spedizione",
"copy_billing_address": "Copia da Fatturazione",
"no_customers": "Ancora nessun Cliente!",
"no_customers_found": "Nessun cliente trovato!",
"list_of_customers": "Qui ci sarà la lista dei tuoi clienti",
"primary_display_name": "Mostra il Nome Principale",
"select_currency": "Selezione Valùta",
"select_a_customer": "Seleziona Cliente",
"type_or_click": "Scrivi o clicca per selezionare",
"confirm_delete": "Non sarai in grado di recuperare questo cliente e tutte le relative fatture, stime e pagamenti. | Non sarai in grado di recuperare questi clienti e tutte le relative fatture, stime e pagamenti.",
"created_message": "Cliente creato con successo",
"updated_message": "Cliente aggiornato con successo",
"deleted_message": "Cliente cancellato con successo | Clienti cancellati con successo"
},
"items": {
"title": "Commesse",
"items_list": "Lista Commesse",
"name": "Nome",
"unit": "Unità/Tipo",
"description": "Descrizione",
"added_on": "Aggiunto il",
"price": "Prezzo",
"date_of_creation": "Data di creazione",
"action": "Azione",
"add_item": "Aggiungi Commessa",
"save_item": "Salva",
"update_item": "Aggiorna",
"item": "Commessa | Commesse",
"add_new_item": "Aggiungi nuova Commessa",
"new_item": "Nuova Commessa",
"edit_item": "Modifica Commessa",
"no_items": "Ancora nessuna commessa!",
"list_of_items": "Qui ci sarà la lista delle commesse.",
"select_a_unit": "Seleziona",
"taxes": "Imposte",
"item_attached_message": "Non puoi eliminare una Commessa che è già attiva",
"confirm_delete": "Non potrai ripristinare la Commessa | Non potrai ripristinare le Commesse",
"created_message": "Commessa creata con successo",
"updated_message": "Commessa aggiornata con successo",
"deleted_message": "Commessa eliminata con successo | Commesse eliminate con successo"
},
"estimates": {
"title": "Preventivi",
"estimate": "Preventivo | Preventivi",
"estimates_list": "Lista Preventivi",
"days": "{days} Giorni",
"months": "{months} Mese",
"years": "{years} Anno",
"all": "Tutti",
"paid": "Pagato",
"unpaid": "Non pagato",
"customer": "CLIENTE",
"ref_no": "RIF N.",
"number": "NUMERO",
"amount_due": "AMMONTARE DOVUTO",
"partially_paid": "Pagamento Parziale",
"total": "Totale",
"discount": "Sconto",
"sub_total": "Sub Totale",
"estimate_number": "Preventivo Numero",
"ref_number": "Numero di Rif.",
"contact": "Contatto",
"add_item": "Aggiungi un item",
"date": "Data",
"due_date": "Data di pagamento",
"expiry_date": "Data di scadenza",
"status": "Status",
"add_tax": "Aggiungi Imposta",
"amount": "Ammontare",
"action": "Azione",
"notes": "Note",
"tax": "Imposta",
"estimate_template": "Modello",
"convert_to_invoice": "Converti in Fattura",
"mark_as_sent": "Segna come Inviata",
"send_estimate": "Invia preventivo",
"record_payment": "Registra Pagamento",
"add_estimate": "Aggiungi Preventivo",
"save_estimate": "Salva Preventivo",
"confirm_conversion": "Questo preventivo verrà usato per generare una nuova fattura.",
"conversion_message": "Fattura creata",
"confirm_send_estimate": "Questo preventivo verrà inviato al cliente via mail",
"confirm_mark_as_sent": "Questo preventivo verrà contrassegnato come inviato",
"confirm_mark_as_accepted": "Questo preventivo verrà contrassegnato come Accettato",
"confirm_mark_as_rejected": "Questo preventivo verrà contrassegnato come Rifiutato",
"no_matching_estimates": "Nessun preventivo trovato!",
"mark_as_sent_successfully": "Preventivo contrassegnato come inviato con successo",
"send_estimate_successfully": "Preventivo inviato con successo",
"errors": {
"required": "Campo obbligatorio"
},
"accepted": "Accettato",
"sent": "Inviato",
"draft": "Bozza",
"declined": "Rifiutato",
"new_estimate": "Nuovo Preventivo",
"add_new_estimate": "Crea Nuovo Preventivo",
"update_Estimate": "Aggiorna preventivo",
"edit_estimate": "Modifica Preventivo",
"items": "Commesse",
"Estimate": "Preventivo | Preventivi",
"add_new_tax": "Aggiungi una nuova tassa/imposta",
"no_estimates": "Ancora nessun preventivo!",
"list_of_estimates": "Questa sezione conterrà la lista dei preventivi.",
"mark_as_rejected": "Segna come Rifiutato",
"mark_as_accepted": "Segna come Accettato",
"marked_as_accepted_message": "Preventivo contrassegnato come accettato",
"marked_as_rejected_message": "Preventivo contrassegnato come rifiutato",
"confirm_delete": "Non potrai più recuperare questo preventivo | Non potrai più recuperare questi preventivi",
"created_message": "Preventivo creato con successo",
"updated_message": "Preventivo modificato con successo",
"deleted_message": "Preventivo eliminato con successo | Preventivi eliminati con successo",
"user_email_does_not_exist": "La Email utente non esiste",
"something_went_wrong": "Si è verificato un errore",
"item": {
"title": "Titolo Commessa",
"description": "Descrizione",
"quantity": "Quantità",
"price": "Prezzo",
"discount": "Sconto",
"total": "Totale",
"total_discount": "Sconto Totale",
"sub_total": "Sub Totale",
"tax": "Tasse",
"amount": "Ammontare",
"select_an_item": "Scrivi o clicca per selezionare un item",
"type_item_description": "Scrivi una Descrizione (opzionale)"
}
},
"invoices": {
"title": "Fatture",
"invoices_list": "Lista Fatture",
"days": "{days} Giorni",
"months": "{months} Mese",
"years": "{years} Anno",
"all": "Tutti",
"paid": "Pagato",
"unpaid": "Insoluto",
"customer": "CLIENTE",
"paid_status": "STATO DI PAGAMENTO",
"ref_no": "RIF N.",
"number": "NUMERO",
"amount_due": "AMMONTARE DOVUTO",
"partially_paid": "Parzialmente Pagata",
"total": "Totale",
"discount": "Sconto",
"sub_total": "Sub Totale",
"invoice": "Fattura | Fatture",
"invoice_number": "Numero Fattura",
"ref_number": "Rif Numero",
"contact": "Contatto",
"add_item": "Aggiungi Commessa/Item",
"date": "Data",
"due_date": "Data di pagamento",
"status": "Stato",
"add_tax": "Aggiungi Imposta",
"amount": "Ammontare",
"action": "Azione",
"notes": "Note",
"view": "Vedi",
"send_invoice": "Invia Fattura",
"invoice_template": "Modello Fattura",
"template": "Modello",
"mark_as_sent": "Segna come inviata",
"confirm_send_invoice": "Questa fattura sarà inviata via Mail al Cliente",
"invoice_mark_as_sent": "Questa fattura sarà contrassegnata come inviata",
"confirm_send": "Questa fattura sarà inviata via Mail al Cliente",
"invoice_date": "Data fattura",
"record_payment": "Registra Pagamento",
"add_new_invoice": "Aggiungi nuova Fattura",
"update_expense": "Aggiorna Costo",
"edit_invoice": "Modifica Fattura",
"new_invoice": "Nuova Fattura",
"save_invoice": "Salva fattura",
"update_invoice": "Aggiorna Fattura",
"add_new_tax": "Aggiungi tassa/imposta",
"no_invoices": "Ancora nessuna fattura!",
"list_of_invoices": "Questa sezione conterrà la lista delle Fatture.",
"select_invoice": "Seleziona Fattura",
"no_matching_invoices": "Nessuna fattura trovata!",
"mark_as_sent_successfully": "Fattura contassegnata come inviata con successo",
"send_invoice_successfully": "Fattura inviata con successo",
"cloned_successfully": "Fattura copiata con successo",
"clone_invoice": "Clona Fattura",
"confirm_clone": "Questa fattura verrà clonata in una nuova fattura",
"item": {
"title": "Titolo Commessa",
"description": "Descrizione",
"quantity": "Quantità",
"price": "Prezzo",
"discount": "Sconto",
"total": "Totale",
"total_discount": "Sconto Totale",
"sub_total": "Sub Totale",
"tax": "Tassa",
"amount": "Ammontare",
"select_an_item": "Scrivi o clicca per selezionare un item",
"type_item_description": "Scrivi una descrizione (opzionale)"
},
"payment_attached_message": "Una delle fatture selezionate ha già associato un pagamento. Assicurati di eliminare il pagamento associato prima di procedere con la rimozione",
"confirm_delete": "Non potrai recuperare la Fattura cancellata | Non potrai recuperare le Fatture cancellate",
"created_message": "Fattura creata con successo",
"updated_message": "Fattura aggiornata con successo",
"deleted_message": "Fattura cancellata con successo | Fatture cancellate con successo",
"marked_as_sent_message": "Fattura contrassegnata come inviata con successo",
"user_email_does_not_exist": "La Email utente non esiste",
"something_went_wrong": "Si è verificato un errore",
"invalid_due_amount_message": "L'ammontare totale della fattura non può essere inferiore all'ammontare totale pagato per questa fattura. Modifica la fattura o cancella i pagamenti associati per continuare."
},
"credit_notes": {
"title": "Note di Credito",
"credit_notes_list": "Lista Note di Credito",
"credit_notes": "Note di Credito",
"contact": "Contatta",
"date": "Data",
"amount": "Ammontare",
"action": "Azione",
"credit_number": "Numero Credito",
"notes": "Note",
"confirm_delete": "Vuoi cancellare questa nota di credito?",
"item": {
"title": "Titolo",
"description": "Descrizione",
"quantity": "Quantità",
"price": "Prezzo",
"discount": "Sconto",
"total": "Totale",
"total_discount": "Sconto Totale",
"sub_total": "Sub Totale",
"tax": "Tassa"
}
},
"payments": {
"title": "Pagamenti",
"payments_list": "Lista Pagamenti",
"record_payment": "Registra Pagamento",
"customer": "Cliente",
"date": "Data",
"amount": "Ammontare",
"action": "Azione",
"payment_number": "Numero di pagamento",
"payment_mode": "Modalità di Pagamento",
"invoice": "Fattura",
"note": "Note",
"add_payment": "Aggiungi Pagamento",
"new_payment": "Nuovo Pagamento",
"edit_payment": "Modifica Pagamento",
"view_payment": "Vedi Pagamento",
"add_new_payment": "Aggiungi nuovo pagamento",
"send_payment_receipt": "Invia ricevuta di pagamento",
"save_payment": "Salva pagamento",
"update_payment": "Aggiorna pagamento",
"payment": "Pagamento | Pagamenti",
"no_payments": "Ancora nessun pagamento!",
"no_matching_payments": "Non ci sono pagamenti!",
"list_of_payments": "Questa sezione conterrà la lista dei pagamenti.",
"select_payment_mode": "Seleziona modalità di pagamento",
"confirm_send_payment": "Questo pagamento verrà inviato via email al cliente",
"send_payment_successfully": "Pagamento inviato con successo",
"user_email_does_not_exist": "Email utente non esiste",
"something_went_wrong": "si è verificato un errore",
"confirm_delete": "Non potrai recuperare questo pagamento | Non potrai recuperare questi pagamenti",
"created_message": "Pagamento creato con successo",
"updated_message": "Pagamento aggiornato con successo",
"deleted_message": "Pagamento cancellato con successo | Pagamenti cancellati con successo",
"invalid_amount_message": "L'ammontare del pagamento non è valido"
},
"expenses": {
"title": "Spese",
"expenses_list": "Lista Costi",
"expense_title": "Titolo",
"contact": "Contatto",
"category": "Categoria",
"from_date": "Dalla Data",
"to_date": "Alla Data",
"expense_date": "Data",
"description": "Descrizione",
"receipt": "Ricevuta",
"amount": "Ammontare",
"action": "Azione",
"note": "Nota",
"category_id": "Id categoria",
"date": "Data Spesa",
"add_expense": "Aggiungi Spesa",
"add_new_expense": "Aggiungi nuova Spesa",
"save_expense": "Salva la Spesa",
"update_expense": "Aggiorna Spesa",
"download_receipt": "Scarica la Ricevuta",
"edit_expense": "Modifica Spesa",
"new_expense": "Nuova Spesa",
"expense": "Spesa | Spese",
"no_expenses": "Ancora nessuna spesa!",
"list_of_expenses": "Questa sezione conterrà la lista delle Spese.",
"confirm_delete": "Non potrai recuperare questa spesa | Non potrai recuperare queste spese",
"created_message": "Spesa creata con successo",
"updated_message": "Spesa modificata con successo",
"deleted_message": "Spesa cancellata con successo | Spese cancellate con successo",
"categories": {
"categories_list": "Lista categorie",
"title": "Titolo",
"name": "Nome",
"description": "Descrizione",
"amount": "Ammontare",
"actions": "Azioni",
"add_category": "Aggiungi Categoria",
"new_category": "Nuova Categoria",
"category": "Categoria | Categorie",
"select_a_category": "Seleziona Categoria"
}
},
"login": {
"email": "Email",
"password": "Password",
"forgot_password": "Password dimenticata?",
"or_signIn_with": "o fai login con",
"login": "Login",
"register": "Registrati",
"reset_password": "Resetta Password",
"password_reset_successfully": "Password Resettata con successo",
"enter_email": "Inserisci email",
"enter_password": "Inserisci Password",
"retype_password": "Ridigita Password",
"login_placeholder": "mail@example.com"
},
"reports": {
"title": "Report",
"from_date": "Da",
"to_date": "A",
"status": "Status",
"paid": "Pagato",
"unpaid": "Non pagato",
"download_pdf": "Scarica PDF",
"view_pdf": "Vedi PDF",
"update_report": "Aggiorna Report",
"report": "Report | Reports",
"profit_loss": {
"profit_loss": "Guadagni & Perdite",
"to_date": "A",
"from_date": "Da",
"date_range": "Seleziona intervallo date"
},
"sales": {
"sales": "Vendite",
"date_range": "Seleziona intervallo date",
"to_date": "A",
"from_date": "Da",
"report_type": "Tipo di report"
},
"taxes": {
"taxes": "Tasse",
"to_date": "Alla data",
"from_date": "Dalla data",
"date_range": "Seleziona intervallo date"
},
"errors": {
"required": "Campo obbligatorio"
},
"invoices": {
"invoice": "Fattura",
"invoice_date": "Data fattura",
"due_date": "Data di pagamento",
"amount": "Ammontare",
"contact_name": "Nome contatto",
"status": "Status"
},
"estimates": {
"estimate": "Preventivo",
"estimate_date": "Data preventivo",
"due_date": "Data di pagamento",
"estimate_number": "Numero di preventivo",
"ref_number": "Numero di Rif.",
"amount": "Ammontare",
"contact_name": "Nome contatto",
"status": "Status"
},
"expenses": {
"expenses": "Spese",
"category": "Categoria",
"date": "Data",
"amount": "Ammontare",
"to_date": "Alla data",
"from_date": "Dalla data",
"date_range": "Seleziona intervallo date"
}
},
"settings": {
"menu_title": {
"account_settings": "Impostazioni Account",
"company_information": "Informazioni Azienda",
"customization": "Personalizzazione",
"preferences": "Opzioni",
"notifications": "Notifiche",
"tax_types": "Tupi di Tasse",
"expense_category": "Categorie di spesa",
"update_app": "Aggiorna App"
},
"title": "Impostazioni",
"setting": "Opzione | Impostazioni",
"general": "Generale",
"language": "Lingua",
"primary_currency": "Valuta Principale",
"timezone": "Time Zone",
"date_format": "Formato data",
"currencies": {
"title": "Valute",
"currency": "Valùta | Valute",
"currencies_list": "Lista valute",
"select_currency": "Seleziona Valùta",
"name": "Nome",
"code": "Codice",
"symbol": "Simbolo",
"precision": "Precisione",
"thousand_separator": "Separatore migliaia",
"decimal_separator": "Separatore decimali",
"position": "Posizione",
"position_of_symbol": "Posizione del Simbolo",
"right": "Destra",
"left": "Sinistra",
"action": "Azione",
"add_currency": "Aggiungi Valùta"
},
"mail": {
"host": "Mail Host",
"port": "Mail Port",
"driver": "Mail Driver",
"secret": "Secret",
"mailgun_secret": "Mailgun Secret",
"mailgun_domain": "Domain",
"mailgun_endpoint": "Mailgun Endpoint",
"ses_secret": "SES Secret",
"ses_key": "SES Key",
"password": "Mail Password",
"username": "Mail Username",
"mail_config": "Configurazione Mail",
"from_name": "Nome Mittente Mail",
"from_mail": "Indirizzo Mittente Mail",
"encryption": "Mail Encryption",
"mail_config_desc": "Form per Configurazione Driver Mail per invio mail dall'App. Puoi anche configurare providers di terze parti come Sendgrid, SES, etc.."
},
"pdf": {
"title": "Configurazione PDF",
"footer_text": "Testo Footer",
"pdf_layout": "Layout PDF"
},
"company_info": {
"company_info": "Info azienda",
"company_name": "Nome azienda",
"company_logo": "Logo azienda",
"section_description": "Informazioni sulla tua azienda che saranno mostrate in fattura, preventivi ed altri documenti creati dell'applicazione.",
"phone": "Telefono",
"country": "Paese",
"state": "Stato",
"city": "Città",
"address": "Indirizzo",
"zip": "CAP",
"save": "Salva",
"updated_message": "Informazioni Azienda aggiornate con successo."
},
"customization": {
"customization": "personalizzazione",
"save": "Salva",
"addresses": {
"title": "Indirizzi",
"section_description": "Puoi settare l'indirizzo di fatturazione del Cliente e/o il formato dell'indirizzo di spedizione (Mostrato solo sul PDF). ",
"customer_billing_address": "Indirizzo Fatturazione Cliente",
"customer_shipping_address": "Indirizzo spedizione Cliente",
"company_address": "Indirizzo Azienda",
"insert_fields": "Inserisci Campi",
"contact": "Contatto",
"address": "Indirizzo",
"display_name": "Mostra nome",
"primary_contact_name": "Nome contatto primario",
"email": "Email",
"website": "Sito web",
"name": "Nome",
"country": "Paese",
"state": "Stato",
"city": "Città",
"company_name": "Nome Azienda",
"address_street_1": "Indirizzo 1",
"address_street_2": "Indirizzo 2",
"phone": "Telefono",
"zip_code": "CAP/ZIP Code",
"address_setting_updated": "Indirizzo aggiornato con Successo"
},
"updated_message": "Info azienda aggiornate con successo",
"invoices": {
"title": "Fatture",
"notes": "Note",
"invoice_prefix": "Prefisso Fattura",
"invoice_settings": "Impostazioni fattura",
"autogenerate_invoice_number": "Auto genera numero di fattura",
"invoice_setting_description": "Disabilita, se non vuoi auto-generare i numeri delle fatture ogni volta che crei una nuova fattura.",
"enter_invoice_prefix": "Inserisci prefisso fattura",
"terms_and_conditions": "Termini e Condizioni",
"invoice_setting_updated": "Impostazioni fatture aggiornate con successo"
},
"estimates": {
"title": "Preventivi",
"estimate_prefix": "Prefisso Preventivi",
"estimate_settings": "Impostazioni Preventivi",
"autogenerate_estimate_number": "Auto-genera Numero di preventivo",
"estimate_setting_description": "Disabilita, se non vuoi autogenerare il numero di preventivo ogni volta che ne viene creato uno nuovo.",
"enter_estimate_prefix": "Inserisci prefisso preventivo",
"estimate_setting_updated": "Impostazioni preventivi aggiornate con successo"
},
"payments": {
"title": "Pagamenti",
"payment_prefix": "Prefisso Pagamento",
"payment_settings": "Impostazioni Pagamento",
"autogenerate_payment_number": "Auto genera il numero di Pagamento",
"payment_setting_description": "Disabilita, se non vuoi autogenerare il numero di pagamento ogni volta che ne viene creato uno nuovo.",
"enter_payment_prefix": "Inserisci prefisso di pagamento",
"payment_setting_updated": "Impostazioni di pagamento aggiornate con successo",
"payment_mode": "Modalità di pagamento",
"add_payment_mode": "Aggiungi modalità di pagamento",
"mode_name": "Nome modalità",
"payment_mode_added": "Modalità di pagamento aggiunta",
"payment_mode_updated": "Modalità di pagamento aggiornata",
"payment_mode_confirm_delete": "Non potrai ripristinare la modalità di pagamento",
"already_in_use": "Modalità di pagamento già in uso",
"deleted_message": "Payment Mode deleted successfully"
},
"items": {
"title": "Items",
"units": "unità",
"add_item_unit": "Aggiungi Unità Item",
"unit_name": "Nome",
"item_unit_added": "Unità aggiunta",
"item_unit_updated": "Unità aggiornata",
"item_unit_confirm_delete": "Non potrai ripristinare questa unità Item",
"already_in_use": "Unità Item già in uso",
"deleted_message": "Unità item eliminata con successo"
}
},
"account_settings": {
"profile_picture": "Immagine profilo",
"name": "Nome",
"email": "Email",
"password": "Password",
"confirm_password": "Conferma Password",
"account_settings": "Impostazioni Account",
"save": "Salva",
"section_description": "Puoi aggiornare nome email e password utilizzando il form qui sotto.",
"updated_message": "Impostazioni account aggiornate con successo"
},
"user_profile": {
"name": "Nome",
"email": "Email",
"password": "Password",
"confirm_password": "Conferma Password"
},
"notification": {
"title": "Notifica",
"email": "Invia notifiche a",
"description": "Quali notifiche email vorresti ricevere quando qualcosa cambia?",
"invoice_viewed": "Fattura visualizzata",
"invoice_viewed_desc": "Quando il cliente visualizza la fattura inviata via dashboard applicazione.",
"estimate_viewed": "Preventivo visualizzato",
"estimate_viewed_desc": "Quando il cliente visualizza il preventivo inviato dall'applicazione.",
"save": "Salva",
"email_save_message": "Email salvata con successo",
"please_enter_email": "Inserisci Email"
},
"tax_types": {
"title": "Tipi di Imposta",
"add_tax": "Aggiungi Imposta",
"description": "Puoi aggiongere e rimuovere imposte a piacimento. Vengono supportate Tasse differenti per prodotti/servizi specifici esattamento come per le fatture.",
"add_new_tax": "Aggiungi nuova imposta",
"tax_settings": "Impostazioni Imposte",
"tax_per_item": "Tassa per prodotto/servizio",
"tax_name": "Nome imposta",
"compound_tax": "Imposta composta",
"percent": "Percento",
"action": "Azione",
"tax_setting_description": "Abilita se vuoi aggiungere imposte specifiche per prodotti o servizi. Di default le imposte sono aggiunte direttamente alla fattura.",
"created_message": "Tipo di imposta creato con successo",
"updated_message": "Tipo di imposta aggiornato con successo",
"deleted_message": "Tipo di imposta eliminato con successo",
"confirm_delete": "Non potrai ripristinare questo tipo di imposta",
"already_in_use": "Imposta già in uso"
},
"expense_category": {
"title": "Categorie di spesa",
"action": "Azione",
"description": "Le categorie sono necessarie per aggiungere delle voci di spesa. Puoi aggiungere o eliminare queste categorie in base alle tue preferenze.",
"add_new_category": "Aggiungi nuova categoria",
"category_name": "Nome Categoria",
"category_description": "Descrizione",
"created_message": "Categoria di spesa creata con successo",
"deleted_message": "Categoria di spesa eliminata con successo",
"updated_message": "Categoria di spesa aggiornata con successo",
"confirm_delete": "Non potrai ripristinare questa categoria di spesa",
"already_in_use": "Categoria già in uso"
},
"preferences": {
"currency": "Valùta",
"language": "Lingua",
"time_zone": "Time Zone",
"fiscal_year": "Anno finanziario",
"date_format": "Formato Data",
"discount_setting": "Impostazione Sconto",
"discount_per_item": "Sconto Per Item ",
"discount_setting_description": "Abilita se vuoi aggiungere uno sconto ad uno specifica fattura. Di default, lo sconto è aggiunto direttamente in fattura.",
"save": "Salva",
"preference": "Preferenza | Preferenze",
"general_settings": "Impostazioni di default del sistema.",
"updated_message": "Preferenze aggiornate con successo",
"select_language": "seleziona lingua",
"select_time_zone": "Seleziona Time Zone",
"select_date_formate": "Seleziona Formato Data",
"select_financial_year": "Seleziona anno finanziario"
},
"update_app": {
"title": "Aggiorna App",
"description": "Puoi facilmente aggiornare l'app. Aggiorna cliccando sul bottone qui sotto",
"check_update": "Controllo aggiornamenti",
"avail_update": "Aggiornamento disponibile",
"next_version": "Versione successiva",
"update": "Aggiorna ora",
"update_progress": "Aggiornamento in corso...",
"progress_text": "Sarà necessario qualche minuto. Per favore non aggiornare la pagina e non chiudere la finestra prima che l'aggiornamento sia completato",
"update_success": "L'App è aggiornata! Attendi che la pagina venga ricaricata automaticamente.",
"latest_message": "Nessun aggiornamneto disponibile! Sei già alla versione più recente.",
"current_version": "Versione corrente",
"download_zip_file": "Scarica il file ZIP",
"unzipping_package": "Pacchetto di decompressione",
"copying_files": "Copia dei file",
"running_migrations": "Esecuzione delle migrazioni",
"finishing_update": "Aggiornamento di finitura",
"update_failed": "Aggiornamento non riuscito",
"update_failed_text": "Scusate! L'aggiornamento non è riuscito il: passaggio {step}"
}
},
"wizard": {
"account_info": "Informazioni Account",
"account_info_desc": "I dettagli qui sotto verranno usati per creare l'account principale dell'Amministratore. Puoi modificarli in qualsiasi momento dopo esserti loggato come Amministratore.",
"name": "Nome",
"email": "Email",
"password": "Password",
"confirm_password": "Conferma Password",
"save_cont": "Salva & Continua",
"company_info": "Informazioni Azienda",
"company_info_desc": "Questa informazione verrà mostrata nelle fatture. Puoi modificare queste informazione in un momento successivo dalla pagina delle impostazioni.",
"company_name": "Nome Azienda",
"company_logo": "Logo Azienda",
"logo_preview": "Anteprima Logo",
"preferences": "Impostazioni",
"preferences_desc": "Impostazioni di default del sistema.",
"country": "Paese",
"state": "Stato",
"city": "Città",
"address": "Indirizzo",
"street": "Indirizzo1 | Indirizzo2",
"phone": "Telefono",
"zip_code": "CAP/Zip Code",
"go_back": "Torna indietro",
"currency": "Valùta",
"language": "Lingua",
"time_zone": "Time Zone",
"fiscal_year": "Anno Finanziario",
"date_format": "Formato Date",
"from_address": "Indirizzo - Da",
"username": "Username",
"next": "Successivo",
"continue": "Continua",
"skip": "Salta",
"database": {
"database": "URL del sito & database",
"connection": "Connessione Database",
"host": "Database Host",
"port": "Database - Porta",
"password": "Database Password",
"app_url": "App URL",
"username": "Database Username",
"db_name": "Database Nome",
"desc": "Crea un database sul tuo server e setta le credenziali usando il form qui sotto."
},
"permissions": {
"permissions": "Permessi",
"permission_confirm_title": "Sei sicuro di voler continuare?",
"permission_confirm_desc": "Controllo sui permessi Cartelle, fallito",
"permission_desc": "Qui sotto la lista dei permessi richiesti per far funzionare correttamente l'App. Se il controllo dei permessi fallisce, assicurati di aggiornare/modificare i permessi sulle cartelle."
},
"mail": {
"host": "Mail Host",
"port": "Mail - Porta",
"driver": "Mail Driver",
"secret": "Secret",
"mailgun_secret": "Mailgun Secret",
"mailgun_domain": "Domain",
"mailgun_endpoint": "Mailgun Endpoint",
"ses_secret": "SES Secret",
"ses_key": "SES Key",
"password": "Mail Password",
"username": "Mail Username",
"mail_config": "Configurazione Mail",
"from_name": "Nome mittente mail",
"from_mail": "Indirizzo mittente mail",
"encryption": "Tipo di cifratura Mail",
"mail_config_desc": "Form per configurazione del 'driver mail' per inviare emails dall'App. Puoi anche configurare servizi di terze parti come Sendgrid, SES, ecc.."
},
"req": {
"system_req": "Requisiti di Sistema",
"php_req_version": "Php (versione {version} richiesta)",
"check_req": "Controllo Requisiti",
"system_req_desc": "Crater ha alcuni requisiti di sistema. Assicurati che il server ha la versione di php richiesta e tutte le estensioni necessarie."
},
"errors": {
"migrate_failed": "Migrate Failed",
"database_variables_save_error": "Cannot write configuration to .env file. Please check its file permissions",
"mail_variables_save_error": "Email configuration failed.",
"connection_failed": "Database connection failed",
"database_should_be_empty": "Database should be empty"
},
"success": {
"mail_variables_save_successfully": "Email configurata con successo",
"database_variables_save_successfully": "Database configurato con successo."
}
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2020",
"super_simple_invoicing": "Fatturazione super semplice",
"for_freelancer": "per Freelancers &",
"small_businesses": "Medio Piccoli Business ",
"crater_help": "Crater ti aiuta a tracciare le spese, registrare pagamenti e generare graziose",
"invoices_and_estimates": "fatture & preventivi con possibilità di scegliere tra diversi modelli."
},
"validation": {
"invalid_url": "URL non valido (es: http://www.crater.com)",
"required": "Campo obbligatorio",
"email_incorrect": "Email non corretta.",
"email_already_taken": "Email già in uso.",
"email_does_not_exist": "L'utente con questa email non esiste",
"item_unit_already_taken": "Questo nome item è già utilizzato",
"payment_mode_already_taken": "Questa modalità di pagamento è già stata inserita.",
"send_reset_link": "Invia Link di Reset",
"not_yet": "Non ancora? Invia di nuovo",
"password_min_length": "La password deve contenere {count} caratteri",
"name_min_length": "Il nome deve avere almeno {count} lettere.",
"enter_valid_tax_rate": "Inserisci un tasso di imposta valido",
"numbers_only": "Solo numeri.",
"characters_only": "Solo caratteri.",
"password_incorrect": "La Password deve essere identica",
"password_length": "La password deve essere lunga {count} caratteri.",
"qty_must_greater_than_zero": "La quantità deve essere maggiore di zero.",
"price_greater_than_zero": "Il prezzo deve essere maggiore di zero.",
"payment_greater_than_zero": "Il pagamento deve essere maggiore di zero.",
"payment_greater_than_due_amount": "Il pagamento inserito è maggiore di quello indicato in fattura.",
"quantity_maxlength": "La Quantità non può essere maggiore di 20 cifre.",
"price_maxlength": "Il prezzo non può contenere più di 20 cifre.",
"price_minvalue": "Il prezzo deve essere maggiore di 0.",
"amount_maxlength": "La somma non deve contenere più di 20 cifre.",
"amount_minvalue": "La somma deve essere maggiore di 0.",
"description_maxlength": "La Descrizione non deve superare i 255 caratteri.",
"subject_maxlength": "L'Oggetto non deve superare i 100 caratter.",
"message_maxlength": "Il messaggio non può superare i 255 caratteri.",
"maximum_options_error": "Massimo di {max} opzioni selezionate. Per selezionare un'altra opzione deseleziona prima una opzione.",
"notes_maxlength": "Le note non possono superare i 255 caratteri.",
"address_maxlength": "L'Indirizzo non può eccedere i 255 caratteri.",
"ref_number_maxlength": "Il Numero di Riferimento non può superare i 255 caratteri.",
"prefix_maxlength": "Il Prefisso non può superare i 5 caratteri.",
"something_went_wrong": "Si è verificato un errore"
}
}

View File

@ -62,14 +62,14 @@
"four_zero_four": "404",
"you_got_lost": "Ops! Se perdeu!",
"go_home": "Ir para Home",
"setting_updated": "Configuração atualizada com sucesso",
"select_state": "Selecione Estado",
"select_country": "Selecionar pais",
"select_city": "Selecionar cidade",
"street_1": "Rua 1",
"street_2": "Rua # 2",
"action_failed": "Ação: Falhou"
"action_failed": "Ação: Falhou",
"retry": "Atualização falhou"
},
"dashboard": {
"select_year": "Selecione Ano",
@ -155,7 +155,7 @@
"select_a_customer": "Selecione um cliente",
"type_or_click": "Digite ou clique para selecionar",
"confirm_delete": "Você não poderá recuperar este cliente | Você não poderá recuperar esses clientes",
"confirm_delete": "Você não poderá recuperar este cliente e todas as faturas, estimativas e pagamentos relacionados. | Você não poderá recuperar esses clientes e todas as faturas, estimativas e pagamentos relacionados.",
"created_message": "Cliente criado com sucesso",
"updated_message": "Cliente atualizado com sucesso",
"deleted_message": "Cliente excluído com sucesso | Clientes excluídos com sucesso"
@ -414,6 +414,7 @@
"expense_title": "Título",
"contact": "Contato",
"category": "Categoria",
"customer": "Cliente",
"from_date": "A partir da Data",
"to_date": "Até a Data",
"expense_date": "Data",
@ -527,7 +528,7 @@
"date_range": "Selecionar período"
}
},
"settings": {
"settings": {
"menu_title": {
"account_settings": "Configurações da conta",
"company_information": "Informações da Empresa",
@ -601,281 +602,288 @@
"updated_message": "Informações da Empresa atualizadas com sucesso"
},
"customization": {
"customization": "Personalizar",
"save": "Salvar",
"addresses": {
"title": "Endereço",
"section_description": "Você pode definir o endereço de cobrança do cliente e o formato do endereço de entrega do cliente (exibido apenas em PDF).",
"customer_billing_address": "Endereço de Cobrança do Cliente",
"customer_shipping_address": "Endereço de Entrega do Cliente",
"company_address": "Endereço da Empresa",
"insert_fields": "Inserir Campos",
"contact": "Contato",
"address": "Endereço",
"display_name": "Nome em Exibição",
"primary_contact_name": "Nome do Contato Principal",
"email": "Email",
"website": "Website",
"name": "Nome",
"country": "Pais",
"state": "Estado",
"city": "Cidade",
"company_name": "Nome da Empresa",
"address_street_1": "Endereço Rua 1",
"address_street_2": "Endereço Rua 2",
"phone": "Telefone",
"zip_code": "CEP",
"address_setting_updated": "Configuração de Endereço Atualizada com Sucesso"
},
"updated_message": "Informações da Empresa atualizadas com sucesso",
"invoices": {
"title": "Faturas",
"notes": "Notas",
"invoice_prefix": "Fatura Prefixo",
"invoice_settings": "Configrações da Fatura",
"autogenerate_invoice_number": "Gerar automaticamente o número da Fatura",
"invoice_setting_description": "Desative isso, se você não deseja gerar automaticamente números da Fatura sempre que criar uma nova.",
"enter_invoice_prefix": "Digite o prefixo da Fatura",
"terms_and_conditions": "Termos e Condições",
"invoice_setting_updated": "Configuração da Fatura atualizada com sucesso"
},
"estimates": {
"title": "Orçamentos",
"estimate_prefix": "Orçamento Prefixo",
"estimate_settings": "Configurações do Orçamento",
"autogenerate_estimate_number": "Gerar automaticamente o número do Orçamento",
"estimate_setting_description": "Desative isso, se você não deseja gerar automaticamente números do Orçamento sempre que criar um novo.",
"enter_estimate_prefix": "Digite o prefixo do Orçamento",
"estimate_setting_updated": "Configuração do Orçamento atualizada com sucesso"
},
"payments": {
"title": "Pagamentos",
"payment_prefix": "Pagamento Prefixo",
"payment_settings": "Configurações de Pagamento",
"autogenerate_payment_number": "Gerar automaticamente número do Pagamento",
"payment_setting_description": "Desative isso, se você não deseja gerar automaticamente números do Pagamento sempre que criar um novo.",
"enter_payment_prefix": "Digite o Prefixo do Pagamento",
"payment_setting_updated": "Configurações de Pagamento atualizada com sucesso"
}
},
"account_settings": {
"profile_picture": "Foto do Perfil",
"name": "Nome",
"customization": "Personalizar",
"save": "Salvar",
"addresses": {
"title": "Endereço",
"section_description": "Você pode definir o endereço de cobrança do cliente e o formato do endereço de entrega do cliente (exibido apenas em PDF).",
"customer_billing_address": "Endereço de Cobrança do Cliente",
"customer_shipping_address": "Endereço de Entrega do Cliente",
"company_address": "Endereço da Empresa",
"insert_fields": "Inserir Campos",
"contact": "Contato",
"address": "Endereço",
"display_name": "Nome em Exibição",
"primary_contact_name": "Nome do Contato Principal",
"email": "Email",
"password": "Senha",
"confirm_password": "Confirmar Senha",
"account_settings": "Configurações da conta",
"save": "Salvar",
"section_description": "Você pode atualizar seu nome, email e senha usando o formulário abaixo.",
"updated_message": "Configurações da conta atualizadas com sucesso"
},
"user_profile": {
"website": "Website",
"name": "Nome",
"email": "Email",
"password": "Password",
"confirm_password": "Confirmar Senha"
},
"notification": {
"title": "Notificação",
"email": "Enviar Notificações para",
"description": "Quais notificações por email você gostaria de receber quando algo mudar?",
"invoice_viewed": "Fatura Visualizada",
"invoice_viewed_desc": "Quando o seu cliente visualiza uma Fatura enviada pelo painel do Crater.",
"estimate_viewed": "Orçamento Visualizado",
"estimate_viewed_desc": "Quando o seu cliente visualiza um Orçamento enviada pelo painel do Crater.",
"save": "Salvar",
"email_save_message": "E-mail salvo com sucesso",
"please_enter_email": "Por favor digite um E-mail"
},
"tax_types": {
"title": "Tipos de Impostos",
"add_tax": "Adicionar Imposto",
"description": "Você pode adicionar ou remover impostos conforme desejar. O Crater suporta impostos sobre itens individuais e também na Fatura.",
"add_new_tax": "Adicionar Novo Imposto",
"tax_settings": "Configurações de Impostos",
"tax_per_item": "Imposto por Item",
"tax_name": "Nome do Imposto",
"compound_tax": "Imposto Composto",
"percent": "Porcentagem",
"action": "Ação",
"tax_setting_description": "Habilite isso se desejar adicionar Impostos a itens da Fatura Idividualmente. Por padrão, os impostos são adicionados diretamente à Fatura.",
"created_message": "Tipo de Imposto criado com sucesso",
"updated_message": "Tipo de Imposto Atualizado com sucesso",
"deleted_message": "Tipo de Imposto Deletado com sucesso",
"confirm_delete": "Você não poderá recuperar este tipo de Imposto",
"already_in_use": "O Imposto já está em uso"
},
"expense_category": {
"title": "Categoria de Despesa",
"action": "Ação",
"description": "As Categorias são necessárias para adicionar entradas de Despesas. Você pode adicionar ou remover essas Categorias de acordo com sua preferência.",
"add_new_category": "Adicionar Nova Categoria",
"category_name": "Nome da Categoria",
"category_description": "Descrição",
"created_message": "Categoria de Despesa criada com sucesso",
"deleted_message": "Categoria de Despesa excluída com sucesso",
"updated_message": "Categoria de Despesa atualizada com sucesso",
"confirm_delete": "Você não poderá recuperar esta Categoria de Despesa",
"already_in_use": "A categoria já está em uso"
},
"preferences": {
"currency": "Moeda",
"language": "Idioma",
"time_zone": "Fuso Horário",
"fiscal_year": "Ano Financeiro",
"date_format": "Formato da Data",
"discount_setting": "Configuração de Desconto",
"discount_per_item": "Desconto por Item ",
"discount_setting_description": "Habilite isso se desejar adicionar desconto a itens de Fatura individualmente. Por padrão, o desconto é adicionado diretamente à Fatura.",
"save": "Salvar",
"preference": "Preferência | Preferências",
"general_settings": "Preferências padrão para o sistema.",
"updated_message": "Preferências atualizadas com sucesso",
"select_language": "Selecione um Idioma",
"select_time_zone": "Selecione um fuso horário",
"select_date_formate": "Selecione um formato de data",
"select_financial_year": "Selecione o ano financeiro"
},
"update_app": {
"title": "Atualizar Aplicativo",
"description": "Você pode atualizar facilmente o Crater, verifique se hà novas atualizações, clicando no botão abaixo",
"check_update": "Verifique se há atualizações",
"avail_update": "Nova atualização disponível",
"next_version": "Próxima versão",
"update": "Atualizar agora",
"update_progress": "Atualização em progresso...",
"progress_text": "Levará apenas alguns minutos. Não atualize a tela ou feche a janela antes que a atualização seja concluída",
"update_success": "O aplicativo foi atualizado! Aguarde enquanto a janela do navegador é recarregada automaticamente.",
"latest_message": "Nenhuma atualização disponível! Você está na versão mais recente.",
"current_version": "Versão Atual"
}
},
"wizard": {
"account_info": "Informação da conta",
"account_info_desc": "Os detalhes abaixo serão usados para criar a conta principal do administrador. Além disso, você pode alterar os detalhes a qualquer momento após o login.",
"name": "Nome",
"email": "Email",
"password": "Senha",
"confirm_password": "Confirmar Senha",
"save_cont": "Salvar e Continuar",
"company_info": "Informação da Empresa",
"company_info_desc": "Esta informação será exibida nas Faturas. Observe que você pode editar isso mais tarde na página de configurações.",
"company_name": "Nome da Empresa",
"company_logo": "Logotipo da Empresa",
"logo_preview": "Previsualizar Logotipo",
"preferences": "Preferências",
"preferences_desc": "Preferências padrão para o sistema.",
"country": "Pais",
"state": "Estado",
"city": "Cidade",
"address": "Endereço",
"street": "Rua 1 | Rua 2",
"company_name": "Nome da Empresa",
"address_street_1": "Endereço Rua 1",
"address_street_2": "Endereço Rua 2",
"phone": "Telefone",
"zip_code": "CEP",
"go_back": "Voltar",
"currency": "Moeda",
"language": "Idioma",
"time_zone": "Fuso Horário",
"fiscal_year": "Ano Financeiro",
"date_format": "Formato de Data",
"from_address": "Do Endereço",
"username": "Nome de Usuário",
"next": "Próximo",
"continue": "Continuar",
"skip": "Pular",
"database": {
"database": "URL do Site e Base de Dados",
"connection": "Conexão da Base de Dados",
"host": "Host da Base de Dados",
"port": "Porta da Base de Dados",
"password": "Senha da Base de Dados",
"app_url": "URL do Aplicativo",
"username": "Usuário da Base de Dados",
"db_name": "Nome da Base de Dados",
"desc": "Crie um Banco de Dados no seu servidor e defina as credenciais usando o formulário abaixo."
},
"permissions": {
"permissions": "Permissões",
"permission_confirm_title": "Você tem certeza que quer continuar?",
"permission_confirm_desc": "Falha na verificação de permissão da pasta",
"permission_desc": "Abaixo está a lista de permissões de pasta que são necessárias para que o aplicativo funcione. Se a verificação da permissão falhar, atualize as permissões da pasta."
},
"mail": {
"host": "Host do email",
"port": "Porta do email",
"driver": "Driver do email",
"secret": "Segredo",
"mailgun_secret": "Segredo do Mailgun",
"mailgun_domain": "Domínio",
"mailgun_endpoint": "Endpoint do Mailgun",
"ses_secret": "Segredo do SES",
"ses_key": "Chave SES",
"password": "Senha do email",
"username": "Nome do Usuário do email",
"mail_config": "Configuração de email",
"from_name": "Nome do email",
"from_mail": "Endereço de email",
"encryption": "Criptografia de email",
"mail_config_desc": "Abaixo está o formulário para configurar o driver de email que será usado para enviar emails do aplicativo. Você também pode configurar provedores de terceiros como Sendgrid, SES etc."
},
"req": {
"system_req": "Requisitos de Sistema",
"php_req_version": "PHP (versão {version} obrigatória)",
"check_req": "Verificar Requisitos",
"system_req_desc": "O Crater tem alguns requisitos de servidor. Verifique se o seu servidor possui a versão do PHP necessária e todas as extensões mencionadas abaixo."
},
"errors": {
"migrate_failed": "Falha na migração",
"database_variables_save_error": "Não é possível gravar a configuração no arquivo .env. Por favor, verifique suas permissões de arquivo",
"mail_variables_save_error": "A configuração do email falhou.",
"connection_failed": "Falha na conexão com o banco de dados",
"database_should_be_empty": "O banco de dados deve estar vazio"
},
"success": {
"mail_variables_save_successfully": "Email configurado com sucesso",
"database_variables_save_successfully": "Banco de dados configurado com sucesso."
}
"address_setting_updated": "Configuração de Endereço Atualizada com Sucesso"
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2020",
"super_simple_invoicing": "Faturamento super simples",
"for_freelancer": "Para Freelancers &",
"small_businesses": "Pequenos Negócios ",
"crater_help": "Crater ajuda a rastrear despesas, registrar pagamentos e gerar belas",
"invoices_and_estimates": "Faturas e Orçamentos com capacidade de escolher vários modelos."
"updated_message": "Informações da Empresa atualizadas com sucesso",
"invoices": {
"title": "Faturas",
"notes": "Notas",
"invoice_prefix": "Fatura Prefixo",
"invoice_settings": "Configrações da Fatura",
"autogenerate_invoice_number": "Gerar automaticamente o número da Fatura",
"invoice_setting_description": "Desative isso, se você não deseja gerar automaticamente números da Fatura sempre que criar uma nova.",
"enter_invoice_prefix": "Digite o prefixo da Fatura",
"terms_and_conditions": "Termos e Condições",
"invoice_setting_updated": "Configuração da Fatura atualizada com sucesso"
},
"validation": {
"invalid_url": "url inválidas (ex: http://www.crater.com)",
"required": "Campo obrigatório",
"email_incorrect": "E-mail incorreto",
"email_already_taken": "O email já foi recebido.",
"email_does_not_exist": "O usuário com determinado email não existe",
"send_reset_link": "Enviar link de redefinição",
"not_yet": "Ainda não? Envie novamente",
"password_min_length": "A senha deve conter {count} caracteres",
"name_min_length": "O nome deve ter pelo menos {count} letras.",
"enter_valid_tax_rate": "Insira uma taxa de imposto válida",
"numbers_only": "Apenas Números.",
"characters_only": "Apenas Caracteres.",
"password_incorrect": "As senhas devem ser idênticas",
"password_length": "A senha deve ter {count} caracteres.",
"qty_must_greater_than_zero": "A quantidade deve ser maior que zero.",
"price_greater_than_zero": "O preço deve ser maior que zero.",
"payment_greater_than_zero": "O pagamento deve ser maior que zero.",
"payment_greater_than_due_amount": "O pagamento inserido é mais do que o valor devido desta fatura.",
"quantity_maxlength": "A quantidade não deve exceder 20 dígitos.",
"price_maxlength": "O preço não deve ser superior a 20 dígitos.",
"price_minvalue": "O preço deve ser maior que 0.",
"amount_maxlength": "Montante não deve ser superior a 20 dígitos.",
"amount_minvalue": "Montante deve ser maior que zero",
"description_maxlength": "A descrição não deve ter mais que 255 caracteres.",
"maximum_options_error": "Máximo de {max} opções selecionadas. Primeiro remova uma opção selecionada para selecionar outra.",
"notes_maxlength": "As anotações não devem ter mais que 255 caracteres.",
"address_maxlength": "O endereço não deve ter mais que 255 caracteres.",
"ref_number_maxlength": "O número de referência não deve ter mais que 255 caracteres.",
"prefix_maxlength": "O prefixo não deve ter mais que 5 caracteres."
"estimates": {
"title": "Orçamentos",
"estimate_prefix": "Orçamento Prefixo",
"estimate_settings": "Configurações do Orçamento",
"autogenerate_estimate_number": "Gerar automaticamente o número do Orçamento",
"estimate_setting_description": "Desative isso, se você não deseja gerar automaticamente números do Orçamento sempre que criar um novo.",
"enter_estimate_prefix": "Digite o prefixo do Orçamento",
"estimate_setting_updated": "Configuração do Orçamento atualizada com sucesso"
},
"payments": {
"title": "Pagamentos",
"payment_prefix": "Pagamento Prefixo",
"payment_settings": "Configurações de Pagamento",
"autogenerate_payment_number": "Gerar automaticamente número do Pagamento",
"payment_setting_description": "Desative isso, se você não deseja gerar automaticamente números do Pagamento sempre que criar um novo.",
"enter_payment_prefix": "Digite o Prefixo do Pagamento",
"payment_setting_updated": "Configurações de Pagamento atualizada com sucesso"
}
},
"account_settings": {
"profile_picture": "Foto do Perfil",
"name": "Nome",
"email": "Email",
"password": "Senha",
"confirm_password": "Confirmar Senha",
"account_settings": "Configurações da conta",
"save": "Salvar",
"section_description": "Você pode atualizar seu nome, email e senha usando o formulário abaixo.",
"updated_message": "Configurações da conta atualizadas com sucesso"
},
"user_profile": {
"name": "Nome",
"email": "Email",
"password": "Password",
"confirm_password": "Confirmar Senha"
},
"notification": {
"title": "Notificação",
"email": "Enviar Notificações para",
"description": "Quais notificações por email você gostaria de receber quando algo mudar?",
"invoice_viewed": "Fatura Visualizada",
"invoice_viewed_desc": "Quando o seu cliente visualiza uma Fatura enviada pelo painel do Crater.",
"estimate_viewed": "Orçamento Visualizado",
"estimate_viewed_desc": "Quando o seu cliente visualiza um Orçamento enviada pelo painel do Crater.",
"save": "Salvar",
"email_save_message": "E-mail salvo com sucesso",
"please_enter_email": "Por favor digite um E-mail"
},
"tax_types": {
"title": "Tipos de Impostos",
"add_tax": "Adicionar Imposto",
"description": "Você pode adicionar ou remover impostos conforme desejar. O Crater suporta impostos sobre itens individuais e também na Fatura.",
"add_new_tax": "Adicionar Novo Imposto",
"tax_settings": "Configurações de Impostos",
"tax_per_item": "Imposto por Item",
"tax_name": "Nome do Imposto",
"compound_tax": "Imposto Composto",
"percent": "Porcentagem",
"action": "Ação",
"tax_setting_description": "Habilite isso se desejar adicionar Impostos a itens da Fatura Idividualmente. Por padrão, os impostos são adicionados diretamente à Fatura.",
"created_message": "Tipo de Imposto criado com sucesso",
"updated_message": "Tipo de Imposto Atualizado com sucesso",
"deleted_message": "Tipo de Imposto Deletado com sucesso",
"confirm_delete": "Você não poderá recuperar este tipo de Imposto",
"already_in_use": "O Imposto já está em uso"
},
"expense_category": {
"title": "Categoria de Despesa",
"action": "Ação",
"description": "As Categorias são necessárias para adicionar entradas de Despesas. Você pode adicionar ou remover essas Categorias de acordo com sua preferência.",
"add_new_category": "Adicionar Nova Categoria",
"category_name": "Nome da Categoria",
"category_description": "Descrição",
"created_message": "Categoria de Despesa criada com sucesso",
"deleted_message": "Categoria de Despesa excluída com sucesso",
"updated_message": "Categoria de Despesa atualizada com sucesso",
"confirm_delete": "Você não poderá recuperar esta Categoria de Despesa",
"already_in_use": "A categoria já está em uso"
},
"preferences": {
"currency": "Moeda",
"language": "Idioma",
"time_zone": "Fuso Horário",
"fiscal_year": "Ano Financeiro",
"date_format": "Formato da Data",
"discount_setting": "Configuração de Desconto",
"discount_per_item": "Desconto por Item ",
"discount_setting_description": "Habilite isso se desejar adicionar desconto a itens de Fatura individualmente. Por padrão, o desconto é adicionado diretamente à Fatura.",
"save": "Salvar",
"preference": "Preferência | Preferências",
"general_settings": "Preferências padrão para o sistema.",
"updated_message": "Preferências atualizadas com sucesso",
"select_language": "Selecione um Idioma",
"select_time_zone": "Selecione um fuso horário",
"select_date_formate": "Selecione um formato de data",
"select_financial_year": "Selecione o ano financeiro"
},
"update_app": {
"title": "Atualizar Aplicativo",
"description": "Você pode atualizar facilmente o Crater, verifique se hà novas atualizações, clicando no botão abaixo",
"check_update": "Verifique se há atualizações",
"avail_update": "Nova atualização disponível",
"next_version": "Próxima versão",
"update": "Atualizar agora",
"update_progress": "Atualização em progresso...",
"progress_text": "Levará apenas alguns minutos. Não atualize a tela ou feche a janela antes que a atualização seja concluída",
"update_success": "O aplicativo foi atualizado! Aguarde enquanto a janela do navegador é recarregada automaticamente.",
"latest_message": "Nenhuma atualização disponível! Você está na versão mais recente.",
"current_version": "Versão Atual",
"download_zip_file": "Baixar arquivo ZIP",
"unzipping_package": "Descompactando o pacote",
"copying_files": "Copiando arquivos",
"running_migrations": "Executando migrações",
"finishing_update": "Atualização de acabamento",
"update_failed": "Atualização falhou",
"update_failed_text": "Desculpa! Sua atualização falhou em: {step} step"
}
},
"wizard": {
"account_info": "Informação da conta",
"account_info_desc": "Os detalhes abaixo serão usados para criar a conta principal do administrador. Além disso, você pode alterar os detalhes a qualquer momento após o login.",
"name": "Nome",
"email": "Email",
"password": "Senha",
"confirm_password": "Confirmar Senha",
"save_cont": "Salvar e Continuar",
"company_info": "Informação da Empresa",
"company_info_desc": "Esta informação será exibida nas Faturas. Observe que você pode editar isso mais tarde na página de configurações.",
"company_name": "Nome da Empresa",
"company_logo": "Logotipo da Empresa",
"logo_preview": "Previsualizar Logotipo",
"preferences": "Preferências",
"preferences_desc": "Preferências padrão para o sistema.",
"country": "Pais",
"state": "Estado",
"city": "Cidade",
"address": "Endereço",
"street": "Rua 1 | Rua 2",
"phone": "Telefone",
"zip_code": "CEP",
"go_back": "Voltar",
"currency": "Moeda",
"language": "Idioma",
"time_zone": "Fuso Horário",
"fiscal_year": "Ano Financeiro",
"date_format": "Formato de Data",
"from_address": "Do Endereço",
"username": "Nome de Usuário",
"next": "Próximo",
"continue": "Continuar",
"skip": "Pular",
"database": {
"database": "URL do Site e Base de Dados",
"connection": "Conexão da Base de Dados",
"host": "Host da Base de Dados",
"port": "Porta da Base de Dados",
"password": "Senha da Base de Dados",
"app_url": "URL do Aplicativo",
"username": "Usuário da Base de Dados",
"db_name": "Nome da Base de Dados",
"desc": "Crie um Banco de Dados no seu servidor e defina as credenciais usando o formulário abaixo."
},
"permissions": {
"permissions": "Permissões",
"permission_confirm_title": "Você tem certeza que quer continuar?",
"permission_confirm_desc": "Falha na verificação de permissão da pasta",
"permission_desc": "Abaixo está a lista de permissões de pasta que são necessárias para que o aplicativo funcione. Se a verificação da permissão falhar, atualize as permissões da pasta."
},
"mail": {
"host": "Host do email",
"port": "Porta do email",
"driver": "Driver do email",
"secret": "Segredo",
"mailgun_secret": "Segredo do Mailgun",
"mailgun_domain": "Domínio",
"mailgun_endpoint": "Endpoint do Mailgun",
"ses_secret": "Segredo do SES",
"ses_key": "Chave SES",
"password": "Senha do email",
"username": "Nome do Usuário do email",
"mail_config": "Configuração de email",
"from_name": "Nome do email",
"from_mail": "Endereço de email",
"encryption": "Criptografia de email",
"mail_config_desc": "Abaixo está o formulário para configurar o driver de email que será usado para enviar emails do aplicativo. Você também pode configurar provedores de terceiros como Sendgrid, SES etc."
},
"req": {
"system_req": "Requisitos de Sistema",
"php_req_version": "PHP (versão {version} obrigatória)",
"check_req": "Verificar Requisitos",
"system_req_desc": "O Crater tem alguns requisitos de servidor. Verifique se o seu servidor possui a versão do PHP necessária e todas as extensões mencionadas abaixo."
},
"errors": {
"migrate_failed": "Falha na migração",
"database_variables_save_error": "Não é possível gravar a configuração no arquivo .env. Por favor, verifique suas permissões de arquivo",
"mail_variables_save_error": "A configuração do email falhou.",
"connection_failed": "Falha na conexão com o banco de dados",
"database_should_be_empty": "O banco de dados deve estar vazio"
},
"success": {
"mail_variables_save_successfully": "Email configurado com sucesso",
"database_variables_save_successfully": "Banco de dados configurado com sucesso."
}
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2020",
"super_simple_invoicing": "Faturamento super simples",
"for_freelancer": "Para Freelancers &",
"small_businesses": "Pequenos Negócios ",
"crater_help": "Crater ajuda a rastrear despesas, registrar pagamentos e gerar belas",
"invoices_and_estimates": "Faturas e Orçamentos com capacidade de escolher vários modelos."
},
"validation": {
"invalid_url": "url inválidas (ex: http://www.crater.com)",
"required": "Campo obrigatório",
"email_incorrect": "E-mail incorreto",
"email_already_taken": "O email já foi recebido.",
"email_does_not_exist": "O usuário com determinado email não existe",
"send_reset_link": "Enviar link de redefinição",
"not_yet": "Ainda não? Envie novamente",
"password_min_length": "A senha deve conter {count} caracteres",
"name_min_length": "O nome deve ter pelo menos {count} letras.",
"enter_valid_tax_rate": "Insira uma taxa de imposto válida",
"numbers_only": "Apenas Números.",
"characters_only": "Apenas Caracteres.",
"password_incorrect": "As senhas devem ser idênticas",
"password_length": "A senha deve ter {count} caracteres.",
"qty_must_greater_than_zero": "A quantidade deve ser maior que zero.",
"price_greater_than_zero": "O preço deve ser maior que zero.",
"payment_greater_than_zero": "O pagamento deve ser maior que zero.",
"payment_greater_than_due_amount": "O pagamento inserido é mais do que o valor devido desta fatura.",
"quantity_maxlength": "A quantidade não deve exceder 20 dígitos.",
"price_maxlength": "O preço não deve ser superior a 20 dígitos.",
"price_minvalue": "O preço deve ser maior que 0.",
"amount_maxlength": "Montante não deve ser superior a 20 dígitos.",
"amount_minvalue": "Montante deve ser maior que zero",
"description_maxlength": "A descrição não deve ter mais que 255 caracteres.",
"maximum_options_error": "Máximo de {max} opções selecionadas. Primeiro remova uma opção selecionada para selecionar outra.",
"notes_maxlength": "As anotações não devem ter mais que 255 caracteres.",
"address_maxlength": "O endereço não deve ter mais que 255 caracteres.",
"ref_number_maxlength": "O número de referência não deve ter mais que 255 caracteres.",
"prefix_maxlength": "O prefixo não deve ter mais que 5 caracteres."
}
}

View File

@ -21,13 +21,6 @@ export const login = ({ commit, dispatch, state }, data) => {
window.toastr['success']('Login Successful')
resolve(response)
}).catch(err => {
if (err.response.data.error === 'invalid_credentials') {
window.toastr['error']('Invalid Credentials')
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', err.message)
}
commit(types.AUTH_ERROR, err.response)
Ls.remove('auth.token')
reject(err)

View File

@ -42,7 +42,6 @@ export default {
},
[types.ADD_ITEM_UNIT] (state, data) {
state.itemUnits.push(data.unit)
state.itemUnits = [data.unit, ...state.itemUnits]
},

View File

@ -40,7 +40,6 @@ export default {
},
[types.ADD_PAYMENT_MODE] (state, data) {
state.paymentModes.push(data.paymentMethod)
state.paymentModes = [data.paymentMethod, ...state.paymentModes]
},

View File

@ -46,7 +46,7 @@
</div>
</div>
<base-button type="submit" color="theme">{{ $t('login.login') }}</base-button>
<base-button :loading="isLoading" type="submit" color="theme">{{ $t('login.login') }}</base-button>
<!-- <div class="social-links">
@ -87,7 +87,8 @@ export default {
password: '',
remember: ''
},
submitted: false
submitted: false,
isLoading: false
}
},
validations: {
@ -98,7 +99,7 @@ export default {
},
password: {
required,
minLength: minLength(5)
minLength: minLength(8)
}
}
},
@ -113,7 +114,6 @@ export default {
}
this.isLoading = true
this.login(this.loginData).then((res) => {
this.$router.push('/admin/dashboard')
this.isLoading = false

View File

@ -4,16 +4,12 @@
<h3 class="page-title">{{ $t('estimates.title') }}</h3>
<ol class="breadcrumb">
<li class="breadcrumb-item">
<router-link
slot="item-title"
to="dashboard">
<router-link slot="item-title" to="dashboard">
{{ $t('general.home') }}
</router-link>
</li>
<li class="breadcrumb-item">
<router-link
slot="item-title"
to="#">
<router-link slot="item-title" to="#">
{{ $tc('estimates.estimate', 2) }}
</router-link>
</li>
@ -33,11 +29,9 @@
</base-button>
</div>
<router-link slot="item-title" class="col-xs-2" to="estimates/create">
<base-button
size="large"
icon="plus"
color="theme" >
{{ $t('estimates.new_estimate') }}</base-button>
<base-button size="large" icon="plus" color="theme">
{{ $t('estimates.new_estimate') }}</base-button
>
</router-link>
</div>
</div>
@ -46,7 +40,7 @@
<div v-show="showFilters" class="filter-section">
<div class="filter-container">
<div class="filter-customer">
<label>{{ $tc('customers.customer',1) }} </label>
<label>{{ $tc('customers.customer', 1) }} </label>
<base-customer-select
ref="customerSelect"
@select="onSelectCustomer"
@ -85,21 +79,28 @@
</div>
<div class="filter-estimate">
<label>{{ $t('estimates.estimate_number') }}</label>
<base-input
v-model="filters.estimate_number"
icon="hashtag"/>
<base-input v-model="filters.estimate_number" icon="hashtag" />
</div>
</div>
<label class="clear-filter" @click="clearFilter">{{ $t('general.clear_all') }}</label>
<label class="clear-filter" @click="clearFilter">{{
$t('general.clear_all')
}}</label>
</div>
</transition>
<div v-cloak v-show="showEmptyScreen" class="col-xs-1 no-data-info" align="center">
<moon-walker-icon class="mt-5 mb-4"/>
<div
v-cloak
v-show="showEmptyScreen"
class="col-xs-1 no-data-info"
align="center"
>
<moon-walker-icon class="mt-5 mb-4" />
<div class="row" align="center">
<label class="col title">{{ $t('estimates.no_estimates') }}</label>
</div>
<div class="row">
<label class="description col mt-1" align="center">{{ $t('estimates.list_of_estimates') }}</label>
<label class="description col mt-1" align="center">{{
$t('estimates.list_of_estimates')
}}</label>
</div>
<div class="btn-container">
<base-button
@ -116,28 +117,57 @@
<div v-show="!showEmptyScreen" class="table-container">
<div class="table-actions mt-5">
<p class="table-stats">{{ $t('general.showing') }}: <b>{{ estimates.length }}</b> {{ $t('general.of') }} <b>{{ totalEstimates }}</b></p>
<p class="table-stats">
{{ $t('general.showing') }}: <b>{{ estimates.length }}</b>
{{ $t('general.of') }} <b>{{ totalEstimates }}</b>
</p>
<!-- Tabs -->
<ul class="tabs">
<li class="tab" @click="getStatus('DRAFT')">
<a :class="['tab-link', {'a-active': filters.status === 'DRAFT'}]" href="#">{{ $t('general.draft') }}</a>
<a
:class="['tab-link', { 'a-active': filters.status === 'DRAFT' }]"
href="#"
>{{ $t('general.draft') }}</a
>
</li>
<li class="tab" @click="getStatus('SENT')">
<a :class="['tab-link', {'a-active': filters.status === 'SENT'}]" href="#" >{{ $t('general.sent') }}</a>
<a
:class="['tab-link', { 'a-active': filters.status === 'SENT' }]"
href="#"
>{{ $t('general.sent') }}</a
>
</li>
<li class="tab" @click="getStatus('')">
<a :class="['tab-link', {'a-active': filters.status === '' || filters.status !== 'DRAFT' && filters.status !== 'SENT'}]" href="#">{{ $t('general.all') }}</a>
<a
:class="[
'tab-link',
{
'a-active':
filters.status === '' ||
(filters.status !== 'DRAFT' && filters.status !== 'SENT'),
},
]"
href="#"
>{{ $t('general.all') }}</a
>
</li>
</ul>
<transition name="fade">
<v-dropdown v-if="selectedEstimates.length" :show-arrow="false">
<span slot="activator" href="#" class="table-actions-button dropdown-toggle">
<span
slot="activator"
href="#"
class="table-actions-button dropdown-toggle"
>
{{ $t('general.actions') }}
</span>
<v-dropdown-item>
<div class="dropdown-item" @click="removeMultipleEstimates">
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
<font-awesome-icon
:icon="['fas', 'trash']"
class="dropdown-item-icon"
/>
{{ $t('general.delete') }}
</div>
</v-dropdown-item>
@ -153,8 +183,12 @@
type="checkbox"
class="custom-control-input"
@change="selectAllEstimates"
/>
<label
v-show="!isRequestOngoing"
for="select-all"
class="custom-control-label selectall"
>
<label v-show="!isRequestOngoing" for="select-all" class="custom-control-label selectall">
<span class="select-all-label">{{ $t('general.select_all') }} </span>
</label>
</div>
@ -178,7 +212,7 @@
:value="row.id"
type="checkbox"
class="custom-control-input"
>
/>
<label :for="row.id" class="custom-control-label" />
</div>
</template>
@ -186,30 +220,30 @@
<table-column
:label="$t('estimates.date')"
sort-as="estimate_date"
show="formattedEstimateDate" />
show="formattedEstimateDate"
/>
<table-column
:label="$t('estimates.customer')"
sort-as="name"
show="name" />
show="name"
/>
<!-- <table-column
:label="$t('estimates.expiry_date')"
sort-as="expiry_date"
show="formattedExpiryDate" /> -->
<table-column
:label="$t('estimates.status')"
show="status" >
<template slot-scope="row" >
<table-column :label="$t('estimates.status')" show="status">
<template slot-scope="row">
<span> {{ $t('estimates.status') }}</span>
<span :class="'est-status-'+row.status.toLowerCase()">{{ row.status }}</span>
<span :class="'est-status-' + row.status.toLowerCase()">{{
row.status
}}</span>
</template>
</table-column>
<table-column
:label="$tc('estimates.estimate', 1)"
show="estimate_number"/>
<table-column
:label="$t('invoices.total')"
sort-as="total"
>
show="estimate_number"
/>
<table-column :label="$t('invoices.total')" sort-as="total">
<template slot-scope="row">
<span> {{ $t('estimates.total') }}</span>
<div v-html="$utils.formatMoney(row.total, row.user.currency)" />
@ -227,50 +261,114 @@
<dot-icon />
</a>
<v-dropdown-item>
<router-link :to="{path: `estimates/${row.id}/edit`}" class="dropdown-item">
<font-awesome-icon :icon="['fas', 'pencil-alt']" class="dropdown-item-icon" />
<router-link
:to="{ path: `estimates/${row.id}/edit` }"
class="dropdown-item"
>
<font-awesome-icon
:icon="['fas', 'pencil-alt']"
class="dropdown-item-icon"
/>
{{ $t('general.edit') }}
</router-link>
</v-dropdown-item>
<v-dropdown-item>
<div class="dropdown-item" @click="removeEstimate(row.id)">
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
<font-awesome-icon
:icon="['fas', 'trash']"
class="dropdown-item-icon"
/>
{{ $t('general.delete') }}
</div>
</v-dropdown-item>
<v-dropdown-item>
<router-link :to="{path: `estimates/${row.id}/view`}" class="dropdown-item">
<router-link
:to="{ path: `estimates/${row.id}/view` }"
class="dropdown-item"
>
<font-awesome-icon icon="eye" class="dropdown-item-icon" />
{{ $t('general.view') }}
</router-link>
</v-dropdown-item>
<v-dropdown-item>
<a class="dropdown-item" href="#/" @click="convertInToinvoice(row.id)">
<font-awesome-icon icon="file-alt" class="dropdown-item-icon" />
<a
class="dropdown-item"
href="#/"
@click="convertInToinvoice(row.id)"
>
<font-awesome-icon
icon="file-alt"
class="dropdown-item-icon"
/>
{{ $t('estimates.convert_to_invoice') }}
</a>
</v-dropdown-item>
<v-dropdown-item v-if="row.status !== 'SENT'">
<a class="dropdown-item" href="#/" @click.self="onMarkAsSent(row.id)">
<font-awesome-icon icon="check-circle" class="dropdown-item-icon" />
<a
class="dropdown-item"
href="#/"
@click.self="onMarkAsSent(row.id)"
>
<font-awesome-icon
icon="check-circle"
class="dropdown-item-icon"
/>
{{ $t('estimates.mark_as_sent') }}
</a>
</v-dropdown-item>
<v-dropdown-item v-if="row.status !== 'SENT'">
<a class="dropdown-item" href="#/" @click.self="sendEstimate(row.id)">
<font-awesome-icon icon="paper-plane" class="dropdown-item-icon" />
<v-dropdown-item v-if="row.status === 'DRAFT'">
<a
class="dropdown-item"
href="#/"
@click.self="sendEstimate(row.id)"
>
<font-awesome-icon
icon="paper-plane"
class="dropdown-item-icon"
/>
{{ $t('estimates.send_estimate') }}
</a>
</v-dropdown-item>
<!-- resend estimte -->
<v-dropdown-item
v-if="row.status == 'SENT' || row.status == 'VIEWED'"
>
<a
class="dropdown-item"
href="#/"
@click.self="sendEstimate(row.id)"
>
<font-awesome-icon
icon="paper-plane"
class="dropdown-item-icon"
/>
{{ $t('estimates.resend_estimate') }}
</a>
</v-dropdown-item>
<!-- -->
<v-dropdown-item v-if="row.status !== 'ACCEPTED'">
<a class="dropdown-item" href="#/" @click.self="onMarkAsAccepted(row.id)">
<font-awesome-icon icon="check-circle" class="dropdown-item-icon" />
<a
class="dropdown-item"
href="#/"
@click.self="onMarkAsAccepted(row.id)"
>
<font-awesome-icon
icon="check-circle"
class="dropdown-item-icon"
/>
{{ $t('estimates.mark_as_accepted') }}
</a>
</v-dropdown-item>
<v-dropdown-item v-if="row.status !== 'REJECTED'">
<a class="dropdown-item" href="#/" @click.self="onMarkAsRejected(row.id)">
<font-awesome-icon icon="times-circle" class="dropdown-item-icon" />
<a
class="dropdown-item"
href="#/"
@click.self="onMarkAsRejected(row.id)"
>
<font-awesome-icon
icon="times-circle"
class="dropdown-item-icon"
/>
{{ $t('estimates.mark_as_rejected') }}
</a>
</v-dropdown-item>

View File

@ -12,6 +12,7 @@
ref="baseSelect"
v-model="itemSelect"
:options="items"
:loading="loading"
:show-labels="false"
:preserve-search="true"
:initial-search="item.name"
@ -20,7 +21,7 @@
label="name"
class="multi-select-item"
@value="onTextChange"
@select="(val) => $emit('select', val)"
@select="onSelect"
>
<div slot="afterList">
<button type="button" class="list-add-button" @click="openItemModal">
@ -112,6 +113,7 @@ export default {
]),
async searchItems (search) {
let data = {
search,
filter: {
name: search,
unit: '',
@ -141,6 +143,10 @@ export default {
'data': {taxPerItem: this.taxPerItem, taxes: this.taxes}
})
},
onSelect(val) {
this.$emit('select', val)
this.fetchItems()
},
deselectItem () {
this.itemSelect = null
this.$emit('deselect')

View File

@ -1,7 +1,7 @@
<template>
<div v-if="estimate" class="main-content estimate-view-page">
<div class="page-header">
<h3 class="page-title"> {{ estimate.estimate_number }}</h3>
<h3 class="page-title">{{ estimate.estimate_number }}</h3>
<div class="page-actions row">
<div class="col-xs-2 mr-3">
<base-button
@ -26,19 +26,42 @@
{{ $t('estimates.send_estimate') }}
</base-button>
</div>
<v-dropdown :close-on-select="false" align="left" class="filter-container">
<v-dropdown
:close-on-select="true"
align="left"
class="filter-container"
>
<a slot="activator" href="#">
<base-button color="theme">
<font-awesome-icon icon="ellipsis-h" />
</base-button>
</a>
<v-dropdown-item>
<router-link :to="{path: `/admin/estimates/${$route.params.id}/edit`}" class="dropdown-item">
<font-awesome-icon :icon="['fas', 'pencil-alt']" class="dropdown-item-icon"/>
<div class="dropdown-item" @click="copyPdfUrl()">
<font-awesome-icon
:icon="['fas', 'link']"
class="dropdown-item-icon"
/>
{{ $t('general.copy_pdf_url') }}
</div>
<router-link
:to="{ path: `/admin/estimates/${$route.params.id}/edit` }"
class="dropdown-item"
>
<font-awesome-icon
:icon="['fas', 'pencil-alt']"
class="dropdown-item-icon"
/>
{{ $t('general.edit') }}
</router-link>
<div class="dropdown-item" @click="removeEstimate($route.params.id)">
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
<div
class="dropdown-item"
@click="removeEstimate($route.params.id)"
>
<font-awesome-icon
:icon="['fas', 'trash']"
class="dropdown-item-icon"
/>
{{ $t('general.delete') }}
</div>
</v-dropdown-item>
@ -57,14 +80,18 @@
align-icon="right"
@input="onSearched()"
/>
<div
class="btn-group ml-3"
role="group"
aria-label="First group"
>
<v-dropdown :close-on-select="false" align="left" class="filter-container">
<div class="btn-group ml-3" role="group" aria-label="First group">
<v-dropdown
:close-on-select="false"
align="left"
class="filter-container"
>
<a slot="activator" href="#">
<base-button class="inv-button inv-filter-fields-btn" color="default" size="medium">
<base-button
class="inv-button inv-filter-fields-btn"
color="default"
size="medium"
>
<font-awesome-icon icon="filter" />
</base-button>
</a>
@ -80,8 +107,10 @@
class="inv-radio"
value="estimate_date"
@change="onSearched"
>
<label class="inv-label" for="filter_estimate_date">{{ $t('reports.estimates.estimate_date') }}</label>
/>
<label class="inv-label" for="filter_estimate_date">{{
$t('reports.estimates.estimate_date')
}}</label>
</div>
<div class="filter-items">
<input
@ -92,8 +121,10 @@
class="inv-radio"
value="expiry_date"
@change="onSearched"
>
<label class="inv-label" for="filter_due_date">{{ $t('estimates.due_date') }}</label>
/>
<label class="inv-label" for="filter_due_date">{{
$t('estimates.due_date')
}}</label>
</div>
<div class="filter-items">
<input
@ -104,11 +135,19 @@
class="inv-radio"
value="estimate_number"
@change="onSearched"
>
<label class="inv-label" for="filter_estimate_number">{{ $t('estimates.estimate_number') }}</label>
/>
<label class="inv-label" for="filter_estimate_number">{{
$t('estimates.estimate_number')
}}</label>
</div>
</v-dropdown>
<base-button v-tooltip.top-center="{ content: getOrderName }" class="inv-button inv-filter-sorting-btn" color="default" size="medium" @click="sortData">
<base-button
v-tooltip.top-center="{ content: getOrderName }"
class="inv-button inv-filter-sorting-btn"
color="default"
size="medium"
@click="sortData"
>
<font-awesome-icon v-if="getOrderBy" icon="sort-amount-up" />
<font-awesome-icon v-else icon="sort-amount-down" />
</base-button>
@ -116,7 +155,7 @@
</div>
<div class="side-content">
<router-link
v-for="(estimate,index) in estimates"
v-for="(estimate, index) in estimates"
:to="`/admin/estimates/${estimate.id}/view`"
:key="index"
class="side-estimate"
@ -124,10 +163,20 @@
<div class="left">
<div class="inv-name">{{ estimate.user.name }}</div>
<div class="inv-number">{{ estimate.estimate_number }}</div>
<div :class="'est-status-'+estimate.status.toLowerCase()" class="inv-status">{{ estimate.status }}</div>
<div
:class="'est-status-' + estimate.status.toLowerCase()"
class="inv-status"
>
{{ estimate.status }}
</div>
</div>
<div class="right">
<div class="inv-amount" v-html="$utils.formatMoney(estimate.total, estimate.user.currency)" />
<div
class="inv-amount"
v-html="
$utils.formatMoney(estimate.total, estimate.user.currency)
"
/>
<div class="inv-date">{{ estimate.formattedEstimateDate }}</div>
</div>
</router-link>
@ -137,7 +186,7 @@
</div>
</div>
<div class="estimate-view-page-container">
<iframe :src="`${shareableLink}`" class="frame-style"/>
<iframe :src="`${shareableLink}`" class="frame-style" />
</div>
</div>
</template>
@ -289,6 +338,13 @@ export default {
}
})
},
copyPdfUrl () {
let pdfUrl = `${window.location.origin}/estimates/pdf/${this.estimate.unique_hash}`
let response = this.$utils.copyTextToClipboard(pdfUrl)
window.toastr['success'](this.$tc('Copied PDF url to clipboard!'))
},
async removeEstimate (id) {
window.swal({
title: 'Deleted',

View File

@ -102,6 +102,19 @@
<span v-if="!$v.formData.amount.minValue" class="text-danger">{{ $t('validation.price_minvalue') }}</span>
</div>
</div>
<div class="form-group col-sm-6">
<label class="form-label">{{ $t('expenses.customer') }}</label>
<base-select
ref="baseSelect"
v-model="customer"
:options="customerList"
:searchable="true"
:show-labels="false"
:placeholder="$t('customers.select_a_customer')"
label="name"
track-by="id"
/>
</div>
<div class="form-group col-sm-6">
<label for="description">{{ $t('expenses.note') }}</label>
<base-text-area
@ -169,7 +182,8 @@ export default {
expense_category_id: null,
expense_date: new Date(),
amount: null,
notes: ''
notes: '',
user_id: null
},
money: {
decimal: '.',
@ -185,7 +199,9 @@ export default {
passData: [],
contacts: [],
previewReceipt: null,
fileSendUrl: '/api/expenses'
fileSendUrl: '/api/expenses',
customer: null,
customerList: []
}
},
validations: {
@ -297,6 +313,8 @@ export default {
},
async fetchInitialData () {
this.fetchCategories()
let fetchData = await this.fetchCreateExpense()
this.customerList = fetchData.data.customers
if (this.isEdit) {
let response = await this.fetchExpense(this.$route.params.id)
this.category = response.data.expense.category
@ -304,6 +322,9 @@ export default {
this.formData.expense_date = moment(this.formData.expense_date).toString()
this.formData.amount = (response.data.expense.amount)
this.fileSendUrl = `/api/expenses/${this.$route.params.id}`
if (response.data.expense.user_id) {
this.customer = this.customerList.find(customer => customer.id === response.data.expense.user_id)
}
}
},
async sendData () {
@ -319,9 +340,10 @@ export default {
data.append('attachment_receipt', this.file)
}
data.append('expense_category_id', this.formData.expense_category_id)
data.append('expense_date', moment(this.formData.expense_date).format('DD/MM/YYYY'))
data.append('expense_date', moment(this.formData.expense_date).format('DD/MM/YYYY'))
data.append('amount', (this.formData.amount))
data.append('notes', this.formData.notes)
data.append('notes', this.formData.notes ? this.formData.notes : '')
data.append('user_id', this.customer ? this.customer.id : '')
if (this.isEdit) {
this.isLoading = true

View File

@ -43,7 +43,19 @@
<transition name="fade">
<div v-show="showFilters" class="filter-section">
<div class="row">
<div class="col-md-4">
<div class="col-md-3">
<label>{{ $t('expenses.customer') }}</label>
<base-select
v-model="filters.user"
:options="customers"
:searchable="true"
:show-labels="false"
:placeholder="$t('expenses.select_a_customer')"
label="name"
@click="filter = ! filter"
/>
</div>
<div class="col-md-3">
<label>{{ $t('expenses.category') }}</label>
<base-select
v-model="filters.category"
@ -55,7 +67,7 @@
@click="filter = ! filter"
/>
</div>
<div class="col-md-4">
<div class="col-md-3">
<label>{{ $t('expenses.from_date') }}</label>
<base-date-picker
v-model="filters.from_date"
@ -63,7 +75,7 @@
calendar-button-icon="calendar"
/>
</div>
<div class="col-md-4">
<div class="col-md-3">
<label>{{ $t('expenses.to_date') }}</label>
<base-date-picker
v-model="filters.to_date"
@ -161,6 +173,11 @@
sort-as="name"
show="category.name"
/>
<table-column
:label="$t('expenses.customer')"
sort-as="user_name"
show="user_name"
/>
<table-column
:label="$t('expenses.date')"
sort-as="expense_date"
@ -237,10 +254,12 @@ export default {
showFilters: false,
filtersApplied: false,
isRequestOngoing: true,
customers: [],
filters: {
category: null,
from_date: '',
to_date: ''
to_date: '',
user: ''
}
}
},
@ -308,6 +327,7 @@ export default {
]),
async fetchData ({ page, filter, sort }) {
let data = {
user_id: this.filters.user ? this.filters.user.id : null,
expense_category_id: this.filters.category !== null ? this.filters.category.id : '',
from_date: this.filters.from_date === '' ? this.filters.from_date : moment(this.filters.from_date).format('DD/MM/YYYY'),
to_date: this.filters.to_date === '' ? this.filters.to_date : moment(this.filters.to_date).format('DD/MM/YYYY'),
@ -318,6 +338,7 @@ export default {
this.isRequestOngoing = true
let response = await this.fetchExpenses(data)
this.customers = response.data.customers
this.isRequestOngoing = false
return {
@ -340,7 +361,8 @@ export default {
this.filters = {
category: null,
from_date: '',
to_date: ''
to_date: '',
user: null
}
this.$nextTick(() => {

View File

@ -1,19 +1,15 @@
<template>
<div class="invoice-index-page invoices main-content">
<div class="page-header">
<h3 class="page-title"> {{ $t('invoices.title') }}</h3>
<h3 class="page-title">{{ $t('invoices.title') }}</h3>
<ol class="breadcrumb">
<li class="breadcrumb-item">
<router-link
slot="item-title"
to="dashboard">
<router-link slot="item-title" to="dashboard">
{{ $t('general.home') }}
</router-link>
</li>
<li class="breadcrumb-item">
<router-link
slot="item-title"
to="#">
<router-link slot="item-title" to="#">
{{ $tc('invoices.invoice', 2) }}
</router-link>
</li>
@ -32,7 +28,11 @@
{{ $t('general.filter') }}
</base-button>
</div>
<router-link slot="item-title" class="col-xs-2" to="/admin/invoices/create">
<router-link
slot="item-title"
class="col-xs-2"
to="/admin/invoices/create"
>
<base-button size="large" icon="plus" color="theme">
{{ $t('invoices.new_invoice') }}
</base-button>
@ -44,7 +44,7 @@
<div v-show="showFilters" class="filter-section">
<div class="filter-container">
<div class="filter-customer">
<label>{{ $tc('customers.customer',1) }} </label>
<label>{{ $tc('customers.customer', 1) }} </label>
<base-customer-select
ref="customerSelect"
@select="onSelectCustomer"
@ -88,22 +88,29 @@
</div>
<div class="filter-invoice">
<label>{{ $t('invoices.invoice_number') }}</label>
<base-input
v-model="filters.invoice_number"
icon="hashtag"/>
<base-input v-model="filters.invoice_number" icon="hashtag" />
</div>
</div>
<label class="clear-filter" @click="clearFilter">{{ $t('general.clear_all') }}</label>
<label class="clear-filter" @click="clearFilter">{{
$t('general.clear_all')
}}</label>
</div>
</transition>
<div v-cloak v-show="showEmptyScreen" class="col-xs-1 no-data-info" align="center">
<moon-walker-icon class="mt-5 mb-4"/>
<div
v-cloak
v-show="showEmptyScreen"
class="col-xs-1 no-data-info"
align="center"
>
<moon-walker-icon class="mt-5 mb-4" />
<div class="row" align="center">
<label class="col title">{{ $t('invoices.no_invoices') }}</label>
</div>
<div class="row">
<label class="description col mt-1" align="center">{{ $t('invoices.list_of_invoices') }}</label>
<label class="description col mt-1" align="center">{{
$t('invoices.list_of_invoices')
}}</label>
</div>
<div class="btn-container">
<base-button
@ -120,28 +127,65 @@
<div v-show="!showEmptyScreen" class="table-container">
<div class="table-actions mt-5">
<p class="table-stats">{{ $t('general.showing') }}: <b>{{ invoices.length }}</b> {{ $t('general.of') }} <b>{{ totalInvoices }}</b></p>
<p class="table-stats">
{{ $t('general.showing') }}: <b>{{ invoices.length }}</b>
{{ $t('general.of') }} <b>{{ totalInvoices }}</b>
</p>
<!-- Tabs -->
<ul class="tabs">
<li class="tab" @click="getStatus('UNPAID')">
<a :class="['tab-link', {'a-active': filters.status.value === 'UNPAID'}]" href="#" >{{ $t('general.due') }}</a>
<a
:class="[
'tab-link',
{ 'a-active': filters.status.value === 'UNPAID' },
]"
href="#"
>{{ $t('general.due') }}</a
>
</li>
<li class="tab" @click="getStatus('DRAFT')">
<a :class="['tab-link', {'a-active': filters.status.value === 'DRAFT'}]" href="#">{{ $t('general.draft') }}</a>
<a
:class="[
'tab-link',
{ 'a-active': filters.status.value === 'DRAFT' },
]"
href="#"
>{{ $t('general.draft') }}</a
>
</li>
<li class="tab" @click="getStatus('')">
<a :class="['tab-link', {'a-active': filters.status.value === '' || filters.status.value === null || filters.status.value !== 'DRAFT' && filters.status.value !== 'UNPAID'}]" href="#">{{ $t('general.all') }}</a>
<a
:class="[
'tab-link',
{
'a-active':
filters.status.value === '' ||
filters.status.value === null ||
(filters.status.value !== 'DRAFT' &&
filters.status.value !== 'UNPAID'),
},
]"
href="#"
>{{ $t('general.all') }}</a
>
</li>
</ul>
<transition name="fade">
<v-dropdown v-if="selectedInvoices.length" :show-arrow="false">
<span slot="activator" href="#" class="table-actions-button dropdown-toggle">
<span
slot="activator"
href="#"
class="table-actions-button dropdown-toggle"
>
{{ $t('general.actions') }}
</span>
<v-dropdown-item>
<div class="dropdown-item" @click="removeMultipleInvoices">
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
<font-awesome-icon
:icon="['fas', 'trash']"
class="dropdown-item-icon"
/>
{{ $t('general.delete') }}
</div>
</v-dropdown-item>
@ -155,8 +199,12 @@
type="checkbox"
class="custom-control-input"
@change="selectAllInvoices"
/>
<label
v-show="!isRequestOngoing"
for="select-all"
class="custom-control-label selectall"
>
<label v-show="!isRequestOngoing" for="select-all" class="custom-control-label selectall">
<span class="select-all-label">{{ $t('general.select_all') }} </span>
</label>
</div>
@ -180,8 +228,8 @@
:value="row.id"
type="checkbox"
class="custom-control-input"
>
<label :for="row.id" class="custom-control-label"/>
/>
<label :for="row.id" class="custom-control-label" />
</div>
</template>
</table-column>
@ -195,35 +243,33 @@
width="20%"
show="name"
/>
<table-column
:label="$t('invoices.status')"
sort-as="status"
>
<template slot-scope="row" >
<table-column :label="$t('invoices.status')" sort-as="status">
<template slot-scope="row">
<span> {{ $t('invoices.status') }}</span>
<span :class="'inv-status-'+row.status.toLowerCase()">{{ (row.status != 'PARTIALLY_PAID')? row.status : row.status.replace('_', ' ') }}</span>
<span :class="'inv-status-' + row.status.toLowerCase()">{{
row.status != 'PARTIALLY_PAID'
? row.status
: row.status.replace('_', ' ')
}}</span>
</template>
</table-column>
<table-column
:label="$t('invoices.paid_status')"
sort-as="paid_status"
>
<table-column :label="$t('invoices.paid_status')" sort-as="paid_status">
<template slot-scope="row">
<span>{{ $t('invoices.paid_status') }}</span>
<span :class="'inv-status-'+row.paid_status.toLowerCase()">{{ (row.paid_status != 'PARTIALLY_PAID')? row.paid_status : row.paid_status.replace('_', ' ') }}</span>
<span :class="'inv-status-' + row.paid_status.toLowerCase()">{{
row.paid_status != 'PARTIALLY_PAID'
? row.paid_status
: row.paid_status.replace('_', ' ')
}}</span>
</template>
</table-column>
<table-column
:label="$t('invoices.number')"
show="invoice_number"
/>
<table-column
:label="$t('invoices.amount_due')"
sort-as="due_amount"
>
<table-column :label="$t('invoices.number')" show="invoice_number" />
<table-column :label="$t('invoices.amount_due')" sort-as="due_amount">
<template slot-scope="row">
<span>{{ $t('invoices.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)"
/>
</template>
</table-column>
<table-column
@ -238,42 +284,91 @@
<dot-icon />
</a>
<v-dropdown-item>
<router-link :to="{path: `invoices/${row.id}/edit`}" class="dropdown-item">
<font-awesome-icon :icon="['fas', 'pencil-alt']" class="dropdown-item-icon"/>
<router-link
:to="{ path: `invoices/${row.id}/edit` }"
class="dropdown-item"
>
<font-awesome-icon
:icon="['fas', 'pencil-alt']"
class="dropdown-item-icon"
/>
{{ $t('general.edit') }}
</router-link>
<router-link :to="{path: `invoices/${row.id}/view`}" class="dropdown-item">
<router-link
:to="{ path: `invoices/${row.id}/view` }"
class="dropdown-item"
>
<font-awesome-icon icon="eye" class="dropdown-item-icon" />
{{ $t('invoices.view') }}
</router-link>
</v-dropdown-item>
<v-dropdown-item v-if="row.status == 'DRAFT'">
<a class="dropdown-item" href="#/" @click="sendInvoice(row.id)" >
<font-awesome-icon icon="paper-plane" class="dropdown-item-icon" />
<a class="dropdown-item" href="#/" @click="sendInvoice(row.id)">
<font-awesome-icon
icon="paper-plane"
class="dropdown-item-icon"
/>
{{ $t('invoices.send_invoice') }}
</a>
</v-dropdown-item>
<v-dropdown-item
v-if="row.status === 'SENT' || row.status === 'VIEWED'"
>
<a class="dropdown-item" href="#/" @click="sendInvoice(row.id)">
<font-awesome-icon
icon="paper-plane"
class="dropdown-item-icon"
/>
{{ $t('invoices.resend_invoice') }}
</a>
</v-dropdown-item>
<v-dropdown-item v-if="row.status == 'DRAFT'">
<a class="dropdown-item" href="#/" @click="markInvoiceAsSent(row.id)">
<font-awesome-icon icon="check-circle" class="dropdown-item-icon" />
<a
class="dropdown-item"
href="#/"
@click="markInvoiceAsSent(row.id)"
>
<font-awesome-icon
icon="check-circle"
class="dropdown-item-icon"
/>
{{ $t('invoices.mark_as_sent') }}
</a>
</v-dropdown-item>
<v-dropdown-item v-if="row.status === 'SENT' || row.status === 'VIEWED' || row.status === 'OVERDUE'">
<router-link :to="`/admin/payments/${row.id}/create`" class="dropdown-item">
<font-awesome-icon :icon="['fas', 'credit-card']" class="dropdown-item-icon"/>
<v-dropdown-item
v-if="
row.status === 'SENT' ||
row.status === 'VIEWED' ||
row.status === 'OVERDUE'
"
>
<router-link
:to="`/admin/payments/${row.id}/create`"
class="dropdown-item"
>
<font-awesome-icon
:icon="['fas', 'credit-card']"
class="dropdown-item-icon"
/>
{{ $t('payments.record_payment') }}
</router-link>
</v-dropdown-item>
<v-dropdown-item>
<a class="dropdown-item" href="#/" @click="onCloneInvoice(row.id)">
<a
class="dropdown-item"
href="#/"
@click="onCloneInvoice(row.id)"
>
<font-awesome-icon icon="copy" class="dropdown-item-icon" />
{{ $t('invoices.clone_invoice') }}
</a>
</v-dropdown-item>
<v-dropdown-item>
<div class="dropdown-item" @click="removeInvoice(row.id)">
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
<font-awesome-icon
:icon="['fas', 'trash']"
class="dropdown-item-icon"
/>
{{ $t('general.delete') }}
</div>
</v-dropdown-item>

View File

@ -12,6 +12,7 @@
ref="baseSelect"
v-model="itemSelect"
:options="items"
:loading="loading"
:show-labels="false"
:preserve-search="true"
:initial-search="item.name"
@ -20,7 +21,7 @@
label="name"
class="multi-select-item"
@value="onTextChange"
@select="(val) => $emit('select', val)"
@select="onSelect"
>
<div slot="afterList">
<button type="button" class="list-add-button" @click="openItemModal">
@ -101,6 +102,7 @@ export default {
]),
async searchItems (search) {
let data = {
search,
filter: {
name: search,
unit: '',
@ -130,6 +132,10 @@ export default {
'data': {taxPerItem: this.taxPerItem, taxes: this.taxes}
})
},
onSelect(val) {
this.$emit('select', val)
this.fetchItems()
},
deselectItem () {
this.itemSelect = null
this.$emit('deselect')

View File

@ -1,7 +1,7 @@
<template>
<div v-if="invoice" class="main-content invoice-view-page">
<div class="page-header">
<h3 class="page-title"> {{ invoice.invoice_number }}</h3>
<h3 class="page-title">{{ invoice.invoice_number }}</h3>
<div class="page-actions row">
<div class="col-xs-2 mr-3">
<base-button
@ -24,26 +24,47 @@
>
{{ $t('invoices.send_invoice') }}
</base-button>
<router-link v-if="invoice.status === 'SENT'" :to="`/admin/payments/${$route.params.id}/create`">
<base-button
color="theme"
>
<router-link
v-if="invoice.status === 'SENT'"
:to="`/admin/payments/${$route.params.id}/create`"
>
<base-button color="theme">
{{ $t('payments.record_payment') }}
</base-button>
</router-link>
<v-dropdown :close-on-select="false" align="left" class="filter-container">
<v-dropdown
:close-on-select="true"
align="left"
class="filter-container"
>
<a slot="activator" href="#">
<base-button color="theme">
<font-awesome-icon icon="ellipsis-h" />
</base-button>
</a>
<v-dropdown-item>
<router-link :to="{path: `/admin/invoices/${$route.params.id}/edit`}" class="dropdown-item">
<font-awesome-icon :icon="['fas', 'pencil-alt']" class="dropdown-item-icon"/>
<div class="dropdown-item" @click="copyPdfUrl">
<font-awesome-icon
:icon="['fas', 'link']"
class="dropdown-item-icon"
/>
{{ $t('general.copy_pdf_url') }}
</div>
<router-link
:to="{ path: `/admin/invoices/${$route.params.id}/edit` }"
class="dropdown-item"
>
<font-awesome-icon
:icon="['fas', 'pencil-alt']"
class="dropdown-item-icon"
/>
{{ $t('general.edit') }}
</router-link>
<div class="dropdown-item" @click="removeInvoice($route.params.id)">
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
<font-awesome-icon
:icon="['fas', 'trash']"
class="dropdown-item-icon"
/>
{{ $t('general.delete') }}
</div>
</v-dropdown-item>
@ -61,14 +82,18 @@
align-icon="right"
@input="onSearch"
/>
<div
class="btn-group ml-3"
role="group"
aria-label="First group"
>
<v-dropdown :close-on-select="false" align="left" class="filter-container">
<div class="btn-group ml-3" role="group" aria-label="First group">
<v-dropdown
:close-on-select="false"
align="left"
class="filter-container"
>
<a slot="activator" href="#">
<base-button class="inv-button inv-filter-fields-btn" color="default" size="medium">
<base-button
class="inv-button inv-filter-fields-btn"
color="default"
size="medium"
>
<font-awesome-icon icon="filter" />
</base-button>
</a>
@ -84,8 +109,10 @@
class="inv-radio"
value="invoice_date"
@change="onSearch"
>
<label class="inv-label" for="filter_invoice_date">{{ $t('invoices.invoice_date') }}</label>
/>
<label class="inv-label" for="filter_invoice_date">{{
$t('invoices.invoice_date')
}}</label>
</div>
<div class="filter-items">
<input
@ -96,8 +123,10 @@
class="inv-radio"
value="due_date"
@change="onSearch"
>
<label class="inv-label" for="filter_due_date">{{ $t('invoices.due_date') }}</label>
/>
<label class="inv-label" for="filter_due_date">{{
$t('invoices.due_date')
}}</label>
</div>
<div class="filter-items">
<input
@ -108,11 +137,19 @@
class="inv-radio"
value="invoice_number"
@change="onSearch"
>
<label class="inv-label" for="filter_invoice_number">{{ $t('invoices.invoice_number') }}</label>
/>
<label class="inv-label" for="filter_invoice_number">{{
$t('invoices.invoice_number')
}}</label>
</div>
</v-dropdown>
<base-button v-tooltip.top-center="{ content: getOrderName }" class="inv-button inv-filter-sorting-btn" color="default" size="medium" @click="sortData">
<base-button
v-tooltip.top-center="{ content: getOrderName }"
class="inv-button inv-filter-sorting-btn"
color="default"
size="medium"
@click="sortData"
>
<font-awesome-icon v-if="getOrderBy" icon="sort-amount-up" />
<font-awesome-icon v-else icon="sort-amount-down" />
</base-button>
@ -121,7 +158,7 @@
<base-loader v-if="isSearching" />
<div v-else class="side-content">
<router-link
v-for="(invoice,index) in invoices"
v-for="(invoice, index) in invoices"
:to="`/admin/invoices/${invoice.id}/view`"
:key="index"
class="side-invoice"
@ -129,10 +166,20 @@
<div class="left">
<div class="inv-name">{{ invoice.user.name }}</div>
<div class="inv-number">{{ invoice.invoice_number }}</div>
<div :class="'inv-status-'+invoice.status.toLowerCase()" class="inv-status">{{ invoice.status }}</div>
<div
:class="'inv-status-' + invoice.status.toLowerCase()"
class="inv-status"
>
{{ invoice.status }}
</div>
</div>
<div class="right">
<div class="inv-amount" v-html="$utils.formatMoney(invoice.due_amount, invoice.user.currency)" />
<div
class="inv-amount"
v-html="
$utils.formatMoney(invoice.due_amount, invoice.user.currency)
"
/>
<div class="inv-date">{{ invoice.formattedInvoiceDate }}</div>
</div>
</router-link>
@ -141,8 +188,8 @@
</p>
</div>
</div>
<div class="invoice-view-page-container" >
<iframe :src="`${shareableLink}`" class="frame-style"/>
<div class="invoice-view-page-container">
<iframe :src="`${shareableLink}`" class="frame-style" />
</div>
</div>
</template>
@ -291,6 +338,14 @@ export default {
}
})
},
copyPdfUrl () {
let pdfUrl = `${window.location.origin}/invoices/pdf/${this.invoice.unique_hash}`
let response = this.$utils.copyTextToClipboard(pdfUrl)
window.toastr['success'](this.$tc('Copied PDF url to clipboard!'))
},
async removeInvoice (id) {
this.selectInvoice([parseInt(id)])
this.id = id

View File

@ -1,7 +1,7 @@
<template>
<div v-if="payment" class="main-content payment-view-page">
<div class="page-header">
<h3 class="page-title"> {{ payment.payment_number }}</h3>
<h3 class="page-title">{{ payment.payment_number }}</h3>
<div class="page-actions row">
<base-button
:loading="isSendingEmail"
@ -11,19 +11,39 @@
>
{{ $t('payments.send_payment_receipt') }}
</base-button>
<v-dropdown :close-on-select="false" align="left" class="filter-container">
<v-dropdown
:close-on-select="true"
align="left"
class="filter-container"
>
<a slot="activator" href="#">
<base-button color="theme">
<font-awesome-icon icon="ellipsis-h" />
</base-button>
</a>
<v-dropdown-item>
<router-link :to="{path: `/admin/payments/${$route.params.id}/edit`}" class="dropdown-item">
<font-awesome-icon :icon="['fas', 'pencil-alt']" class="dropdown-item-icon"/>
<div class="dropdown-item" @click="copyPdfUrl">
<font-awesome-icon
:icon="['fas', 'link']"
class="dropdown-item-icon"
/>
{{ $t('general.copy_pdf_url') }}
</div>
<router-link
:to="{ path: `/admin/payments/${$route.params.id}/edit` }"
class="dropdown-item"
>
<font-awesome-icon
:icon="['fas', 'pencil-alt']"
class="dropdown-item-icon"
/>
{{ $t('general.edit') }}
</router-link>
<div class="dropdown-item" @click="removePayment($route.params.id)">
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
<font-awesome-icon
:icon="['fas', 'trash']"
class="dropdown-item-icon"
/>
{{ $t('general.delete') }}
</div>
</v-dropdown-item>
@ -41,14 +61,18 @@
align-icon="right"
@input="onSearch"
/>
<div
class="btn-group ml-3"
role="group"
aria-label="First group"
>
<v-dropdown :close-on-select="false" align="left" class="filter-container">
<div class="btn-group ml-3" role="group" aria-label="First group">
<v-dropdown
:close-on-select="false"
align="left"
class="filter-container"
>
<a slot="activator" href="#">
<base-button class="inv-button inv-filter-fields-btn" color="default" size="medium">
<base-button
class="inv-button inv-filter-fields-btn"
color="default"
size="medium"
>
<font-awesome-icon icon="filter" />
</base-button>
</a>
@ -64,8 +88,10 @@
class="inv-radio"
value="invoice_number"
@change="onSearch"
>
<label class="inv-label" for="filter_invoice_number">{{ $t('invoices.title') }}</label>
/>
<label class="inv-label" for="filter_invoice_number">{{
$t('invoices.title')
}}</label>
</div>
<div class="filter-items">
<input
@ -76,8 +102,10 @@
class="inv-radio"
value="payment_date"
@change="onSearch"
>
<label class="inv-label" for="filter_payment_date">{{ $t('payments.date') }}</label>
/>
<label class="inv-label" for="filter_payment_date">{{
$t('payments.date')
}}</label>
</div>
<div class="filter-items">
<input
@ -88,11 +116,19 @@
class="inv-radio"
value="payment_number"
@change="onSearch"
>
<label class="inv-label" for="filter_payment_number">{{ $t('payments.payment_number') }}</label>
/>
<label class="inv-label" for="filter_payment_number">{{
$t('payments.payment_number')
}}</label>
</div>
</v-dropdown>
<base-button v-tooltip.top-center="{ content: getOrderName }" class="inv-button inv-filter-sorting-btn" color="default" size="medium" @click="sortData">
<base-button
v-tooltip.top-center="{ content: getOrderName }"
class="inv-button inv-filter-sorting-btn"
color="default"
size="medium"
@click="sortData"
>
<font-awesome-icon v-if="getOrderBy" icon="sort-amount-up" />
<font-awesome-icon v-else icon="sort-amount-down" />
</base-button>
@ -101,7 +137,7 @@
<base-loader v-if="isSearching" />
<div v-else class="side-content">
<router-link
v-for="(payment,index) in payments"
v-for="(payment, index) in payments"
:to="`/admin/payments/${payment.id}/view`"
:key="index"
class="side-payment"
@ -112,7 +148,10 @@
<div class="inv-number">{{ payment.invoice_number }}</div>
</div>
<div class="right">
<div class="inv-amount" v-html="$utils.formatMoney(payment.amount, payment.user.currency)" />
<div
class="inv-amount"
v-html="$utils.formatMoney(payment.amount, payment.user.currency)"
/>
<div class="inv-date">{{ payment.formattedPaymentDate }}</div>
<!-- <div class="inv-number">{{ payment.payment_method.name }}</div> -->
</div>
@ -122,8 +161,8 @@
</p>
</div>
</div>
<div class="payment-view-page-container" >
<iframe :src="`${shareableLink}`" class="frame-style"/>
<div class="payment-view-page-container">
<iframe :src="`${shareableLink}`" class="frame-style" />
</div>
</div>
</template>
@ -260,6 +299,13 @@ export default {
}
})
},
copyPdfUrl () {
let pdfUrl = `${window.location.origin}/payments/pdf/${this.payment.unique_hash}`
let response = this.$utils.copyTextToClipboard(pdfUrl)
window.toastr['success'](this.$tc('Copied PDF url to clipboard!'))
},
async removePayment (id) {
this.id = id
window.swal({

View File

@ -1,33 +1,76 @@
<template>
<div class="setting-main-container">
<div class="setting-main-container update-container">
<div class="card setting-card">
<div class="page-header">
<h3 class="page-title">{{ $t('settings.update_app.title') }}</h3>
<p class="page-sub-title">
{{ $t('settings.update_app.description') }}
</p>
<label class="input-label">{{ $t('settings.update_app.current_version') }}</label><br>
<label class="input-label">{{
$t('settings.update_app.current_version')
}}</label
><br />
<label class="version mb-4">{{ currentVersion }}</label>
<base-button :outline="true" :disabled="isCheckingforUpdate || isUpdating" size="large" color="theme" class="mb-4" @click="checkUpdate">
<font-awesome-icon :class="{'update': isCheckingforUpdate}" style="margin-right: 10px;" icon="sync-alt" />
<base-button
:outline="true"
:disabled="isCheckingforUpdate || isUpdating"
size="large"
color="theme"
class="mb-4"
@click="checkUpdate"
>
<font-awesome-icon
:class="{ update: isCheckingforUpdate }"
style="margin-right: 10px;"
icon="sync-alt"
/>
{{ $t('settings.update_app.check_update') }}
</base-button>
<hr>
<hr />
<div v-show="!isUpdating" v-if="isUpdateAvailable" class="mt-4 content">
<h3 class="page-title mb-3">{{ $t('settings.update_app.avail_update') }}</h3>
<label class="input-label">{{ $t('settings.update_app.next_version') }}</label><br>
<h3 class="page-title mb-3">
{{ $t('settings.update_app.avail_update') }}
</h3>
<label class="input-label">{{
$t('settings.update_app.next_version')
}}</label
><br />
<label class="version">{{ updateData.version }}</label>
<p class="page-sub-title" style="white-space: pre-wrap;">{{ description }}</p>
<base-button size="large" icon="rocket" color="theme" @click="onUpdateApp">
<base-button
size="large"
icon="rocket"
color="theme"
@click="onUpdateApp"
>
{{ $t('settings.update_app.update') }}
</base-button>
</div>
<div v-if="isUpdating" class="mt-4 content">
<h3 class="page-title">{{ $t('settings.update_app.update_progress') }}</h3>
<p class="page-sub-title">
{{ $t('settings.update_app.progress_text') }}
</p>
<font-awesome-icon icon="spinner" class="fa-spin"/>
<div class="d-flex flex-row justify-content-between">
<div>
<h3 class="page-title">
{{ $t('settings.update_app.update_progress') }}
</h3>
<p class="page-sub-title">
{{ $t('settings.update_app.progress_text') }}
</p>
</div>
<font-awesome-icon icon="spinner" class="update-spinner fa-spin" />
</div>
<ul class="update-steps-container">
<li class="update-step" v-for="step in updateSteps">
<p class="update-step-text">{{ $t(step.translationKey) }}</p>
<div class="update-status-container">
<span v-if="step.time" class="update-time">{{
step.time
}}</span>
<span :class="'update-status status-' + getStatus(step)">{{
getStatus(step)
}}</span>
</div>
</li>
</ul>
</div>
</div>
</div>
@ -36,7 +79,7 @@
<script>
export default {
data () {
data() {
return {
isShowProgressBar: false,
isUpdateAvailable: false,
@ -46,60 +89,78 @@ export default {
interval: null,
description: '',
currentVersion: '',
updateSteps: [
{
translationKey: 'settings.update_app.download_zip_file',
stepUrl: '/api/update/download',
time: null,
started: false,
completed: false,
},
{
translationKey: 'settings.update_app.unzipping_package',
stepUrl: '/api/update/unzip',
time: null,
started: false,
completed: false,
},
{
translationKey: 'settings.update_app.copying_files',
stepUrl: '/api/update/copy',
time: null,
started: false,
completed: false,
},
{
translationKey: 'settings.update_app.running_migrations',
stepUrl: '/api/update/migrate',
time: null,
started: false,
completed: false,
},
{
translationKey: 'settings.update_app.finishing_update',
stepUrl: '/api/update/finish',
time: null,
started: false,
completed: false,
},
],
updateData: {
isMinor: Boolean,
installed: '',
version: ''
}
version: '',
},
}
},
created () {
created() {
window.addEventListener('beforeunload', (event) => {
if (this.isUpdating) {
event.returnValue = 'Update is in progress!'
}
})
},
mounted () {
mounted() {
window.axios.get('/api/settings/app/version').then((res) => {
this.currentVersion = res.data.version
})
},
methods: {
closeHandler () {
closeHandler() {
console.log('closing')
},
async onUpdateApp () {
try {
this.isUpdating = true
this.updateData.installed = this.currentVersion
let res = await window.axios.post('/api/update', this.updateData)
if (res.data.success) {
setTimeout(async () => {
await window.axios.post('/api/update/finish', this.updateData)
window.toastr['success'](this.$t('settings.update_app.update_success'))
this.currentVersion = this.updateData.version
this.isUpdateAvailable = false
setTimeout(() => {
location.reload()
}, 2000)
}, 1000)
} else {
console.log(res.data)
window.toastr['error'](res.data.error)
}
} catch (e) {
console.log(e)
window.toastr['error']('Something went wrong')
getStatus(step) {
if (step.started && step.completed) {
return 'finished'
} else if (step.started && !step.completed) {
return 'running'
} else if (!step.started && !step.completed) {
return 'pending'
} else {
return 'error'
}
this.isUpdating = false
},
async checkUpdate () {
async checkUpdate() {
try {
this.isCheckingforUpdate = true
let response = await window.axios.get('/api/check/update')
@ -122,8 +183,67 @@ export default {
this.isCheckingforUpdate = false
window.toastr['error']('Something went wrong')
}
}
}
},
async onUpdateApp() {
let path = null
for (let index = 0; index < this.updateSteps.length; index++) {
let currentStep = this.updateSteps[index]
try {
this.isUpdating = true
currentStep.started = true
let updateParams = {
version: this.updateData.version,
installed: this.currentVersion,
path: path || null,
}
let requestResponse = await window.axios.post(
currentStep.stepUrl,
updateParams
)
currentStep.completed = true
if (requestResponse.data && requestResponse.data.path) {
path = requestResponse.data.path
}
// on finish
if (
currentStep.translationKey == 'settings.update_app.finishing_update'
) {
this.isUpdating = false
window.toastr['success'](
this.$t('settings.update_app.update_success')
)
setTimeout(() => {
location.reload()
}, 3000)
}
} catch (error) {
currentStep.started = false
currentStep.completed = true
window.toastr['error'](this.$t('validation.something_went_wrong'))
this.onUpdateFailed(currentStep.translationKey)
return false
}
}
},
onUpdateFailed(translationKey) {
let stepName = this.$t(translationKey)
swal({
title: this.$t('settings.update_app.update_failed'),
text: this.$tc('settings.update_app.update_failed_text', stepName, {step: stepName}),
buttons: [this.$t('general.cancel'), this.$t('general.retry')],
}).then(async (value) => {
if (value) {
this.onUpdateApp()
return
}
this.isUpdating = false
})
},
},
}
</script>

View File

@ -54,7 +54,8 @@ import {
faEyeSlash,
faSyncAlt,
faRocket,
faCamera
faCamera,
faLink,
} from '@fortawesome/free-solid-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
@ -119,7 +120,8 @@ library.add(
faPaperPlane,
faSyncAlt,
faRocket,
faCamera
faCamera,
faLink
)
Vue.component('font-awesome-icon', FontAwesomeIcon)

View File

@ -27,6 +27,7 @@ fieldset[disabled] .multiselect {
top: 50%;
left: 50%;
margin: -8px 0 0 -8px;
z-index: 5;
width: 16px;
height: 16px;
border-radius: 100%;

View File

@ -122,6 +122,84 @@
}
.update-container {
.update-spinner {
font-size: 30px;
color: $ls-color-gray--dark;
}
.update-steps-container {
list-style-type: none;
width: 100%;
padding: 0px;
.update-step {
display: flex;
width: 100%;
justify-content: space-between;
padding: 10px 0px;
border-bottom: 1px solid $ls-color-gray--light;
&:last-child {
border-bottom: 0px solid;
}
}
}
.update-step-text {
font-size: $font-size-base;
margin: 0px;
line-height: 2rem;
}
.update-status-container {
display: flex;
flex-direction: row;
align-items: center;
.update-time {
font-size: 10px;
color: $ls-color-gray--dark;
margin-right: 10px;
}
.update-status {
font-size: 13px;
width: 88px;
height: 28px;
display: block;
text-align: center;
border-radius: 30px;
text-transform: uppercase;
line-height: 2rem;
}
.status-pending {
background-color: #EAF1FB;
color: $ls-color-secondary;
}
.status-running {
background-color: rgba(21, 178, 236, 0.15);
color: $ls-color-light-blue;
}
.status-finished {
background-color: #D4F6EE;
color: $ls-color-green;
}
.status-error {
background-color: rgba(251, 113, 120, 0.22);
color: $ls-color-red;
}
}
}
.add-new-tax {
height: 45px;
white-space: nowrap;

View File

@ -1,10 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Estimate</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* -- Base -- */
body {
font-family: "DejaVu Sans";
}
@ -12,31 +14,22 @@
html {
margin: 0px;
padding: 0px;
margin-top: 50px;
}
table {
border-collapse: collapse;
}
.header-line {
color:rgba(0, 0, 0, 0.2);
position: absolute;
top: 90px;
left: 0px;
width: 100%;
}
hr {
margin: 0 30px 0 30px;
color:rgba(0, 0, 0, 0.2);
color: rgba(0, 0, 0, 0.2);
border: 0.5px solid #EAF1FB;
}
.header-center {
text-align: center
}
/* -- Header -- */
.header-table {
.header-container {
position: absolute;
width: 100%;
height: 90px;
@ -44,6 +37,14 @@
top: -50px;
}
.header-bottom-divider {
color: rgba(0, 0, 0, 0.2);
position: absolute;
top: 90px;
left: 0px;
width: 100%;
}
.header-logo {
height: 50px;
margin-top: 20px;
@ -51,122 +52,95 @@
color: #817AE3;
}
.inv-flex{
display:flex;
}
.inv-data{
text-align:right;
margin-right:120px;
}
.inv-value{
text-align:left;
margin-left:160px;
}
.header {
font-size: 20px;
color: rgba(0, 0, 0, 0.7);
}
.TextColor1 {
font-size: 16px;
color: rgba(0, 0, 0, 0.5);
}
@page {
margin-top: 60px !important;
}
.wrapper {
display: block;
margin-top: 0px;
padding-top: 16px;
padding-bottom: 20px;
display: block;
margin-top: 0px;
padding-top: 16px;
padding-bottom: 20px;
}
.address {
/* display: inline-block; */
padding-top: 30px
/* -- Company Details -- */
.company-details-container {
padding-top: 30px;
}
.company {
.company-address-container {
float: left;
padding-left: 30px;
font-weight: normal;
display: inline;
float:left;
width:30%;
width: 30%;
text-transform: capitalize;
margin-bottom: 2px;
}
.company h1 {
font-style: normal;
font-weight: normal;
.company-address-container {
padding-left: 30px;
float: left;
width: 30%;
text-transform: capitalize;
margin-bottom: 2px;
}
.company-address-container h1 {
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
margin-bottom: 0px;
margin-top: 10px;
}
.company-add {
.company-address {
margin-top: 2px;
text-align: left;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 15px;
color: #595959;
}
.job-add {
/* display: inline; */
.estimate-details-container {
float: right;
padding: 10px 30px 0 0;
}
.amount-due {
background-color: #f2f2f2;
}
.textRight {
text-align: right;
}
.textLeft {
text-align: left;
}
.textStyle1 {
font-style: normal;
font-weight: normal;
.attribute-label {
font-size: 12px;
line-height: 18px;
padding-right: 40px;
text-align: left;
color: #55547A
}
.textStyle2 {
font-style: normal;
font-weight: normal;
.attribute-value {
font-size: 12px;
line-height: 18px;
text-align: right;
}
.bill-add {
width:45%;
/* -- Customer Address -- */
.customer-address-container {
width: 45%;
padding: 0px 0 0 0px;
}
/* -------------------------- */
/* shipping style */
/* -- Shipping -- */
.ship-address-container {
.shipping-address-container {
float: right;
padding-left: 30px;
}
.ship-to {
font-style: normal;
font-weight: normal;
.shipping-address-container--left {
float: left;
padding-left: 0px;
}
.shipping-address-label {
font-size: 12px;
line-height: 18px;
padding: 0px;
@ -174,18 +148,15 @@
margin-bottom: 0px;
}
.ship-user-name {
max-width: 250px
font-style: normal;
font-weight: normal;
.shipping-address-name {
max-width: 160px;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin: 0px;
}
.ship-user-address {
font-style: normal;
font-weight: normal;
.shipping-address {
font-size: 10px;
line-height: 15px;
color: #595959;
@ -193,27 +164,15 @@
margin: 0px;
width: 160px;
}
.ship-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
}
/* -------------------------- */
/* billing style */
/* -- Billing -- */
.bill-address-container {
.billing-address-container {
float: left;
padding-left: 30px;
}
.bill-to {
font-style: normal;
font-weight: normal;
.billing-address-label {
font-size: 12px;
line-height: 18px;
padding: 0px;
@ -221,19 +180,15 @@
margin-bottom: 0px;
}
.bill-user-name {
max-width: 250px
font-style: normal;
font-weight: normal;
.billing-address-name {
max-width: 160px;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin: 0px;
}
.bill-user-address {
font-style: normal;
font-weight: normal;
.billing-address {
font-size: 10px;
line-height: 15px;
color: #595959;
@ -242,28 +197,20 @@
width: 160px;
}
.bill-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
}
/* -- Items Table -- */
.table2 {
.items-table {
margin-top: 35px;
padding: 0px 30px 10px 30px;
page-break-before: avoid;
page-break-after: auto;
}
.table2 hr {
height:0.1px;
.items-table hr {
height: 0.1px;
}
.ItemTableHeader {
.item-table-heading {
font-size: 13.5;
text-align: center;
color: rgba(0, 0, 0, 0.85);
@ -271,85 +218,86 @@
padding-bottom: 10px;
}
tr.main-table-header th {
tr.item-table-heading-row th {
border-bottom: 0.620315px solid #E8E8E8;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
.main-table-header {
.item-table-heading-row {
margin-bottom: 10px;
}
tr.item-details td {
font-style: normal;
font-weight: normal;
tr.item-row td {
font-size: 12px;
line-height: 18px;
}
.items {
.item-cell {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
color: #040405;
text-align: center;
padding: 5px;
padding-top: 10px;
}
.padd8 {
padding-top: 8px;
padding-bottom: 8px;
}
.padd2 {
padding-top: 2px;
padding-bottom: 2px;
}
.table3 {
border-top: none;
box-sizing: border-box;
width: 630px;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
}
.total-border-left {
border: 1px solid #E8E8E8!important;
border-right: 0px !important;
padding-top: 0px;
padding:8px !important;
}
.total-border-right {
border: 1px solid #E8E8E8!important;
border-left: 0px !important;
padding-top: 0px;
padding:8px !important;
}
.inv-item {
border-color: #d9d9d9;
}
.no-border {
border: none;
.item-description {
color: #595959;
font-size: 9px;
line-height: 12px;
}
.desc {
font-weight: 100;
text-align: justify;
font-size: 10px;
margin-bottom: 15px;
margin-top:7px;
color:rgba(0, 0, 0, 0.85);
/* -- Total Display Table -- */
.total-display-container {
padding: 0 25px;
}
.total-display-table {
border-top: none;
box-sizing: border-box;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
margin-left: 500px;
margin-top: 20px;
}
.total-table-attribute-label {
font-size: 12px;
color: #55547A;
text-align: left;
padding-left: 10px;
}
.total-table-attribute-value {
font-weight: bold;
text-align: right;
font-size: 12px;
color: #040405;
padding-right: 10px;
padding-top: 2px;
padding-bottom: 2px;
}
.total-border-left {
border: 1px solid #E8E8E8 !important;
border-right: 0px !important;
padding-top: 0px;
padding: 8px !important;
}
.total-border-right {
border: 1px solid #E8E8E8 !important;
border-left: 0px !important;
padding-top: 0px;
padding: 8px !important;
}
/* -- Notes -- */
.notes {
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
@ -360,8 +308,6 @@
}
.notes-label {
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
@ -371,65 +317,122 @@
padding-bottom: 10px;
}
/* -- Helpers -- */
.text-primary {
color: #5851DB;
}
.text-center {
text-align: center
}
table .text-left {
text-align: left;
}
table .text-right {
text-align: right;
}
.border-0 {
border: none;
}
.py-2 {
padding-top: 2px;
padding-bottom: 2px;
}
.py-8 {
padding-top: 8px;
padding-bottom: 8px;
}
.py-3 {
padding: 3px 0;
}
.pr-20 {
padding-right: 20px;
}
.pr-10 {
padding-right: 10px;
}
.pl-20 {
padding-left: 20px;
}
.pl-10 {
padding-left: 10px;
}
.pl-0 {
padding-left: 0;
}
</style>
</head>
<body>
<div class="header-table">
<div class="header-container">
<table width="100%">
<tr>
<td class="header-center">
<td class="text-center">
@if($logo)
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
@else
@if($estimate->user->company)
<h2 class="header-logo"> {{$estimate->user->company->name}} </h2>
@endif
@if($estimate->user->company)
<h2 class="header-logo"> {{$estimate->user->company->name}} </h2>
@endif
@endif
</td>
</tr>
</table>
<hr class="header-line" />
<hr class="header-bottom-divider" />
</div>
<div class="wrapper">
<div class="address">
<div class="company">
<div class="company-details-container">
<div class="company-address-container">
@include('app.pdf.estimate.partials.company-address')
</div>
<div class="job-add">
<table>
<div class="estimate-details-container">
<table class="estimate-details-table">
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Estimate Number</td>
<td class="textStyle2"> &nbsp;{{$estimate->estimate_number}}</td>
<td class="attribute-label">Estimate Number</td>
<td class="attribute-value"> &nbsp;{{$estimate->estimate_number}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Estimate Date </td>
<td class="textStyle2"> &nbsp;{{$estimate->formattedEstimateDate}}</td>
<td class="attribute-label">Estimate Date </td>
<td class="attribute-value"> &nbsp;{{$estimate->formattedEstimateDate}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Expiry Date</td>
<td class="textStyle2"> &nbsp;{{$estimate->formattedExpiryDate}}</td>
<td class="attribute-label">Expiry Date</td>
<td class="attribute-value"> &nbsp;{{$estimate->formattedExpiryDate}}</td>
</tr>
</table>
</div>
<div style="clear: both;"></div>
</div>
<div class="bill-add">
<div class="bill-address-container">
<div class="customer-address-container">
<div class="billing-address-container">
@include('app.pdf.estimate.partials.billing-address')
</div>
@if($estimate->user->billingaddress)
<div class="ship-address-container">
<div class="shipping-address-container">
@else
<div class="ship-address-container " style="float:left;padding-left:0px;">
<div class="shipping-address-container--left">
@endif
@include('app.pdf.estimate.partials.shipping-address')
@include('app.pdf.estimate.partials.shipping-address')
</div>
<div style="clear: both;"></div>
</div>
<div style="position:relative">
@include('app.pdf.estimate.partials.table')
</div>
@include('app.pdf.estimate.partials.notes')
</div>
<div style="position:relative">
@include('app.pdf.estimate.partials.table')
</div>
@include('app.pdf.estimate.partials.notes')
</div>
</body>
</html>

View File

@ -1,9 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Estimate</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* -- Base -- */
body {
font-family: "DejaVu Sans";
}
@ -11,22 +13,21 @@
html {
margin: 0px;
padding: 0px;
margin-top: 50px;
}
table {
border-collapse: collapse;
}
.header-left {
padding-top: 45px;
padding-bottom: 45px;
padding-left: 30px;
display:inline-block;
width:30%;
hr {
color: rgba(0, 0, 0, 0.2);
border: 0.5px solid #EAF1FB;
}
@page {
margin-top: 60px !important;
}
.header-table {
/* -- Header -- */
.header-container {
background: #817AE3;
position: absolute;
width: 100%;
@ -34,351 +35,286 @@
left: 0px;
top: -60px;
}
.header-section-left {
padding-top: 45px;
padding-bottom: 45px;
padding-left: 30px;
display: inline-block;
width: 30%;
}
.header-logo {
position: absolute;
height: 50px;
text-transform: capitalize;
color: #fff;
}
.header-right {
display:inline-block;
width:35%;
float:right;
.header-section-right {
display: inline-block;
width: 35%;
float: right;
padding: 20px 30px 20px 0px;
text-align: right;
color:white;
color: white;
}
}
.inv-flex{
display:flex;
}
.inv-data{
text-align:right;
margin-right:120px;
}
.inv-value{
text-align:left;
margin-left:160px;
}
.header {
font-size: 20px;
color: rgba(0, 0, 0, 0.7);
}
.TextColor1 {
font-size: 16px;
color: rgba(0, 0, 0, 0.5);
/* -- Estimate Details -- */
.estimate-details-container {
text-align: center;
width: 40%;
}
.wrapper {
display: block;
margin-top: 60px;
padding-bottom: 20px;
.estimate-details-container h1 {
margin: 0;
font-size: 24px;
line-height: 36px;
text-align: right;
font-family: "DejaVu Sans";
}
.address {
display: block;
padding-top: 20px;
}
.company {
padding: 0 0 0 30px;
display: inline;
float:left;
width:30%;
}
.company h1 {
font-style: normal;
font-weight: bold;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
margin-bottom: 0;
}
.company-add {
font-style: normal;
font-weight: normal;
.estimate-details-container h4 {
margin: 0;
font-size: 10px;
line-height: 15px;
color: #595959;
margin-top: 0px;
}
/* -------------------------- */
/* billing style */
.bill-address-container {
display: block;
/* position: absolute; */
float:right;
padding: 0 40px 0 0;
}
.bill-to {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
padding: 0px;
margin-bottom: 0px;
}
.bill-user-name {
max-width: 250px
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
.bill-user-address {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
width: 170px;
}
.bill-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
}
/* -------------------------- */
/* shipping style */
.ship-address-container {
display: block;
float:right;
padding: 0 30px 0 0;
}
.ship-to {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
padding: 0px;
margin-bottom: 0px;
}
.ship-user-name {
max-width: 250px
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
.ship-user-address {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
width: 170px;
}
.ship-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
}
.job-add {
display: inline;
float: right;
width:40%;
}
.amount-due {
background-color: #f2f2f2;
}
.textRight {
text-align: right;
}
.textLeft {
text-align: left;
.estimate-details-container h3 {
margin-bottom: 1px;
margin-top: 0;
}
.textStyle1 {
/* -- Address -- */
.wrapper {
display: block;
margin-top: 60px;
padding-bottom: 20px;
}
.address-container {
display: block;
padding-top: 20px;
}
/* -- Company Address -- */
.company-address-container {
padding: 0 0 0 30px;
display: inline;
float: left;
width: 30%;
}
.company-address-container {
padding-left: 30px;
float: left;
width: 30%;
text-transform: capitalize;
margin-bottom: 2px;
}
.company-address-container h1 {
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
margin-bottom: 0px;
margin-top: 10px;
}
.company-address {
margin-top: 2px;
text-align: left;
font-size: 12px;
line-height: 15px;
color: #595959;
}
/* -- Billing -- */
.billing-address-container {
display: block;
/* position: absolute; */
float: right;
padding: 0 40px 0 0;
}
.billing-address-label {
font-size: 12px;
line-height: 18px;
padding: 0px;
margin-bottom: 0px;
}
.billing-address-name {
max-width: 160px;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
.billing-address {
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
width: 170px;
}
/* -- Shipping -- */
.shipping-address-container {
display: block;
float: right;
padding: 0 30px 0 0;
}
.shipping-address-label {
font-size: 12px;
line-height: 18px;
padding: 0px;
margin-bottom: 0px;
}
.shipping-address-name {
max-width: 160px;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
.shipping-address {
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
width: 170px;
}
.attribute-label {
font-size: 12;
font-weight: bold;
line-height:22px;
line-height: 22px;
color: rgba(0, 0, 0, 0.8);
}
.textStyle2 {
.attribute-value {
font-size: 12;
line-height:22px;
line-height: 22px;
color: rgba(0, 0, 0, 0.7);
}
.main-table-header td {
padding: 5px;
padding-bottom: 10px;
}
/* -- Items Table -- */
.main-table-header {
border-bottom: 1px solid red;
}
.table2 {
margin-top: 30px;
padding: 0px 30px 10px 30px;
.items-table {
padding: 30px 30px 10px 30px;
page-break-before: avoid;
page-break-after: auto;
}
hr {
margin: 0 30px 0 30px;
color:rgba(0, 0, 0, 0.2);
border: 0.5px solid #EAF1FB;
.items-table hr {
height: 0.1px;
margin: 0 30px;
}
.table2 hr {
height:0.1px;
}
.ItemTableHeader {
.item-table-heading {
font-size: 13.5;
text-align: center;
color: rgba(0, 0, 0, 0.85);
padding: 5px;
}
tr.main-table-header th {
.item-table-heading-row td {
padding: 5px;
padding-bottom: 10px;
}
.item-table-heading-row {
border-bottom: 1px solid red;
}
tr.item-table-heading-row th {
border-bottom: 0.620315px solid #E8E8E8;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
tr.item-details td {
font-style: normal;
font-weight: normal;
tr.item-row td {
font-size: 12px;
line-height: 18px;
}
.items {
.item-cell {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
color: #040405;
text-align: center;
padding: 5px;
padding-top: 10px;
}
.note-header {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
.item-description {
color: #595959;
font-size: 9px;
line-height: 12px;
page-break-inside: avoid;
}
.note-text {
font-size: 10;
color: rgba(0, 0, 0, 0.6);
/* -- Total Display Table -- */
.total-display-container {
padding: 0 25px;
}
.padd8 {
padding-top: 8px;
padding-bottom: 8px;
.item-cell-table-hr {
margin: 0 25px 0 30px;
}
.padd2 {
.total-display-table {
box-sizing: border-box;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
margin-left: 500px;
border: 1px solid #EAF1FB;
border-top: none;
}
.total-table-attribute-label {
font-size: 12px;
color: #55547A;
text-align: left;
padding-left: 10px;
}
.total-table-attribute-value {
font-weight: bold;
text-align: right;
font-size: 12px;
color: #040405;
padding-right: 10px;
padding-top: 2px;
padding-bottom: 2px;
}
.table3 {
border: 1px solid #EAF1FB;
border-top: none;
box-sizing: border-box;
width: 630px;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
}
.text-per-item-table3 {
border: 1px solid #EAF1FB;
border-top: none;
padding-right: 30px;
box-sizing: border-box;
width: 260px;
/* height: 100px; */
position: absolute;
right: -25;
}
.inv-item {
border-color: #d9d9d9;
}
.no-border {
border: none;
}
.desc {
font-weight: 100;
text-align: justify;
font-size: 10px;
margin-bottom: 15px;
margin-top:7px;
color:rgba(0, 0, 0, 0.85);
}
.company-details{
text-align: center;
width: 40%;
}
.company-details h1 {
margin:0;
font-style: normal;
font-weight: 500;
font-size: 24px;
line-height: 36px;
text-align: right;
}
.company-details h4 {
margin:0;
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
text-align: right;
}
.company-details h3 {
margin-bottom:1px;
margin-top:0;
}
/* -- Notes -- */
.notes {
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
@ -389,8 +325,6 @@
}
.notes-label {
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
@ -400,23 +334,79 @@
padding-bottom: 10px;
}
/* -- Helpers -- */
.text-primary {
color: #5851DB;
}
.text-center {
text-align: center
}
table .text-left {
text-align: left;
}
table .text-right {
text-align: right;
}
.border-0 {
border: none;
}
.py-2 {
padding-top: 2px;
padding-bottom: 2px;
}
.py-8 {
padding-top: 8px;
padding-bottom: 8px;
}
.py-3 {
padding: 3px 0;
}
.pr-20 {
padding-right: 20px;
}
.pr-10 {
padding-right: 10px;
}
.pl-20 {
padding-left: 20px;
}
.pl-10 {
padding-left: 10px;
}
.pl-0 {
padding-left: 0;
}
</style>
</head>
<body>
<div class="header-table">
<div class="header-container">
<table width="100%">
<tr>
@if($logo)
<td width="60%" class="header-left">
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
@else
<td width="60%" class="header-left" style="padding-top: 0px;">
@if($estimate->user->company)
<h1 class="header-logo"> {{$estimate->user->company->name}} </h1>
@endif
@endif
<td width="60%" class="header-section-left">
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
@else
<td width="60%" class="header-section-left" style="padding-top: 0px;">
@if($estimate->user->company)
<h1 class="header-logo"> {{$estimate->user->company->name}} </h1>
@endif
@endif
</td>
<td width="40%" class="header-right company-details">
<td width="40%" class="header-section-right estimate-details-container">
<h1>Estimate</h1>
<h4>{{$estimate->estimate_number}}</h4>
<h4>{{$estimate->formattedEstimateDate}}</h4>
@ -426,24 +416,24 @@
</div>
<hr>
<div class="wrapper">
<div class="address">
<div class="company">
<div class="address-container">
<div class="company-address-container">
@include('app.pdf.estimate.partials.company-address')
</div>
<div class="ship-address-container">
<div class="shipping-address-container">
@include('app.pdf.estimate.partials.shipping-address')
</div>
@if($estimate->user->shippingaddress)
<div class="bill-address-container">
<div class="billing-address-container">
@else
<div class="bill-address-container" style="float:right;padding-right:0px;">
<div class="billing-address-container" style="float:right; padding-right:0px;">
@endif
@include('app.pdf.estimate.partials.billing-address')
</div>
<div style="clear: both;"></div>
@include('app.pdf.estimate.partials.table')
@include('app.pdf.estimate.partials.notes')
</div>
@include('app.pdf.estimate.partials.table')
@include('app.pdf.estimate.partials.notes')
</div>
</body>
</html>

View File

@ -1,10 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Estimate</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* -- Base -- */
body {
font-family: "DejaVu Sans";
}
@ -12,147 +14,138 @@
html {
margin: 0px;
padding: 0px;
margin-top: 50px;
}
table {
border-collapse: collapse;
}
.header-line {
color:rgba(0, 0, 0, 0.2);
position: absolute;
top: 80px;
left: 0px;
right: -70px;
width: 100%;
}
hr {
color:rgba(0, 0, 0, 0.2);
color: rgba(0, 0, 0, 0.2);
border: 0.5px solid #EAF1FB;
}
.items-table-hr{
margin: 0 30px 0 30px;
}
/* -- Header -- */
.header-left {
padding-top: 45px;
padding-bottom: 45px;
padding-left: 30px;
display:inline-block;
width:30%;
}
.header-table {
.header-container {
position: absolute;
width: 100%;
height: 150px;
left: 0px;
top: -60px;
}
.header-section-left {
padding-top: 45px;
padding-bottom: 45px;
padding-left: 30px;
display: inline-block;
width: 30%;
}
.header-bottom-divider {
color: rgba(0, 0, 0, 0.2);
position: absolute;
top: 100px;
left: 0px;
width: 100%;
}
.header-logo {
position: absolute;
height: 50px;
text-transform: capitalize;
color: #817AE3;
}
.header-right {
display:inline-block;
.header-section-right {
display: inline-block;
position: absolute;
right:0;
right: 0;
padding: 15px 30px 15px 0px;
float: right;
}
.inv-flex{
display:flex;
}
.inv-data{
text-align:right;
margin-right:120px;
}
.inv-value{
text-align:left;
margin-left:160px;
}
.header {
font-size: 20px;
color: rgba(0, 0, 0, 0.7);
}
.TextColor1 {
font-size: 16px;
color: rgba(0, 0, 0, 0.5);
/* -- Company Address -- */
.company-address-container {
width: auto;
text-transform: capitalize;
margin-bottom: 2px;
}
@page {
margin-top: 60px !important;
}
.company-address-container h1 {
.wrapper {
display: block;
padding-top: 50px;
padding-bottom: 20px;
}
.address {
display: inline-block;
padding-top: 100px
}
.bill-add {
display: inline;
float:left;
width:40%;
padding: 0 0 0 30px;
}
.company {
padding-left: 30px;
display: inline;
float:left;
width:30%;
}
.company h1 {
font-style: normal;
font-weight: bold;
font-size: 18px;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
margin-bottom: 0px;
margin-top: 10px;
}
.company-add {
.company-address {
margin-top: 2px;
text-align: left;
font-style: normal;
font-weight: normal;
font-size: 10px;
font-size: 12px;
line-height: 15px;
color: #595959;
margin: 0px;
}
/* -------------------------- */
/* shipping style */
.ship-to {
/* -- Content Wrapper -- */
.wrapper {
display: block;
padding-top: 100px;
padding-bottom: 20px;
}
.main-content {
}
.customer-address-container {
display: inline;
float: left;
width: 40%;
padding: 0 0 0 30px;
}
/* -- Shipping -- */
.shipping-address-container {
float: right;
display: block;
}
.shipping-address-container--left {
float: left;
padding-left: 0;
}
.shipping-address-label {
padding-top: 5px;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
margin-bottom: 0px;
}
.ship-user-name {
.shipping-address-name {
padding: 0px;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
margin: 0px;
max-width: 160px;
}
.ship-user-address {
font-style: normal;
font-weight: normal;
.shipping-address {
font-size: 10px;
line-height: 15px;
color: #595959;
@ -160,38 +153,28 @@
width: 160px;
}
.ship-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
/* -- Billing -- */
.billing-address-container {
float: left;
}
/* -------------------------- */
/* billing style */
.bill-to {
.billing-address-label {
padding-top: 5px;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
margin-bottom: 0px;
}
.bill-user-name {
.billing-address-name {
padding: 0px;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
margin: 0px;
max-width: 160px;
}
.bill-user-address {
font-style: normal;
font-weight: normal;
.billing-address {
font-size: 10px;
line-height: 15px;
color: #595959;
@ -199,187 +182,131 @@
width: 160px;
}
.bill-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
}
/* -- Estimate Details -- */
.job-add {
.estimate-details-container {
display: block;
float: right;
padding: 20px 30px 0 0;
}
.amount-due {
background-color: #f2f2f2;
}
.textRight {
text-align: right;
}
.textLeft {
.attribute-label {
font-size: 12px;
line-height: 18px;
text-align: left;
color: #55547A
}
.textStyle1 {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
.textStyle2 {
font-style: normal;
font-weight: normal;
.attribute-value {
font-size: 12px;
line-height: 18px;
text-align: right;
}
.main-table-header td {
padding: 10px;
}
.main-table-header {
border-bottom: 1px solid red;
}
tr.main-table-header th {
font-style: normal;
font-weight: 600;
font-size: 12px;
line-height: 18px;
}
tr.item-details td {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
.table2 {
padding: 0px 30px 10px 30px;
/* -- Items Table -- */
.items-table {
padding: 30px 30px 10px 30px;
page-break-before: avoid;
page-break-after: auto;
}
.table2 hr {
height:0.1px;
.items-table hr {
height: 0.1px;
margin: 0 30px;
}
.ItemTableHeader {
.item-table-heading {
font-size: 13.5;
text-align: center;
color: rgba(0, 0, 0, 0.85);
padding: 5px;
padding-bottom: 10px;
}
.items {
tr.item-table-heading-row th {
border-bottom: 0.620315px solid #E8E8E8;
font-size: 12px;
line-height: 18px;
}
.item-table-heading-row {
margin-bottom: 10px;
}
tr.item-row td {
font-size: 12px;
line-height: 18px;
}
.item-cell {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
color: #040405;
text-align: center;
padding: 5px;
padding-top: 10px;
border-color: #d9d9d9;
}
.note-header {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
.item-description {
color: #595959;
font-size: 9px;
line-height: 12px;
}
.note-text {
font-size: 10;
color: rgba(0, 0, 0, 0.6);
.item-cell-table-hr {
margin: 0 30px 0 30px;
}
.padd8 {
padding-top: 8px;
padding-bottom: 8px;
/* -- Total Display Table -- */
.total-display-container {
padding: 0 25px;
}
.padd2 {
.total-display-table {
box-sizing: border-box;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
margin-left: 500px;
margin-top: 20px;
}
.total-table-attribute-label {
font-size: 12px;
color: #55547A;
text-align: left;
padding-left: 10px;
}
.total-table-attribute-value {
font-weight: bold;
text-align: right;
font-size: 12px;
color: #040405;
padding-right: 10px;
padding-top: 2px;
padding-bottom: 2px;
}
.table3 {
border: 1px solid #EAF1FB;
border-top: none;
box-sizing: border-box;
width: 630px;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
.total-border-left {
border: 1px solid #E8E8E8 !important;
border-right: 0px !important;
padding-top: 0px;
padding: 8px !important;
}
td.estimate-total1 {
text-align:left;
padding: 15px 0 15px 10px;
font-size:12px;
line-height: 18px;
color: #55547A;
border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8;
border-left:1px solid #E8E8E8;
.total-border-right {
border: 1px solid #E8E8E8 !important;
border-left: 0px !important;
padding-top: 0px;
padding: 8px !important;
}
td.estimate-total2 {
font-weight: 500;
text-align: right;
font-size:12px;
line-height: 18px;
padding: 15px 10px 15px 0;
color: #5851DB;
border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8;
border-right:1px solid #E8E8E8;
}
.inv-item {
border-color: #d9d9d9;
}
.no-border {
border: none;
}
.desc {
font-weight: 100;
text-align: justify;
font-size: 10px;
margin-bottom: 15px;
margin-top:7px;
color:rgba(0, 0, 0, 0.85);
}
.company-details h1 {
margin:0;
font-style: normal;
font-weight: bold;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
text-align: left;
max-width: 220px;
}
.company-details h4 {
margin:0;
font-style: normal;
font-weight: 100;
font-size: 18px;
line-height: 25px;
text-align: right;
}
.company-details h3 {
margin-bottom:1px;
margin-top:0;
}
tr.total td {
border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8;
}
/* -- Notes -- */
.notes {
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
@ -390,8 +317,6 @@
}
.notes-label {
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
@ -401,67 +326,125 @@
padding-bottom: 10px;
}
/* -- Helpers -- */
.text-primary {
color: #5851DB;
}
.text-center {
text-align: center
}
table .text-left {
text-align: left;
}
table .text-right {
text-align: right;
}
.border-0 {
border: none;
}
.py-2 {
padding-top: 2px;
padding-bottom: 2px;
}
.py-8 {
padding-top: 8px;
padding-bottom: 8px;
}
.py-3 {
padding: 3px 0;
}
.pr-20 {
padding-right: 20px;
}
.pr-10 {
padding-right: 10px;
}
.pl-20 {
padding-left: 20px;
}
.pl-10 {
padding-left: 10px;
}
.pl-0 {
padding-left: 0;
}
</style>
</head>
<body>
<div class="header-table">
<div class="header-container">
<table width="100%">
<tr>
@if($logo)
<td class="header-left">
<td class="header-section-left">
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
@else
@else
@if($estimate->user->company)
<td class="header-left" style="padding-top:0px;">
<h1 class="header-logo"> {{$estimate->user->company->name}} </h1>
<td class="header-section-left" style="padding-top:0px;">
<h1 class="header-logo"> {{$estimate->user->company->name}} </h1>
@endif
@endif
@endif
</td>
<td class="header-right company-details">
<td class="header-section-right company-address-container">
@include('app.pdf.estimate.partials.company-address')
</td>
</tr>
</table>
</div>
<hr class="header-line">
<hr class="header-bottom-divider">
<div class="wrapper">
<div class="address">
<div class="bill-add">
<div style="float:left;">
<div class="main-content">
<div class="customer-address-container">
<div class="billing-address-container">
@include('app.pdf.estimate.partials.billing-address')
</div>
@if($estimate->user->billingaddress)
<div style="float:right;">
@else
<div style="float:left;">
@endif
@include('app.pdf.estimate.partials.shipping-address')
@if($estimate->user->billingaddress)
<div class="shipping-address-container">
@else
<div class="shipping-address-container--left">
@endif
@include('app.pdf.estimate.partials.shipping-address')
</div>
<div style="clear: both;"></div>
</div>
<div class="estimate-details-container">
<table>
<tr>
<td class="attribute-label">Estimate Number</td>
<td class="attribute-value"> &nbsp;{{$estimate->estimate_number}}</td>
</tr>
<tr>
<td class="attribute-label">Estimate Date </td>
<td class="attribute-value"> &nbsp;{{$estimate->formattedEstimateDate}}</td>
</tr>
<tr>
<td class="attribute-label">Expiry Date</td>
<td class="attribute-value"> &nbsp;{{$estimate->formattedExpiryDate}}</td>
</tr>
</table>
</div>
<div style="clear: both;"></div>
</div>
<div class="job-add">
<table>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Estimate Number</td>
<td class="textStyle2"> &nbsp;{{$estimate->estimate_number}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Estimate Date </td>
<td class="textStyle2"> &nbsp;{{$estimate->formattedEstimateDate}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Expiry Date</td>
<td class="textStyle2"> &nbsp;{{$estimate->formattedExpiryDate}}</td>
</tr>
</table>
</div>
<div style="clear: both;"></div>
@include('app.pdf.estimate.partials.table')
@include('app.pdf.estimate.partials.notes')
</div>
@include('app.pdf.estimate.partials.table')
@include('app.pdf.estimate.partials.notes')
</div>
</body>
</html>

View File

@ -1,11 +1,11 @@
@if($estimate->user->billingaddress)
<p class="bill-to">Bill To,</p>
<p class="billing-address-label">Bill To,</p>
@if($estimate->user->billingaddress->name)
<p class="bill-user-name">
<p class="billing-address-name">
{{$estimate->user->billingaddress->name}}
</p>
@endif
<p class="bill-user-address">
<p class="billing-address">
@if($estimate->user->billingaddress->address_street_1)
{!! nl2br(htmlspecialchars($estimate->user->billingaddress->address_street_1)) !!}<br>
@endif
@ -31,7 +31,7 @@
@endif
@if($estimate->user->billingaddress->phone)
<p class="bill-user-phone">
<p class="billing-address">
Phone :{{$estimate->user->billingaddress->phone}}
</p>
@endif

View File

@ -3,7 +3,7 @@
@endif
@if($company_address)
<p class="company-add">
<p class="company-address">
@if($company_address->addresses[0]['address_street_1'])
{!! nl2br(htmlspecialchars($company_address->addresses[0]['address_street_1'])) !!} <br>
@endif

View File

@ -1,11 +1,11 @@
@if($estimate->user->shippingaddress)
<p class="ship-to">Ship To,</p>
<p class="shipping-address-label">Ship To,</p>
@if($estimate->user->shippingaddress->name)
<p class="ship-user-name">
<p class="shipping-address-name">
{{$estimate->user->shippingaddress->name}}
</p>
@endif
<p class="ship-user-address">
<p class="shipping-address">
@if($estimate->user->shippingaddress->address_street_1)
{!! nl2br(htmlspecialchars($estimate->user->shippingaddress->address_street_1)) !!}<br>
@endif
@ -30,8 +30,8 @@
{{$estimate->user->shippingaddress->country->name}}<br>
@endif
@if($estimate->user->phone)
<p class="ship-user-phone">
@if($estimate->user->shippingAddress->phone)
<p class="shipping-address">
Phone :{{$estimate->user->shippingaddress->phone}}
</p>
@endif

View File

@ -1,50 +1,49 @@
<table width="100%" class="table2" cellspacing="0" border="0">
<tr class="main-table-header">
<th width="2%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">#</th>
<th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th>
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Price</th>
<table width="100%" class="items-table" cellspacing="0" border="0">
<tr class="item-table-heading-row">
<th width="2%" class="item-table-heading text-right pr-20">#</th>
<th width="40%" class="item-table-heading text-left pl-0">Items</th>
<th class="item-table-heading text-right pr-20">Quantity</th>
<th class="item-table-heading text-right pr-20">Price</th>
@if($estimate->discount_per_item === 'YES')
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-left: 10px">Discount</th>
<th class="item-table-heading text-right pl-10">Discount</th>
@endif
<th class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th>
<th class="item-table-heading text-right">Amount </th>
</tr>
@php
$index = 1
@endphp
@foreach ($estimate->items as $item)
<tr class="item-details">
<tr class="item-row">
<td
class="inv-item items"
style="text-align: right; color: #040405; padding-right: 20px; vertical-align: top;"
class="item-cell text-right pr-20"
style="vertical-align: top;"
>
{{$index}}
</td>
<td
class="inv-item items"
style="text-align: left; color: #040405;padding-left: 0px"
class="item-cell text-left pl-0"
>
<span>{{ $item->name }}</span><br>
<span
style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;"
class="item-description"
>
{!! nl2br(htmlspecialchars($item->description)) !!}
</span>
</td>
<td
class="inv-item items"
style="text-align: right; color: #040405; padding-right: 20px"
class="item-cell text-right pr-20"
style="vertical-align: top;"
>
{{$item->quantity}}
</td>
<td
class="inv-item items"
style="text-align: right; color: #040405; padding-right: 20px"
class="item-cell text-right pr-20"
style="vertical-align: top;"
>
{!! format_money_pdf($item->price, $estimate->user->currency) !!}
</td>
@if($estimate->discount_per_item === 'YES')
<td class="inv-item items" style="text-align: right; color: #040405; padding-left: 10px">
<td class="item-cell text-right pl-10" style="vertical-align: top;">
@if($item->discount_type === 'fixed')
{!! format_money_pdf($item->discount_val, $estimate->user->currency) !!}
@endif
@ -53,7 +52,7 @@
@endif
</td>
@endif
<td class="inv-item items" style="text-align: right; color: #040405;">
<td class="item-cell text-right" style="vertical-align: top;">
{!! format_money_pdf($item->total, $estimate->user->currency) !!}
</td>
</tr>
@ -63,74 +62,68 @@
@endforeach
</table>
<hr class="items-table-hr">
<hr class="item-cell-table-hr">
<table width="100%" cellspacing="0px" style="margin-left:420px;margin-top: 10px" border="0" class="table3 @if(count($estimate->items) > 12) page-break @endif">
<tr>
<td class="no-borde" style="color: #55547A; padding-left:10px; font-size:12px;">Subtotal</td>
<td class="no-border items"
style="padding-right:10px; text-align: right; font-size:12px; color: #040405; font-weight: 500;">{!! format_money_pdf($estimate->sub_total, $estimate->user->currency) !!}</td>
</tr>
@if ($estimate->tax_per_item === 'YES')
@for ($i = 0; $i < count($labels); $i++)
<tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
{{$labels[$i]}}
</td>
<td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
{!! format_money_pdf($taxes[$i], $estimate->user->currency) !!}
</td>
</tr>
@endfor
@else
@foreach ($estimate->taxes as $tax)
<tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
{{$tax->name.' ('.$tax->percent.'%)'}}
</td>
<td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
{!! format_money_pdf($tax->amount, $estimate->user->currency) !!}
</td>
</tr>
@endforeach
@endif
@if ($estimate->discount_per_item === 'NO')
<div class="total-display-container">
<table width="100%" cellspacing="0px" border="0" class="total-display-table @if(count($estimate->items) > 12) page-break @endif">
<tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
@if($estimate->discount_type === 'fixed')
Discount
@endif
@if($estimate->discount_type === 'percentage')
Discount ({{$estimate->discount}}%)
@endif
</td>
<td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
@if($estimate->discount_type === 'fixed')
{!! format_money_pdf($estimate->discount_val, $estimate->user->currency) !!}
@endif
@if($estimate->discount_type === 'percentage')
{!! format_money_pdf($estimate->discount_val, $estimate->user->currency) !!}
@endif
<td class="border-0 total-table-attribute-label">Subtotal</td>
<td class="border-0 item-cell total-table-attribute-value ">{!! format_money_pdf($estimate->sub_total, $estimate->user->currency) !!}</td>
</tr>
@if ($estimate->tax_per_item === 'YES')
@for ($i = 0; $i < count($labels); $i++)
<tr>
<td class="border-0 total-table-attribute-label">
{{$labels[$i]}}
</td>
<td class="border-0 item-cell total-table-attribute-value">
{!! format_money_pdf($taxes[$i], $estimate->user->currency) !!}
</td>
</tr>
@endfor
@else
@foreach ($estimate->taxes as $tax)
<tr>
<td class="border-0 total-table-attribute-label">
{{$tax->name.' ('.$tax->percent.'%)'}}
</td>
<td class="border-0 item-cell total-table-attribute-value" >
{!! format_money_pdf($tax->amount, $estimate->user->currency) !!}
</td>
</tr>
@endforeach
@endif
@if ($estimate->discount_per_item === 'NO')
<tr>
<td class="border-0 total-table-attribute-label pl-10">
@if($estimate->discount_type === 'fixed')
Discount
@endif
@if($estimate->discount_type === 'percentage')
Discount ({{$estimate->discount}}%)
@endif
</td>
<td class="border-0 item-cell total-table-attribute-value text-right">
@if($estimate->discount_type === 'fixed')
{!! format_money_pdf($estimate->discount_val, $estimate->user->currency) !!}
@endif
@if($estimate->discount_type === 'percentage')
{!! format_money_pdf($estimate->discount_val, $estimate->user->currency) !!}
@endif
</td>
</tr>
@endif
<tr>
<td class="py-3"></td>
<td class="py-3"></td>
</tr>
<tr>
<td class="border-0 total-border-left total-table-attribute-label">Total</td>
<td class="border-0 total-border-right item-cell py-8 total-table-attribute-value text-primary">
{!! format_money_pdf($estimate->total, $estimate->user->currency)!!}
</td>
</tr>
@endif
<tr>
<td style="padding:3px 0px"></td>
<td style="padding:3px 0px"></td>
</tr>
<tr>
<td class="no-border total-border-left"
style="padding-left:10px; padding-bottom:10px; text-align:left; padding-top:20px; font-size:12px; color: #55547A;"
>
<label class="total-bottom"> Total </label>
</td>
<td
class="no-border total-border-right items padd8"
style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; padding-top:20px; color: #5851DB"
>
{!! format_money_pdf($estimate->total, $estimate->user->currency)!!}
</td>
</tr>
</table>
</table>
</div>

View File

@ -1,10 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Invoice</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* -- Base -- */
body {
font-family: "DejaVu Sans";
}
@ -15,29 +17,27 @@
margin-top: 50px;
}
table {
border-collapse: collapse;
.text-center {
text-align: center
}
.header-line {
color:rgba(0, 0, 0, 0.2);
hr {
margin: 0 30px 0 30px;
color: rgba(0, 0, 0, 0.2);
border: 0.5px solid #EAF1FB;
}
/* -- Header -- */
.header-bottom-divider {
color: rgba(0, 0, 0, 0.2);
position: absolute;
top: 90px;
left: 0px;
width: 100%;
}
hr {
margin: 0 30px 0 30px;
color:rgba(0, 0, 0, 0.2);
border: 0.5px solid #EAF1FB;
}
.header-center {
text-align: center
}
.header-table {
.header-container {
position: absolute;
width: 100%;
height: 90px;
@ -52,122 +52,69 @@
color: #817AE3;
}
.inv-flex{
display:flex;
}
.inv-data{
text-align:right;
margin-right:120px;
}
.inv-value{
text-align:left;
margin-left:160px;
}
.header {
font-size: 20px;
color: rgba(0, 0, 0, 0.7);
}
.TextColor1 {
font-size: 16px;
color: rgba(0, 0, 0, 0.5);
.content-wrapper {
display: block;
margin-top: 0px;
padding-top: 16px;
padding-bottom: 20px;
}
@page {
margin-top: 60px !important;
}
.wrapper {
display: block;
margin-top: 0px;
padding-top: 16px;
padding-bottom: 20px;
}
.address {
/* display: inline-block; */
padding-top: 30px
}
.company {
float: left;
.company-address-container {
padding-left: 30px;
font-weight: normal;
display: inline;
float:left;
width:30%;
float: left;
width: 30%;
text-transform: capitalize;
margin-bottom: 2px;
}
.company h1 {
font-style: normal;
font-weight: normal;
.company-address-container h1 {
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
margin-bottom: 0px;
margin-top: 10px;
}
.company-add {
.company-address {
margin-top: 2px;
text-align: left;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 15px;
color: #595959;
}
.job-add {
/* display: inline; */
.invoice-details-container {
float: right;
padding: 10px 30px 0 0;
}
.amount-due {
background-color: #f2f2f2;
}
.textRight {
text-align: right;
}
.textLeft {
text-align: left;
}
.textStyle1 {
font-style: normal;
font-weight: normal;
.attribute-label {
font-size: 12px;
line-height: 18px;
padding-right: 40px;
text-align: left;
color: #55547A;
}
.textStyle2 {
font-style: normal;
font-weight: normal;
.attribute-value {
font-size: 12px;
line-height: 18px;
text-align: right;
}
.bill-add {
width:45%;
padding: 0px 0 0 0px;
}
/* -------------------------- */
/* shipping style */
/* -- Shipping -- */
.ship-address-container {
.shipping-address-container {
float: right;
padding-left: 30px;
}
.ship-to {
font-style: normal;
font-weight: normal;
.shipping-address-label {
font-size: 12px;
line-height: 18px;
padding: 0px;
@ -175,18 +122,15 @@
margin-bottom: 0px;
}
.ship-user-name {
max-width: 250px
font-style: normal;
font-weight: normal;
.shipping-address-name {
max-width: 160px;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin: 0px;
}
.ship-user-address {
font-style: normal;
font-weight: normal;
.shipping-address {
font-size: 10px;
line-height: 15px;
color: #595959;
@ -194,27 +138,15 @@
margin: 0px;
width: 160px;
}
.ship-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
}
/* -------------------------- */
/* billing style */
/* -- Billing -- */
.bill-address-container {
.billing-address-container {
float: left;
padding-left: 30px;
}
.bill-to {
font-style: normal;
font-weight: normal;
.billing-address-label {
font-size: 12px;
line-height: 18px;
padding: 0px;
@ -222,19 +154,15 @@
margin-bottom: 0px;
}
.bill-user-name {
max-width: 250px
font-style: normal;
font-weight: normal;
.billing-address-name {
max-width: 160px;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin: 0px;
}
.bill-user-address {
font-style: normal;
font-weight: normal;
.billing-address {
font-size: 10px;
line-height: 15px;
color: #595959;
@ -243,115 +171,102 @@
width: 160px;
}
.bill-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
}
/* -- Items Table -- */
.table2 {
.items-table {
margin-top: 35px;
padding: 0px 30px 10px 30px;
page-break-before: avoid;
page-break-after: auto;
}
.table2 hr {
height:0.1px;
.items-table hr {
height: 0.1px;
}
.ItemTableHeader {
.item-table-heading {
font-size: 13.5;
text-align: center;
color: rgba(0, 0, 0, 0.85);
padding: 5px;
color: #55547A;
}
tr.main-table-header th {
tr.item-table-heading-row th {
border-bottom: 0.620315px solid #E8E8E8;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
tr.item-details td {
font-style: normal;
font-weight: normal;
tr.item-row td {
font-size: 12px;
line-height: 18px;
}
.items {
.item-cell {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
text-align: center;
padding: 5px;
padding-top: 10px;
color: #040405;
}
.padd8 {
padding-top: 8px;
padding-bottom: 8px;
.item-description {
color: #595959;
font-size: 9px;
line-height: 12px;
}
.padd2 {
/* -- Total Display Table -- */
.total-display-container {
padding: 0 25px;
}
.total-display-table {
border-top: none;
box-sizing: border-box;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
margin-left: 500px;
margin-top: 20px;
}
.total-table-attribute-label {
font-size: 13px;
color: #55547A;
text-align: left;
padding-left: 10px;
}
.total-table-attribute-value {
font-weight: bold;
text-align: right;
font-size: 13px;
color: #040405;
padding-right: 10px;
padding-top: 2px;
padding-bottom: 2px;
}
.table3 {
/* border: 1px solid #EAF1FB; */
border-top: none;
/* padding-right: 30px; */
box-sizing: border-box;
width: 630px;
/* position: absolute;
right: -25; */
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
}
.total-border-left {
border: 1px solid #E8E8E8!important;
border: 1px solid #E8E8E8 !important;
border-right: 0px !important;
padding-top: 0px;
padding:8px !important;
padding: 8px !important;
}
.total-border-right {
border: 1px solid #E8E8E8!important;
border: 1px solid #E8E8E8 !important;
border-left: 0px !important;
padding-top: 0px;
padding:8px !important;
padding: 8px !important;
}
.inv-item {
border-color: #d9d9d9;
}
.no-border {
border: none;
}
.desc {
font-weight: 100;
text-align: justify;
font-size: 10px;
margin-bottom: 15px;
margin-top:7px;
color:rgba(0, 0, 0, 0.85);
}
/* -- Notes -- */
.notes {
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
@ -362,8 +277,6 @@
}
.notes-label {
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
@ -373,13 +286,69 @@
padding-bottom: 10px;
}
/* -- Helpers -- */
.text-primary {
color: #5851DB;
}
.text-center {
text-align: center
}
table .text-left {
text-align: left;
}
table .text-right {
text-align: right;
}
.border-0 {
border: none;
}
.py-2 {
padding-top: 2px;
padding-bottom: 2px;
}
.py-8 {
padding-top: 8px;
padding-bottom: 8px;
}
.py-3 {
padding: 3px 0;
}
.pr-20 {
padding-right: 20px;
}
.pr-10 {
padding-right: 10px;
}
.pl-20 {
padding-left: 20px;
}
.pl-10 {
padding-left: 10px;
}
.pl-0 {
padding-left: 0;
}
</style>
</head>
<body>
<div class="header-table">
<div class="header-container">
<table width="100%">
<tr>
<td class="header-center">
<td class="text-center">
@if($logo)
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
@else
@ -390,48 +359,44 @@
</td>
</tr>
</table>
<hr class="header-line" style="border: 0.620315px solid #E8E8E8;"/>
<hr class="header-bottom-divider" style="border: 0.620315px solid #E8E8E8;" />
</div>
<div class="wrapper">
<div class="address">
<div class="company">
<div class="content-wrapper">
<div style="padding-top: 30px">
<div class="company-address-container">
@include('app.pdf.invoice.partials.company-address')
</div>
<div class="job-add">
<div class="invoice-details-container">
<table>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Invoice Number</td>
<td class="textStyle2"> &nbsp;{{$invoice->invoice_number}}</td>
<td class="attribute-label">Invoice Number</td>
<td class="attribute-value"> &nbsp;{{$invoice->invoice_number}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Invoice Date </td>
<td class="textStyle2"> &nbsp;{{$invoice->formattedInvoiceDate}}</td>
<td class="attribute-label">Invoice Date </td>
<td class="attribute-value"> &nbsp;{{$invoice->formattedInvoiceDate}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Due date</td>
<td class="textStyle2"> &nbsp;{{$invoice->formattedDueDate}}</td>
<td class="attribute-label">Due date</td>
<td class="attribute-value"> &nbsp;{{$invoice->formattedDueDate}}</td>
</tr>
</table>
</div>
<div style="clear: both;"></div>
</div>
<div class="bill-add">
<div class="bill-address-container">
@include('app.pdf.invoice.partials.billing-address')
</div>
@if($invoice->user->billingaddress)
<div class="ship-address-container">
@else
<div class="ship-address-container " style="float:left;padding-left:0px;">
@endif
@include('app.pdf.invoice.partials.shipping-address')
</div>
<div style="clear: both;"></div>
<div class="billing-address-container">
@include('app.pdf.invoice.partials.billing-address')
</div>
<div style="position:relative">
<div class="shipping-address-container" @if($invoice->user->billingaddress) style="float:left;" @else style="float:left: padding-left: 0px;" @endif>
@include('app.pdf.invoice.partials.shipping-address')
@if($invoice->user->billingaddress) <div style="clear: both;"></div> @endif
</div>
<div style="position: relative; clear: both;">
@include('app.pdf.invoice.partials.table')
</div>
@include('app.pdf.invoice.partials.notes')
</div>
</body>
</html>

View File

@ -1,10 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Invoice</title>
{{-- <link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet"> --}}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* -- Base -- */
body {
font-family: "DejaVu Sans";
}
@ -12,22 +13,22 @@
html {
margin: 0px;
padding: 0px;
margin-top: 50px;
}
table {
border-collapse: collapse;
}
.header-left {
padding-top: 45px;
padding-bottom: 45px;
padding-left: 30px;
display:inline-block;
width:30%;
hr {
margin: 0 30px 0 30px;
color: rgba(0, 0, 0, 0.2);
border: 0.5px solid #EAF1FB;
}
@page {
margin-top: 60px !important;
}
.header-table {
/* -- Header -- */
.header-container {
background: #817AE3;
position: absolute;
width: 100%;
@ -35,351 +36,266 @@
left: 0px;
top: -60px;
}
.header-section-left {
padding-top: 45px;
padding-bottom: 45px;
padding-left: 30px;
display: inline-block;
width: 30%;
}
.header-logo {
position: absolute;
height: 50px;
text-transform: capitalize;
color: #fff;
}
.header-right {
display:inline-block;
width:35%;
float:right;
.header-section-right {
display: inline-block;
width: 35%;
float: right;
padding: 20px 30px 20px 0px;
text-align: right;
color:white;
color: white;
}
}
.inv-flex{
display:flex;
}
.inv-data{
text-align:right;
margin-right:120px;
}
.inv-value{
text-align:left;
margin-left:160px;
}
.header {
font-size: 20px;
color: rgba(0, 0, 0, 0.7);
}
.TextColor1 {
font-size: 16px;
color: rgba(0, 0, 0, 0.5);
}
/* -- Estimate Details -- */
.wrapper {
display: block;
margin-top: 60px;
padding-bottom: 20px;
}
.address {
display: block;
padding-top: 20px;
}
.company {
padding: 0 0 0 30px;
display: inline;
float:left;
width:30%;
}
.company h1 {
font-style: normal;
font-weight: bold;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
margin-bottom: 0;
}
.company-add {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin-top: 0px;
}
/* -------------------------- */
/* billing style */
.bill-address-container {
display: block;
/* position: absolute; */
float:right;
padding: 0 40px 0 0;
}
.bill-to {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
padding: 0px;
margin-bottom: 0px;
}
.bill-user-name {
max-width: 250px
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
.bill-user-address {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
width: 170px;
}
.bill-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
}
/* -------------------------- */
/* shipping style */
.ship-address-container {
display: block;
float:right;
padding: 0 30px 0 0;
}
.ship-to {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
padding: 0px;
margin-bottom: 0px;
}
.ship-user-name {
max-width: 250px
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
.ship-user-address {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
width: 170px;
}
.ship-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
}
.job-add {
display: inline;
float: right;
width:40%;
}
.amount-due {
background-color: #f2f2f2;
}
.textRight {
text-align: right;
}
.textLeft {
text-align: left;
}
.textStyle1 {
font-size: 12;
font-weight: bold;
line-height:22px;
color: rgba(0, 0, 0, 0.8);
}
.textStyle2 {
font-size: 12;
line-height:22px;
color: rgba(0, 0, 0, 0.7);
}
.main-table-header td {
padding: 5px;
padding-bottom: 10px;
}
.main-table-header {
border-bottom: 1px solid red;
}
.table2 {
margin-top: 30px;
padding: 0px 30px 10px 30px;
page-break-before: avoid;
page-break-after: auto;
}
hr {
margin: 0 30px 0 30px;
color:rgba(0, 0, 0, 0.2);
border: 0.5px solid #EAF1FB;
}
.table2 hr {
height:0.1px;
}
.ItemTableHeader {
font-size: 13.5;
text-align: center;
color: rgba(0, 0, 0, 0.85);
padding: 5px;
}
tr.main-table-header th {
border-bottom: 0.620315px solid #E8E8E8;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
tr.item-details td {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
.items {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
text-align: center;
padding: 5px;
padding-top: 10px;
}
.note-header {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
}
.note-text {
font-size: 10;
color: rgba(0, 0, 0, 0.6);
}
.padd8 {
padding-top: 8px;
padding-bottom: 8px;
}
.padd2 {
padding-top: 2px;
padding-bottom: 2px;
}
.table3 {
border: 1px solid #EAF1FB;
border-top: none;
box-sizing: border-box;
width: 630px;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
}
.text-per-item-table3 {
border: 1px solid #EAF1FB;
border-top: none;
padding-right: 30px;
box-sizing: border-box;
width: 260px;
/* height: 100px; */
position: absolute;
right: -25;
}
.inv-item {
border-color: #d9d9d9;
}
.no-border {
border: none;
}
.desc {
font-weight: 100;
text-align: justify;
font-size: 10px;
margin-bottom: 15px;
margin-top:7px;
color:rgba(0, 0, 0, 0.85);
}
.company-details{
.invoice-details-container {
text-align: center;
width: 40%;
}
.company-details h1 {
margin:0;
font-style: normal;
font-weight: 500;
.invoice-details-container h1 {
margin: 0;
font-size: 24px;
line-height: 36px;
text-align: right;
}
.company-details h4 {
margin:0;
font-style: normal;
font-weight: normal;
.invoice-details-container h4 {
margin: 0;
font-size: 10px;
line-height: 15px;
text-align: right;
}
.company-details h3 {
margin-bottom:1px;
margin-top:0;
.invoice-details-container h3 {
margin-bottom: 1px;
margin-top: 0;
}
/* -- Content Wrapper -- */
.content-wrapper {
display: block;
margin-top: 60px;
padding-bottom: 20px;
}
.address-container {
display: block;
padding-top: 20px;
}
/* -- Company -- */
.company-address-container {
padding: 0 0 0 30px;
display: inline;
float: left;
width: 30%;
}
.company-address-container h1 {
font-weight: bold;
font-size: 15px;
letter-spacing: 0.05em;
margin-bottom: 0;
margin-top: 18px;
}
.company-address{
font-size: 10px;
line-height: 15px;
color: #595959;
margin-top: 0px;
}
/* -- Billing -- */
.billing-address-container {
display: block;
/* position: absolute; */
float: right;
padding: 0 40px 0 0;
}
.billing-address-label {
font-size: 12px;
line-height: 18px;
padding: 0px;
margin-bottom: 0px;
}
.billing-address-name {
max-width: 250px;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
.billing-address{
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
width: 170px;
}
/* -- Shipping -- */
.shipping-address-container {
display: block;
float: right;
padding: 0 30px 0 0;
}
.shipping-address-label {
font-size: 12px;
line-height: 18px;
padding: 0px;
margin-bottom: 0px;
}
.shipping-address-name {
max-width: 250px;
font-size: 15px;
line-height: 22px;
padding: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
.shipping-address {
font-size: 10px;
line-height: 15px;
color: #595959;
padding: 0px;
margin: 0px;
width: 170px;
}
/* -- Items Table -- */
.items-table {
margin-top: 35px;
padding: 0px 30px 10px 30px;
page-break-before: avoid;
page-break-after: auto;
}
.items-table hr {
height: 0.1px;
}
.item-table-heading {
font-size: 13.5;
text-align: center;
color: rgba(0, 0, 0, 0.85);
padding: 5px;
color: #55547A;
}
tr.item-table-heading-row th {
border-bottom: 0.620315px solid #E8E8E8;
font-size: 12px;
line-height: 18px;
}
tr.item-row td {
font-size: 12px;
line-height: 18px;
}
.item-cell {
font-size: 13;
text-align: center;
padding: 5px;
padding-top: 10px;
color: #040405;
}
.item-description {
color: #595959;
font-size: 9px;
line-height: 12px;
}
/* -- Total Display Table -- */
.total-display-container {
padding: 0 25px;
}
.item-cell-table-hr {
margin: 0 25px 0 30px;
}
.total-display-table {
box-sizing: border-box;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
margin-left: 500px;
border: 1px solid #EAF1FB;
border-top: none;
}
.total-table-attribute-label {
font-size: 12px;
color: #55547A;
text-align: left;
padding-left: 10px;
}
.total-table-attribute-value {
font-weight: 500;
text-align: right;
font-size: 12px;
color: #040405;
padding-right: 10px;
padding-top: 2px;
padding-bottom: 2px;
}
.total-border-left {
border: 1px solid #E8E8E8 !important;
border-right: 0px !important;
padding-top: 0px;
padding: 8px !important;
}
.total-border-right {
border: 1px solid #E8E8E8 !important;
border-left: 0px !important;
padding-top: 0px;
padding: 8px !important;
}
/* -- Notes -- */
.notes {
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
@ -390,8 +306,6 @@
}
.notes-label {
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
@ -401,23 +315,79 @@
padding-bottom: 10px;
}
/* -- Helpers -- */
.text-primary {
color: #5851DB;
}
.text-center {
text-align: center
}
table .text-left {
text-align: left;
}
table .text-right {
text-align: right;
}
.border-0 {
border: none;
}
.py-2 {
padding-top: 2px;
padding-bottom: 2px;
}
.py-8 {
padding-top: 8px;
padding-bottom: 8px;
}
.py-3 {
padding: 3px 0;
}
.pr-20 {
padding-right: 20px;
}
.pr-10 {
padding-right: 10px;
}
.pl-20 {
padding-left: 20px;
}
.pl-10 {
padding-left: 10px;
}
.pl-0 {
padding-left: 0;
}
</style>
</head>
<body>
<div class="header-table">
<div class="header-container">
<table width="100%">
<tr>
@if($logo)
<td width="60%" class="header-left">
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
@else
<td width="60%" class="header-left" style="padding-top: 0px;">
@if($invoice->user->company)
<h1 class="header-logo"> {{$invoice->user->company->name}} </h1>
@endif
@endif
<td width="60%" class="header-section-left">
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
@else
<td width="60%" class="header-section-left" style="padding-top: 0px;">
@if($invoice->user->company)
<h1 class="header-logo"> {{$invoice->user->company->name}} </h1>
@endif
@endif
</td>
<td width="40%" class="header-right company-details">
<td width="40%" class="header-section-right invoice-details-container">
<h1>Invoice</h1>
<h4>{{$invoice->invoice_number}}</h4>
<h4>{{$invoice->formattedInvoiceDate}}</h4>
@ -426,25 +396,26 @@
</table>
</div>
<hr>
<div class="wrapper">
<div class="address">
<div class="company">
<div class="content-wrapper">
<div class="address-container">
<div class="company-address-container">
@include('app.pdf.invoice.partials.company-address')
</div>
<div class="ship-address-container">
<div class="shipping-address-container">
@include('app.pdf.invoice.partials.shipping-address')
</div>
@if($invoice->user->shippingaddress)
<div class="bill-address-container">
@else
<div class="bill-address-container" style="float:right;padding-right:0px;">
@endif
@include('app.pdf.invoice.partials.billing-address')
<div class="billing-address-container">
@else
<div class="billing-address-container" style="float:right;padding-right:0px;">
@endif
@include('app.pdf.invoice.partials.billing-address')
</div>
<div style="clear: both;"></div>
</div>
<div style="clear: both;"></div>
@include('app.pdf.invoice.partials.table')
@include('app.pdf.invoice.partials.notes')
</div>
@include('app.pdf.invoice.partials.table')
@include('app.pdf.invoice.partials.notes')
</div>
</body>
</html>

View File

@ -1,11 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>Invoice</title>
{{-- <link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet"> --}}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* -- Base -- */
body {
font-family: "DejaVu Sans";
}
@ -13,146 +15,134 @@
html {
margin: 0px;
padding: 0px;
margin-top: 50px;
}
table {
border-collapse: collapse;
}
.header-line {
color:rgba(0, 0, 0, 0.2);
position: absolute;
top: 80px;
left: 0px;
right: -70px;
width: 100%;
}
hr {
color:rgba(0, 0, 0, 0.2);
color: rgba(0, 0, 0, 0.2);
border: 0.5px solid #EAF1FB;
}
.items-table-hr{
margin: 0 30px 0 30px;
/* -- Header -- */
.header-bottom-divider {
color: rgba(0, 0, 0, 0.2);
position: absolute;
top: 100px;
left: 0px;
width: 100%;
}
.header-left {
.header-section-left {
padding-top: 45px;
padding-bottom: 45px;
padding-left: 30px;
display:inline-block;
width:30%;
display: inline-block;
width: 30%;
}
.header-table {
.header-container {
position: absolute;
width: 100%;
height: 150px;
left: 0px;
top: -60px;
}
.header-logo {
position: absolute;
height: 50px;
text-transform: capitalize;
color: #817AE3;
}
.header-right {
display:inline-block;
.header-section-right {
display: inline-block;
position: absolute;
right:0;
right: 0;
padding: 15px 30px 15px 0px;
float: right;
}
.inv-flex{
display:flex;
}
.inv-data{
text-align:right;
margin-right:120px;
}
.inv-value{
text-align:left;
margin-left:160px;
}
.header {
font-size: 20px;
color: rgba(0, 0, 0, 0.7);
}
.TextColor1 {
font-size: 16px;
color: rgba(0, 0, 0, 0.5);
/* -- Company Address */
.company-address-container {
width: auto;
text-transform: capitalize;
margin-bottom: 2px;
}
@page {
margin-top: 60px !important;
}
.wrapper {
display: block;
padding-top: 50px;
padding-bottom: 20px;
}
.address {
display: inline-block;
padding-top: 100px;
}
.bill-add {
display: block;
float:left;
width:40%;
padding: 0 0 0 30px;
}
.company {
padding-left: 30px;
display: inline;
float:left;
width:30%;
}
.company h1 {
font-style: normal;
font-weight: bold;
font-size: 18px;
.company-address-container h1 {
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
margin-bottom: 0px;
margin-top: 10px;
}
.company-add {
text-align: left;
font-style: normal;
font-weight: normal;
font-size: 10px;
.company-address {
margin-top: 2px;
font-size: 12px;
line-height: 15px;
color: #595959;
margin: 0px;
}
/* -------------------------- */
/* shipping style */
.ship-to {
/* -- Content Wrapper */
.content-wrapper {
display: block;
padding-top: 100px;
padding-bottom: 20px;
}
.main-content {
}
.customer-address-container {
display: block;
float: left;
width: 40%;
padding: 0 0 0 30px;
}
/* -- Shipping -- */
.shipping-address-container {
float:right;
display: block;
}
.shipping-address-container--left {
float:left;
display: block;
padding-left: 0;
}
.shipping-address-label {
padding-top: 5px;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
margin-bottom: 0px;
}
.ship-user-name {
.shipping-address-name {
padding: 0px;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
margin: 0px;
max-width: 160px;
}
.ship-user-address {
font-style: normal;
font-weight: normal;
.shipping-address {
font-size: 10px;
line-height: 15px;
color: #595959;
@ -160,237 +150,156 @@
width: 160px;
}
.ship-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
/* -- Billing -- */
.billing-address-container {
display: block;
float: left;
}
/* -------------------------- */
/* billing style */
.bill-to {
.billing-address-label {
padding-top: 5px;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
margin-bottom: 0px;
}
.bill-user-name {
.billing-address-name {
padding: 0px;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
margin: 0px;
max-width: 160px;
}
.bill-user-address {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin:0px;
width: 160px;
}
.bill-user-phone {
font-style: normal;
font-weight: normal;
.billing-address {
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
width: 160px;
}
/* -- Estimate Details -- */
.job-add {
.invoice-details-container {
display: block;
float: right;
padding: 20px 30px 0 0;
}
.amount-due {
background-color: #f2f2f2;
}
.textRight {
text-align: right;
}
.textLeft {
.attribute-label {
font-size: 12px;
line-height: 18px;
text-align: left;
color: #55547A
}
.textStyle1 {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
.textStyle2 {
font-style: normal;
font-weight: normal;
.attribute-value {
font-size: 12px;
line-height: 18px;
text-align: right;
}
.main-table-header td {
padding: 10px;
}
.main-table-header {
border-bottom: 1px solid red;
}
tr.main-table-header th {
font-style: normal;
font-weight: 600;
font-size: 12px;
line-height: 18px;
}
tr.item-details td {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
.table2 {
/* -- Items Table -- */
.items-table {
margin-top: 35px;
padding: 0px 30px 10px 30px;
page-break-before: avoid;
page-break-after: auto;
}
.table2 hr {
height:0.1px;
.items-table hr {
height: 0.1px;
}
.ItemTableHeader {
.item-table-heading {
font-size: 13.5;
text-align: center;
color: rgba(0, 0, 0, 0.85);
padding: 5px;
color: #55547A;
}
.items {
tr.item-table-heading-row th {
border-bottom: 0.620315px solid #E8E8E8;
font-size: 12px;
line-height: 18px;
}
tr.item-row td {
font-size: 12px;
line-height: 18px;
}
.item-cell {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
text-align: center;
padding: 5px;
padding-top: 10px;
color: #040405;
}
.note-header {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
.item-description {
color: #595959;
font-size: 9px;
line-height: 12px;
}
.note-text {
font-size: 10;
color: rgba(0, 0, 0, 0.6);
.item-cell-table-hr {
margin: 0 30px 0 30px;
}
.padd8 {
padding-top: 8px;
padding-bottom: 8px;
/* -- Total Display Table -- */
.total-display-container {
padding: 0 25px;
}
.padd2 {
.total-display-table {
box-sizing: border-box;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
margin-left: 500px;
margin-top: 20px;
}
.total-table-attribute-label {
font-size: 12px;
color: #55547A;
text-align: left;
padding-left: 10px;
}
.total-table-attribute-value {
font-weight: bold;
text-align: right;
font-size: 12px;
color: #040405;
padding-right: 10px;
padding-top: 2px;
padding-bottom: 2px;
}
.table3 {
border: 1px solid #EAF1FB;
border-top: none;
box-sizing: border-box;
width: 630px;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
.total-border-left {
border: 1px solid #E8E8E8 !important;
border-right: 0px !important;
padding-top: 0px;
padding: 8px !important;
}
.text-per-item-table3 {
border: 1px solid #EAF1FB;
border-top: none;
padding-right: 30px;
box-sizing: border-box;
width: 260px;
/* height: 100px; */
position: absolute;
right: -25;
}
td.invoice-total1 {
text-align:left;
padding: 15px 0 15px 10px;
font-size:12px;
line-height: 18px;
color: #55547A;
border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8;
border-left:1px solid #E8E8E8;
}
td.invoice-total2 {
font-weight: 500;
text-align: right;
font-size:12px;
line-height: 18px;
padding: 15px 10px 15px 0;
color: #5851DB;
border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8;
border-right:1px solid #E8E8E8;
}
.inv-item {
border-color: #d9d9d9;
}
.no-border {
border: none;
}
.desc {
font-weight: 100;
text-align: justify;
font-size: 10px;
margin-bottom: 15px;
margin-top:7px;
color:rgba(0, 0, 0, 0.85);
}
.company-details h1 {
margin:0;
font-style: normal;
font-weight: bold;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
text-align: left;
max-width: 220px;
}
.company-details h4 {
margin:0;
font-style: normal;
font-weight: 100;
font-size: 18px;
line-height: 25px;
text-align: right;
}
.company-details h3 {
margin-bottom:1px;
margin-top:0;
}
tr.total td {
border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8;
.total-border-right {
border: 1px solid #E8E8E8 !important;
border-left: 0px !important;
padding-top: 0px;
padding: 8px !important;
}
/* -- Notes -- */
.notes {
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
@ -401,8 +310,6 @@
}
.notes-label {
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
@ -412,67 +319,122 @@
padding-bottom: 10px;
}
/* -- Helpers -- */
.text-primary {
color: #5851DB;
}
.text-center {
text-align: center
}
table .text-left {
text-align: left;
}
table .text-right {
text-align: right;
}
.border-0 {
border: none;
}
.py-2 {
padding-top: 2px;
padding-bottom: 2px;
}
.py-8 {
padding-top: 8px;
padding-bottom: 8px;
}
.py-3 {
padding: 3px 0;
}
.pr-20 {
padding-right: 20px;
}
.pr-10 {
padding-right: 10px;
}
.pl-20 {
padding-left: 20px;
}
.pl-10 {
padding-left: 10px;
}
.pl-0 {
padding-left: 0;
}
</style>
</head>
<body>
<div class="header-table">
<div class="header-container">
<table width="100%">
<tr>
@if($logo)
<td class="header-left">
<td class="header-section-left">
@if($logo)
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
@else
@if($invoice->user->company)
<td class="header-left" style="padding-top:0px;">
<h1 class="header-logo"> {{$invoice->user->company->name}} </h1>
@endif
<h1 class="header-logo"> {{$invoice->user->company->name}} </h1>
@endif
</td>
<td class="header-right company-details">
<td class="header-section-right company-address-container">
@include('app.pdf.invoice.partials.company-address')
</td>
</tr>
</table>
</div>
<hr class="header-line">
<hr class="header-bottom-divider">
<div class="wrapper">
<div class="address">
<div class="bill-add">
<div style="float:left;">
<div class="content-wrapper">
<div class="main-content">
<div class="customer-address-container">
<div class="billing-address-container">
@include('app.pdf.invoice.partials.billing-address')
</div>
@if($invoice->user->billingaddress)
<div style="float:right;">
<div class="shipping-address-container">
@else
<div style="float:left;">
<div class="shipping-address-container--left">
@endif
@include('app.pdf.invoice.partials.shipping-address')
@include('app.pdf.invoice.partials.shipping-address')
</div>
<div style="clear: both;"></div>
</div>
<div class="invoice-details-container">
<table>
<tr>
<td class="attribute-label">Invoice Number</td>
<td class="attribute-value"> &nbsp;{{$invoice->invoice_number}}</td>
</tr>
<tr>
<td class="attribute-label">Invoice Date </td>
<td class="attribute-value"> &nbsp;{{$invoice->formattedInvoiceDate}}</td>
</tr>
<tr>
<td class="attribute-label">Due date</td>
<td class="attribute-value"> &nbsp;{{$invoice->formattedDueDate}}</td>
</tr>
</table>
</div>
<div style="clear: both;"></div>
</div>
<div class="job-add">
<table>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Invoice Number</td>
<td class="textStyle2"> &nbsp;{{$invoice->invoice_number}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Invoice Date </td>
<td class="textStyle2"> &nbsp;{{$invoice->formattedInvoiceDate}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Due date</td>
<td class="textStyle2"> &nbsp;{{$invoice->formattedDueDate}}</td>
</tr>
</table>
</div>
<div style="clear: both;"></div>
@include('app.pdf.invoice.partials.table')
@include('app.pdf.invoice.partials.notes')
</div>
@include('app.pdf.invoice.partials.table')
@include('app.pdf.invoice.partials.notes')
</div>
</body>
</html>

View File

@ -1,11 +1,11 @@
@if($invoice->user->billingaddress)
<p class="bill-to">Bill To,</p>
<p class="billing-address-label">Bill To,</p>
@if($invoice->user->billingaddress->name)
<p class="bill-user-name">
<p class="billing-address-name">
{{$invoice->user->billingaddress->name}}
</p>
@endif
<p class="bill-user-address">
<p class="billing-address">
@if($invoice->user->billingaddress->address_street_1)
{!! nl2br(htmlspecialchars($invoice->user->billingaddress->address_street_1)) !!}<br>
@endif
@ -25,7 +25,7 @@
{{$invoice->user->billingaddress->country->name}}<br>
@endif
@if($invoice->user->billingaddress->phone)
<p class="bill-user-phone">
<p class="billing-address">
Phone :{{$invoice->user->billingaddress->phone}}
</p>
@endif

View File

@ -3,7 +3,7 @@
@endif
@if($company_address)
<p class="company-add">
<p class="company-address">
@if($company_address->addresses[0]['address_street_1'])
{!! nl2br(htmlspecialchars($company_address->addresses[0]['address_street_1'])) !!} <br>
@endif

View File

@ -1,11 +1,11 @@
@if($invoice->user->shippingaddress)
<p class="ship-to">Ship To,</p>
<p class="shipping-address-label">Ship To,</p>
@if($invoice->user->shippingaddress->name)
<p class="ship-user-name">
<p class="shipping-address-name">
{{$invoice->user->shippingaddress->name}}
</p>
@endif
<p class="ship-user-address">
<p class="shipping-address">
@if($invoice->user->shippingaddress->address_street_1)
{!! nl2br(htmlspecialchars($invoice->user->shippingaddress->address_street_1)) !!}<br>
@endif
@ -30,8 +30,8 @@
{{$invoice->user->shippingaddress->country->name}}<br>
@endif
@if($invoice->user->phone)
<p class="ship-user-phone">
@if($invoice->user->shippingaddress->phone)
<p class="shipping-address">
Phone :{{$invoice->user->shippingaddress->phone}}
</p>
@endif

View File

@ -1,46 +1,49 @@
<table width="100%" class="table2" cellspacing="0" border="0">
<tr class="main-table-header">
<th width="2%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">#</th>
<th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th>
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Price</th>
<table width="100%" class="items-table" cellspacing="0" border="0">
<tr class="item-table-heading-row">
<th width="2%" class="item-table-heading text-right pr-20">#</th>
<th width="40%" class="item-table-heading text-left pl-0">Items</th>
<th class="item-table-heading text-right pr-20">Quantity</th>
<th class="item-table-heading pr-20 text-right">Price</th>
@if($invoice->discount_per_item === 'YES')
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-left: 10px">Discount</th>
<th class="item-table-heading text-right pl-10">Discount</th>
@endif
<th class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th>
<th class="item-table-heading text-right">Amount</th>
</tr>
@php
$index = 1
@endphp
@foreach ($invoice->items as $item)
<tr class="item-details">
<tr class="item-row">
<td
class="inv-item items"
style="text-align: right; color: #040405; padding-right: 20px; vertical-align: top;"
class="item-cell text-right pr-20"
style="vertical-align: top;"
>
{{$index}}
</td>
<td
class="inv-item items"
style="text-align: left; color: #040405;padding-left: 0px"
class="item-cell text-left pl-0"
style="vertical-align: top;"
>
<span>{{ $item->name }}</span><br>
<span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{!! nl2br(htmlspecialchars($item->description)) !!}</span>
<span class="item-description">{!! nl2br(htmlspecialchars($item->description)) !!}</span>
</td>
<td
class="inv-item items"
style="text-align: right; color: #040405; padding-right: 20px"
class="item-cell pr-20 text-right"
style="vertical-align: top;"
>
{{$item->quantity}}
</td>
<td
class="inv-item items"
style="text-align: right; color: #040405; padding-right: 20px"
class="item-cell text-right pr-20"
style="vertical-align: top;"
>
{!! format_money_pdf($item->price, $invoice->user->currency) !!}
</td>
@if($invoice->discount_per_item === 'YES')
<td class="inv-item items" style="text-align: right; color: #040405; padding-left: 10px">
<td
class="item-cell text-right pl-10"
style="vertical-align: top;"
>
@if($item->discount_type === 'fixed')
{!! format_money_pdf($item->discount_val, $invoice->user->currency) !!}
@endif
@ -50,8 +53,8 @@
</td>
@endif
<td
class="inv-item items"
style="text-align: right; color: #040405;"
class="item-cell text-right"
style="vertical-align: top;"
>
{!! format_money_pdf($item->total, $invoice->user->currency) !!}
</td>
@ -62,74 +65,74 @@
@endforeach
</table>
<hr class="items-table-hr">
<hr class="item-cell-table-hr">
<table width="100%" cellspacing="0px" style="margin-left:420px; margin-top: 10px" border="0" class="table3 @if(count($invoice->items) > 12) page-break @endif">
<tr>
<td class="no-border" style="color: #55547A; padding-left:10px; font-size:12px;">Subtotal</td>
<td class="no-border items padd2"
style="padding-right:10px; text-align: right; font-size:12px; color: #040405; font-weight: 500;">{!! format_money_pdf($invoice->sub_total, $invoice->user->currency) !!}</td>
</tr>
@if ($invoice->tax_per_item === 'YES')
@for ($i = 0; $i < count($labels); $i++)
<tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
{{$labels[$i]}}
</td>
<td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
{!! format_money_pdf($taxes[$i], $invoice->user->currency) !!}
</td>
</tr>
@endfor
@else
@foreach ($invoice->taxes as $tax)
<tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
{{$tax->name.' ('.$tax->percent.'%)'}}
</td>
<td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
{!! format_money_pdf($tax->amount, $invoice->user->currency) !!}
</td>
</tr>
@endforeach
@endif
@if ($invoice->discount_per_item === 'NO')
<div class="total-display-container">
<table width="100%" cellspacing="0px" border="0" class="total-display-table @if(count($invoice->items) > 12) page-break @endif">
<tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
@if($invoice->discount_type === 'fixed')
Discount
@endif
@if($invoice->discount_type === 'percentage')
Discount ({{$invoice->discount}}%)
@endif
</td>
<td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
@if($invoice->discount_type === 'fixed')
{!! format_money_pdf($invoice->discount_val, $invoice->user->currency) !!}
@endif
@if($invoice->discount_type === 'percentage')
{!! format_money_pdf($invoice->discount_val, $invoice->user->currency) !!}
@endif
<td class="border-0 total-table-attribute-label">Subtotal</td>
<td class="border-0 item-cell py-2 total-table-attribute-value">
{!! format_money_pdf($invoice->sub_total, $invoice->user->currency) !!}
</td>
</tr>
@endif
<tr>
<td style="padding:3px 0px"></td>
<td style="padding:3px 0px"></td>
</tr>
<tr>
<td class="no-border total-border-left"
style="padding-left:10px; padding-bottom:10px; text-align:left; padding-top:20px; font-size:12px; color: #55547A;"
>
<label class="total-bottom"> Total </label>
</td>
<td
class="no-border total-border-right items padd8"
style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; padding-top:20px; color: #5851DB"
>
{!! format_money_pdf($invoice->total, $invoice->user->currency)!!}
</td>
</tr>
</table>
@if ($invoice->tax_per_item === 'YES')
@for ($i = 0; $i < count($labels); $i++)
<tr>
<td class="border-0 total-table-attribute-label">
{{$labels[$i]}}
</td>
<td class="border-0 item-cell py-2 total-table-attribute-value">
{!! format_money_pdf($taxes[$i], $invoice->user->currency) !!}
</td>
</tr>
@endfor
@else
@foreach ($invoice->taxes as $tax)
<tr>
<td class="border-0 total-table-attribute-label">
{{$tax->name.' ('.$tax->percent.'%)'}}
</td>
<td class="border-0 item-cell py-2 total-table-attribute-value">
{!! format_money_pdf($tax->amount, $invoice->user->currency) !!}
</td>
</tr>
@endforeach
@endif
@if ($invoice->discount_per_item === 'NO')
<tr>
<td class="border-0 total-table-attribute-label">
@if($invoice->discount_type === 'fixed')
Discount
@endif
@if($invoice->discount_type === 'percentage')
Discount ({{$invoice->discount}}%)
@endif
</td>
<td class="border-0 item-cell py-2 total-table-attribute-value" >
@if($invoice->discount_type === 'fixed')
{!! format_money_pdf($invoice->discount_val, $invoice->user->currency) !!}
@endif
@if($invoice->discount_type === 'percentage')
{!! format_money_pdf($invoice->discount_val, $invoice->user->currency) !!}
@endif
</td>
</tr>
@endif
<tr>
<td class="py-3"></td>
<td class="py-3"></td>
</tr>
<tr>
<td class="border-0 total-border-left total-table-attribute-label">
Total
</td>
<td
class="border-0 total-border-right item-cell py-8 total-table-attribute-value text-primary"
>
{!! format_money_pdf($invoice->total, $invoice->user->currency)!!}
</td>
</tr>
</table>
</div>

View File

@ -1,11 +1,11 @@
@if($payment->user->billingaddress)
<p class="bill-to">Received From:</p>
<p class="billing-address-label">Received From:</p>
@if($payment->user->billingaddress->name)
<p class="bill-user-name">
<p class="billing-address-name">
{{$payment->user->billingaddress->name}}
</p>
@endif
<p class="bill-user-address">
<p class="billing-address">
@if($payment->user->billingaddress->address_street_1)
{!! nl2br(htmlspecialchars($payment->user->billingaddress->address_street_1)) !!}<br>
@endif
@ -25,7 +25,7 @@
{{$payment->user->billingaddress->country->name}}<br>
@endif
@if($payment->user->billingaddress->phone)
<p class="bill-user-phone">
<p class="billing-address">
Phone :{{$payment->user->billingaddress->phone}}
</p>
@endif

View File

@ -3,7 +3,7 @@
@endif
@if($company_address)
<p class="company-add">
<p class="company-address">
@if($company_address->addresses[0]['address_street_1'])
{!! nl2br(htmlspecialchars($company_address->addresses[0]['address_street_1'])) !!} <br>
@endif

View File

@ -1,11 +1,11 @@
@if($payment->user->shippingaddress)
<p class="ship-to">Ship To,</p>
<p class="shipping-address-label">Ship To,</p>
@if($payment->user->shippingaddress->name)
<p class="ship-user-name">
<p class="shipping-address-name">
{{$payment->user->shippingaddress->name}}
</p>
@endif
<p class="ship-user-address">
<p class="shipping-address">
@if($payment->user->shippingaddress->address_street_1)
{!! nl2br(htmlspecialchars($payment->user->shippingaddress->address_street_1)) !!}<br>
@endif
@ -31,7 +31,7 @@
@endif
@if($payment->user->phone)
<p class="ship-user-phone">
<p class="shipping-address">
Phone :{{$payment->user->shippingaddress->phone}}
</p>
@endif

View File

@ -2,10 +2,10 @@
<html>
<head>
<title>Invoice</title>
{{-- <link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet"> --}}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style type="text/css">
/* -- Base -- */
body {
font-family: "DejaVu Sans";
}
@ -13,6 +13,7 @@
html {
margin: 0px;
padding: 0px;
margin-top: 50px;
}
table {
border-collapse: collapse;
@ -27,339 +28,48 @@
width: 100%;
}
.header-left {
padding-top: 45px;
padding-bottom: 45px;
padding-left: 30px;
display:inline-block;
width:30%;
}
.header-table {
/* -- Heeader -- */
.header-container {
position: absolute;
width: 100%;
height: 150px;
left: 0px;
top: -60px;
}
.header-section-left {
padding-top: 45px;
padding-bottom: 45px;
padding-left: 30px;
display:inline-block;
width:30%;
}
.header-logo {
position: absolute;
height: 50px;
text-transform: capitalize;
color: #817AE3;
}
.header-right {
.header-section-right {
display:inline-block;
position: absolute;
right:0;
padding: 15px 30px 15px 0px;
float: right;
}
.inv-flex{
display:flex;
}
.inv-data{
text-align:right;
margin-right:120px;
}
.inv-value{
text-align:left;
margin-left:160px;
}
.header {
font-size: 20px;
color: rgba(0, 0, 0, 0.7);
}
.TextColor1 {
font-size: 16px;
color: rgba(0, 0, 0, 0.5);
}
/* -- Company Address -- */
@page {
margin-top: 60px !important;
}
.wrapper {
display: block;
height: 200px;
}
.address {
display: inline-block;
padding-top: 20px
}
.bill-add {
display: block;
float:left;
width:40%;
padding: 0 0 0 30px;
}
.company {
padding-left: 30px;
display: inline;
float:left;
width:30%;
}
.company h1 {
font-style: normal;
font-weight: bold;
font-size: 18px;
line-height: 22px;
letter-spacing: 0.05em;
}
.company-add {
text-align: left;
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
}
/* -------------------------- */
/* shipping style */
.ship-to {
padding-top: 5px;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
margin-bottom: 0px;
}
.ship-user-name {
padding: 0px;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
margin: 0px;
}
.ship-user-address {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
width: 160px;
}
.ship-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
}
/* -------------------------- */
/* billing style */
.bill-to {
padding-top: 5px;
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
margin-bottom: 0px;
color: #55547A;
}
.bill-user-name {
padding: 0px;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
margin: 0px;
}
.bill-user-address {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin:0px;
width: 160px;
}
.bill-user-phone {
font-style: normal;
font-weight: normal;
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
}
.job-add {
display: inline;
position: absolute;
float: right;
width: 40%;
height: 120px;
padding: 20px 30px 0 0;
}
.amount-due {
background-color: #f2f2f2;
}
.textRight {
text-align: right;
}
.textLeft {
text-align: left;
}
.textStyle1 {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
.textStyle2 {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
text-align: right;
}
.main-table-header td {
padding: 10px;
}
.main-table-header {
border-bottom: 1px solid red;
}
tr.main-table-header th {
font-style: normal;
font-weight: 600;
font-size: 12px;
line-height: 18px;
}
tr.item-details td {
font-style: normal;
font-weight: normal;
font-size: 12px;
line-height: 18px;
}
.table2 {
margin-top: 188px;
border-bottom: 1px solid #EAF1FB;
padding: 0px 30px 0 30px;
page-break-before: avoid;
page-break-after: auto;
}
.table2 hr {
height:0.1px;
}
.ItemTableHeader {
font-size: 13.5;
text-align: center;
color: rgba(0, 0, 0, 0.85);
padding: 5px;
}
.items {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
text-align: center;
padding: 5px;
}
.note-header {
font-size: 13;
color: rgba(0, 0, 0, 0.6);
}
.note-text {
font-size: 10;
color: rgba(0, 0, 0, 0.6);
}
.padd8 {
padding-top: 8px;
padding-bottom: 8px;
}
.padd2 {
padding-top: 2px;
padding-bottom: 2px;
}
.table3 {
border: 1px solid #EAF1FB;
border-top: none;
box-sizing: border-box;
width: 630px;
page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
}
.text-per-item-table3 {
border: 1px solid #EAF1FB;
border-top: none;
padding-right: 30px;
box-sizing: border-box;
width: 260px;
/* height: 100px; */
position: absolute;
right: -25;
}
td.invoice-total1 {
text-align:left;
padding: 15px 0 15px 10px;
font-size:12px;
line-height: 18px;
color: #55547A;
border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8;
border-left:1px solid #E8E8E8;
}
td.invoice-total2 {
font-weight: 500;
text-align: right;
font-size:12px;
line-height: 18px;
padding: 15px 10px 15px 0;
color: #5851DB;
border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8;
border-right:1px solid #E8E8E8;
}
.inv-item {
border-color: #d9d9d9;
}
.no-border {
border: none;
}
.desc {
font-weight: 100;
text-align: justify;
font-size: 10px;
margin-bottom: 15px;
margin-top:7px;
color:rgba(0, 0, 0, 0.85);
}
.company-details h1 {
margin:0;
font-style: normal;
font-weight: bold;
font-size: 15px;
line-height: 22px;
@ -367,26 +77,117 @@
text-align: left;
max-width: 220px;
}
.company-details h4 {
margin:0;
font-style: normal;
font-weight: 100;
font-size: 18px;
line-height: 25px;
text-align: right;
}
.company-details h3 {
margin-bottom:1px;
margin-top:0;
}
tr.total td {
border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8;
.company-address{
text-align: left;
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
}
.content-wrapper {
display: block;
height: 200px;
}
.main-content {
display: inline-block;
padding-top: 20px
}
/* -- Customer Address -- */
.customer-address-container {
display: block;
float:left;
width:40%;
padding: 0 0 0 30px;
}
/* -- Shipping -- */
.shipping-address-label {
padding-top: 5px;
font-size: 12px;
line-height: 18px;
margin-bottom: 0px;
}
.shipping-address-name {
padding: 0px;
font-size: 15px;
line-height: 22px;
margin: 0px;
}
.shipping-address {
font-size: 10px;
line-height: 15px;
color: #595959;
margin: 0px;
width: 160px;
}
/* -- Billing -- */
.billing-address-container {
float: left;
}
.billing-address-container--right {
float: right;
}
.billing-address-label {
padding-top: 5px;
font-size: 12px;
line-height: 18px;
margin-bottom: 0px;
color: #55547A;
}
.billing-address-name {
padding: 0px;
font-size: 15px;
line-height: 22px;
margin: 0px;
}
.billing-address {
font-size: 10px;
line-height: 15px;
color: #595959;
margin:0px;
width: 160px;
}
/* -- Payment Details -- */
.payment-details-container {
display: inline;
position: absolute;
float: right;
width: 40%;
height: 120px;
padding: 20px 30px 0 0;
}
.attribute-label {
font-size: 12px;
line-height: 18px;
text-align: left;
color: #55547A
}
.attribute-value {
font-size: 12px;
line-height: 18px;
text-align: right;
}
/* -- Notes -- */
.notes {
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
@ -397,8 +198,6 @@
}
.notes-label {
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
@ -408,7 +207,7 @@
padding-bottom: 10px;
}
.content-header {
.content-heading {
margin-top: 120px;
width: 100%;
text-align: center;
@ -419,14 +218,17 @@
margin: 0 0 0 0;
}
.content-header span {
font-weight: 500;
.content-heading span {
font-weight: 400;
font-size: 14px;
line-height: 25px;
padding-bottom: 5px;
border-bottom: 1px solid #B9C1D1;
}
.total-amount {
/* -- Total Display Box -- */
.total-display-box {
width: 315px;
display: block;
margin-right: 30px;
@ -437,7 +239,7 @@
padding: 12px 15px 15px 15px;
}
.total-amount-label {
.total-display-label {
display: inline;
font-weight: 600;
font-size: 14px;
@ -445,7 +247,7 @@
color: #595959;
}
.total-amount span {
.total-display-box span {
float: right;
font-weight: 500;
font-size: 14px;
@ -453,62 +255,64 @@
text-align: right;
color: #5851D8;
}
</style>
</head>
<body>
<div class="header-table">
<div class="header-container">
<table width="100%">
<tr>
@if($logo)
<td class="header-left">
<td class="header-section-left">
<img class="header-logo" src="{{ $logo }}" alt="Company Logo">
@else
@if($payment->user->company)
<td class="header-left" style="padding-top:0px;">
<td class="header-section-left" style="padding-top:0px;">
<h1 class="header-logo"> {{$payment->user->company->name}} </h1>
@endif
@endif
</td>
<td class="header-right company-details">
<td class="header-section-right company-details">
@include('app.pdf.payment.partials.company-address')
</td>
</tr>
</table>
</div>
<hr style="border: 0.620315px solid #E8E8E8;">
<p class="content-header">
<p class="content-heading">
<span>PAYMENT RECEIPT</span>
</p>
<div class="wrapper">
<div class="address">
<div class="bill-add">
<div style="float:left;">
<div class="content-wrapper">
<div class="main-content">
<div class="customer-address-container">
<div class="billing-address-container">
@include('app.pdf.payment.partials.billing-address')
</div>
<div style="float:right;">
<div class="billing-address-container--right">
</div>
<div style="clear: both;"></div>
</div>
<div class="job-add">
<div class="payment-details-container">
<table width="100%">
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Payment Date</td>
<td class="textStyle2"> &nbsp;{{$payment->formattedPaymentDate}}</td>
<td class="attribute-label">Payment Date</td>
<td class="attribute-value"> &nbsp;{{$payment->formattedPaymentDate}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Payment Number</td>
<td class="textStyle2"> &nbsp;{{$payment->payment_number}}</td>
<td class="attribute-label">Payment Number</td>
<td class="attribute-value"> &nbsp;{{$payment->payment_number}}</td>
</tr>
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Payment Mode</td>
<td class="textStyle2"> &nbsp;{{$payment->paymentMethod ? $payment->paymentMethod->name : '-'}}</td>
<td class="attribute-label">Payment Mode</td>
<td class="attribute-value"> &nbsp;{{$payment->paymentMethod ? $payment->paymentMethod->name : '-'}}</td>
</tr>
@if ($payment->invoice && $payment->invoice->invoice_number)
<tr>
<td class="textStyle1" style="text-align: left; color: #55547A">Invoice</td>
<td class="textStyle2"> &nbsp;{{$payment->invoice->invoice_number}}</td>
<td class="attribute-label">Invoice</td>
<td class="attribute-value"> &nbsp;{{$payment->invoice->invoice_number}}</td>
</tr>
@endif
</table>
@ -516,8 +320,8 @@
</div>
<div style="clear: both;"></div>
</div>
<div class="total-amount">
<p class="total-amount-label">Amount Received</p>
<div class="total-display-box">
<p class="total-display-label">Amount Received</p>
<span>{!! format_money_pdf($payment->amount, $payment->user->currency) !!}</span>
</div>
</body>

View File

@ -2,35 +2,24 @@
<html lang="en">
<head>
<title>Expenses Report</title>
{{-- <link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet"> --}}
<style type="text/css">
body {
font-family: "DejaVu Sans";
}
/* html {
margin: 0px;
padding: 0px;
} */
table {
border-collapse: collapse;
}
.main-container {
/* padding: 30px 60px; */
}
.sub-container{
padding: 0px 20px;
}
.header {
.report-header {
width: 100%;
}
.heading-text {
font-style: normal;
font-weight: 600;
font-size: 24px;
color: #5851D8;
@ -41,7 +30,6 @@
}
.heading-date-range {
font-style: normal;
font-weight: 600;
font-size: 15px;
color: #A5ACC1;
@ -52,10 +40,8 @@
}
.sub-heading-text {
font-style: normal;
font-weight: 600;
font-size: 16px;
/* line-height: 21px; */
color: #595959;
padding: 0px;
margin: 0px;
@ -65,8 +51,6 @@
.expenses-title {
margin-top: 60px;
padding-left: 3px;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
color: #040405;
@ -84,18 +68,14 @@
.expense-title {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
color: #595959;
}
.expense-money {
.expense-amount {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
text-align: right;
@ -118,7 +98,6 @@
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 21px;
@ -126,7 +105,7 @@
color: #040405;
}
.total-expense-table {
.report-footer {
width: 100%;
margin-top: 40px;
padding: 15px 20px;
@ -134,22 +113,20 @@
box-sizing: border-box;
}
.total-expense-title {
.report-footer-label {
padding: 0px;
margin: 0px;
text-align: left;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 21px;
color: #595959;
}
.total-expense-money {
.report-footer-value {
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 20px;
line-height: 21px;
@ -158,61 +135,59 @@
</style>
</head>
<body>
<div class="main-container">
<div class="sub-container">
<table class="header">
<tr>
<td>
<p class="heading-text">{{ $company->name }}</p>
</td>
<td>
<p class="heading-date-range">{{ $from_date }} - {{ $to_date }}</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text">EXPENSES REPORT</p>
</td>
</tr>
<div class="sub-container">
<table class="report-header">
<tr>
<td>
<p class="heading-text">{{ $company->name }}</p>
</td>
<td>
<p class="heading-date-range">{{ $from_date }} - {{ $to_date }}</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text">EXPENSES REPORT</p>
</td>
</tr>
</table>
<p class="expenses-title">Expenses</p>
<div class="expenses-table-container">
<table class="expenses-table">
@foreach ($expenseCategories as $expenseCategory)
<tr>
<td>
<p class="expense-title">
{{ $expenseCategory->category->name }}
</p>
</td>
<td>
<p class="expense-amount">
{!! format_money_pdf($expenseCategory->total_amount) !!}
</p>
</td>
</tr>
@endforeach
</table>
<p class="expenses-title">Expenses</p>
<div class="expenses-table-container">
<table class="expenses-table">
@foreach ($expenseCategories as $expenseCategory)
<tr>
<td>
<p class="expense-title">
{{ $expenseCategory->category->name }}
</p>
</td>
<td>
<p class="expense-money">
{!! format_money_pdf($expenseCategory->total_amount) !!}
</p>
</td>
</tr>
@endforeach
</table>
</div>
</div>
<table class="expense-total-table">
<tr>
<td class="expense-total-cell">
<p class="expense-total">{!! format_money_pdf($totalExpense) !!}</p>
</td>
</tr>
</table>
<table class="total-expense-table">
<tr>
<td>
<p class="total-expense-title">TOTAL EXPENSE</p>
</td>
<td>
<p class="total-expense-money">{!! format_money_pdf($totalExpense) !!}</p>
</td>
</tr>
</table>
</div>
<table class="expense-total-table">
<tr>
<td class="expense-total-cell">
<p class="expense-total">{!! format_money_pdf($totalExpense) !!}</p>
</td>
</tr>
</table>
<table class="report-footer">
<tr>
<td>
<p class="report-footer-label">TOTAL EXPENSE</p>
</td>
<td>
<p class="report-footer-value">{!! format_money_pdf($totalExpense) !!}</p>
</td>
</tr>
</table>
</body>
</html>

View File

@ -2,35 +2,24 @@
<html lang="en">
<head>
<title>Profit & Loss Report</title>
{{-- <link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet"> --}}
<style type="text/css">
body {
font-family: "DejaVu Sans";
}
html {
margin: 0px;
padding: 0px;
}
table {
border-collapse: collapse;
}
.main-container {
padding: 30px 60px;
}
.sub-container{
padding: 0px 20px;
}
.header {
.report-header {
width: 100%;
}
.heading-text {
font-style: normal;
font-weight: 600;
font-size: 24px;
color: #5851D8;
@ -41,7 +30,6 @@
}
.heading-date-range {
font-style: normal;
font-weight: 600;
font-size: 15px;
color: #A5ACC1;
@ -52,10 +40,8 @@
}
.sub-heading-text {
font-style: normal;
font-weight: 600;
font-size: 16px;
/* line-height: 21px; */
color: #595959;
padding: 0px;
margin: 0px;
@ -70,18 +56,15 @@
.income-title {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
color: #040405;
text-align: left;
}
.income-money {
.income-amount {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 21px;
@ -93,8 +76,6 @@
.expenses-title {
margin-top: 20px;
padding-left: 3px;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
color: #040405;
@ -112,25 +93,21 @@
.expense-title {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
color: #595959;
}
.expense-money {
.expense-amount {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
text-align: right;
color: #595959;
}
.expense-total-table {
.expense-total-indicator-table {
border-top: 1px solid #EAF1FB;
width: 100%;
}
@ -146,7 +123,6 @@
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 21px;
@ -154,7 +130,7 @@
color: #040405;
}
.profit-table {
.report-footer {
width: 100%;
margin-top: 40px;
padding: 15px 20px;
@ -162,22 +138,20 @@
box-sizing: border-box;
}
.profit-title {
.report-footer-label {
padding: 0px;
margin: 0px;
text-align: left;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 21px;
color: #595959;
}
.profit-money {
.report-footer-value {
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 20px;
line-height: 21px;
@ -186,73 +160,71 @@
</style>
</head>
<body>
<div class="main-container">
<div class="sub-container">
<table class="header">
<tr>
<td>
<p class="heading-text">{{ $company->name }}</p>
</td>
<td>
<p class="heading-date-range">{{ $from_date }} - {{ $to_date }}</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text">PROFIT & LOSS REPORT</p>
</td>
</tr>
</table>
<div class="sub-container">
<table class="report-header">
<tr>
<td>
<p class="heading-text">{{ $company->name }}</p>
</td>
<td>
<p class="heading-date-range">{{ $from_date }} - {{ $to_date }}</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text">PROFIT & LOSS REPORT</p>
</td>
</tr>
</table>
<table class="income-table">
<tr>
<td>
<p class="income-title">Income</p>
</td>
<td>
<p class="income-money">{!! format_money_pdf($income) !!}</p>
</td>
</tr>
</table>
<p class="expenses-title">Expenses</p>
<div class="expenses-table-container">
<table class="expenses-table">
@foreach ($expenseCategories as $expenseCategory)
<tr>
<td>
<p class="expense-title">
{{ $expenseCategory->category->name }}
</p>
</td>
<td>
<p class="expense-money">
{!! format_money_pdf($expenseCategory->total_amount) !!}
</p>
</td>
</tr>
@endforeach
<table class="income-table">
<tr>
<td>
<p class="income-title">Income</p>
</td>
<td>
<p class="income-amount">{!! format_money_pdf($income) !!}</p>
</td>
</tr>
</table>
<p class="expenses-title">Expenses</p>
<div class="expenses-table-container">
<table class="expenses-table">
@foreach ($expenseCategories as $expenseCategory)
<tr>
<td>
<p class="expense-title">
{{ $expenseCategory->category->name }}
</p>
</td>
<td>
<p class="expense-amount">
{!! format_money_pdf($expenseCategory->total_amount) !!}
</p>
</td>
</tr>
@endforeach
</table>
</div>
</table>
</div>
<table class="expense-total-table">
<tr>
<td class="expense-total-cell">
<p class="expense-total">{!! format_money_pdf($totalExpense) !!}</p>
</td>
</tr>
</table>
<table class="profit-table">
<tr>
<td>
<p class="profit-title">NET PROFIT</p>
</td>
<td>
<p class="profit-money">{!! format_money_pdf(($income-$totalExpense)) !!}</p>
</td>
</tr>
</table>
</div>
<table class="expense-total-indicator-table">
<tr>
<td class="expense-total-cell">
<p class="expense-total">{!! format_money_pdf($totalExpense) !!}</p>
</td>
</tr>
</table>
<table class="report-footer">
<tr>
<td>
<p class="report-footer-label">NET PROFIT</p>
</td>
<td>
<p class="report-footer-value">{!! format_money_pdf(($income-$totalExpense)) !!}</p>
</td>
</tr>
</table>
</body>
</html>

View File

@ -2,35 +2,24 @@
<html lang="en">
<head>
<title>Sales Customer Report</title>
{{-- <link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet"> --}}
<style type="text/css">
body {
font-family: "DejaVu Sans";
}
/* html {
margin: 0px;
padding: 0px;
} */
table {
border-collapse: collapse;
}
.main-container {
/* padding: 30px 80px; */
}
.sub-container{
padding: 0px 20px;
}
.header {
.report-header {
width: 100%;
}
.heading-text {
font-style: normal;
font-weight: 600;
font-size: 24px;
color: #5851D8;
@ -41,7 +30,6 @@
}
.heading-date-range {
font-style: normal;
font-weight: 600;
font-size: 15px;
color: #A5ACC1;
@ -52,7 +40,6 @@
}
.sub-heading-text {
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 21px;
@ -62,90 +49,55 @@
margin-top: 30px;
}
.income-table {
margin-top: 53px;
width: 100%;
}
.income-title {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
color: #040405;
text-align: left;
}
.income-money {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 21px;
text-align: right;
color: #040405;
text-align: right;
}
.expenses-title {
.sales-customer-name {
margin-top: 20px;
padding-left: 3px;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
color: #040405;
}
.expenses-table-container {
.sales-table-container {
padding-left: 10px;
}
.expenses-table {
.sales-table {
width: 100%;
padding-bottom: 10px;
}
.expense-title {
.sales-information-text {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
color: #595959;
}
.expense-money {
.sales-amount {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
text-align: right;
color: #595959;
}
.expense-total-table {
.sales-total-indicator-table {
border-top: 1px solid #EAF1FB;
width: 100%;
}
.expense-total-cell {
.sales-total-cell {
padding-top: 10px;
}
.expense-total {
.sales-total-amount {
padding-top: 10px;
padding-right: 30px;
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 21px;
@ -153,7 +105,7 @@
color: #040405;
}
.profit-table {
.report-footer {
width: 100%;
margin-top: 40px;
padding: 15px 20px;
@ -161,22 +113,20 @@
box-sizing: border-box;
}
.profit-title {
.report-footer-label {
padding: 0px;
margin: 0px;
text-align: left;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 21px;
color: #595959;
}
.profit-money {
.report-footer-value {
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 20px;
line-height: 21px;
@ -188,79 +138,67 @@
</style>
</head>
<body>
<div class="main-container">
<div class="sub-container">
<table class="header">
<tr>
<td>
<p class="heading-text">{{ $company->name }}</p>
</td>
<td>
<p class="heading-date-range">{{ $from_date }} - {{ $to_date }}</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text text-center">Sales Report: By Customer</p>
</td>
</tr>
</table>
{{-- <table class="income-table">
<tr>
<td>
<p class="income-title">Income</p>
</td>
<td>
<p class="income-money">{{ $income }}</p>
</td>
</tr>
</table> --}}
@foreach ($customers as $customer)
<p class="expenses-title">{{ $customer->name }}</p>
<div class="expenses-table-container">
<table class="expenses-table">
@foreach ($customer->invoices as $invoice)
<tr>
<td>
<p class="expense-title">
{{ $invoice->formattedInvoiceDate }} ({{ $invoice->invoice_number }})
</p>
</td>
<td>
<p class="expense-money">
{!! format_money_pdf($invoice->total) !!}
</p>
</td>
</tr>
@endforeach
</table>
</div>
<table class="expense-total-table">
<tr>
<td class="expense-total-cell">
<p class="expense-total">
{!! format_money_pdf($customer->totalAmount) !!}
</p>
</td>
</tr>
</table>
@endforeach
</div>
<table class="profit-table">
<div class="sub-container">
<table class="report-header">
<tr>
<td>
<p class="profit-title">TOTAL SALES</p>
<p class="heading-text">{{ $company->name }}</p>
</td>
<td>
<p class="profit-money">
{!! format_money_pdf($totalAmount) !!}
</p>
<p class="heading-date-range">{{ $from_date }} - {{ $to_date }}</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text text-center">Sales Report: By Customer</p>
</td>
</tr>
</table>
@foreach ($customers as $customer)
<p class="sales-customer-name">{{ $customer->name }}</p>
<div class="sales-table-container">
<table class="sales-table">
@foreach ($customer->invoices as $invoice)
<tr>
<td>
<p class="sales-information-text">
{{ $invoice->formattedInvoiceDate }} ({{ $invoice->invoice_number }})
</p>
</td>
<td>
<p class="sales-amount">
{!! format_money_pdf($invoice->total) !!}
</p>
</td>
</tr>
@endforeach
</table>
</div>
<table class="sales-total-indicator-table">
<tr>
<td class="sales-total-cell">
<p class="sales-total-amount">
{!! format_money_pdf($customer->totalAmount) !!}
</p>
</td>
</tr>
</table>
@endforeach
</div>
<table class="report-footer">
<tr>
<td>
<p class="report-footer-label">TOTAL SALES</p>
</td>
<td>
<p class="report-footer-value">
{!! format_money_pdf($totalAmount) !!}
</p>
</td>
</tr>
</table>
</body>
</html>

View File

@ -2,35 +2,24 @@
<html lang="en">
<head>
<title>Sales Item Report</title>
{{-- <link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet"> --}}
<style type="text/css">
body {
font-family: "DejaVu Sans";
}
/* html {
margin: 0px;
padding: 0px;
} */
table {
border-collapse: collapse;
}
.main-container {
/* padding: 30px 80px; */
}
.sub-container{
padding: 0px 20px;
}
.header {
.report-header {
width: 100%;
}
.heading-text {
font-style: normal;
font-weight: 600;
font-size: 24px;
color: #5851D8;
@ -41,7 +30,6 @@
}
.heading-date-range {
font-style: normal;
font-weight: 600;
font-size: 15px;
color: #A5ACC1;
@ -52,7 +40,6 @@
}
.sub-heading-text {
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 21px;
@ -62,90 +49,55 @@
margin-top: 30px;
}
.income-table {
margin-top: 53px;
width: 100%;
}
.income-title {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
color: #040405;
text-align: left;
}
.income-money {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 21px;
text-align: right;
color: #040405;
text-align: right;
}
.expenses-title {
.sales-items-title {
margin-top: 20px;
padding-left: 3px;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
color: #040405;
}
.expenses-table-container {
.items-table-container {
padding-left: 10px;
}
.expenses-table {
.items-table {
width: 100%;
padding-bottom: 10px;
}
.expense-title {
.item-title {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
color: #595959;
}
.expense-money {
.item-sales-amount {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
text-align: right;
color: #595959;
}
.expense-total-table {
.sales-total-indicator-table {
border-top: 1px solid #EAF1FB;
width: 100%;
}
.expense-total-cell {
.sales-total-cell {
padding-top: 10px;
}
.expense-total {
.sales-total-amount {
padding-top: 10px;
padding-right: 30px;
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 21px;
@ -153,7 +105,7 @@
color: #040405;
}
.profit-table {
.report-footer {
width: 100%;
margin-top: 40px;
padding: 15px 20px;
@ -161,22 +113,20 @@
box-sizing: border-box;
}
.profit-title {
.report-footer-label {
padding: 0px;
margin: 0px;
text-align: left;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 21px;
color: #595959;
}
.profit-money {
.report-footer-value {
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 20px;
line-height: 21px;
@ -188,78 +138,66 @@
</style>
</head>
<body>
<div class="main-container">
<div class="sub-container">
<table class="header">
<tr>
<td>
<p class="heading-text">{{ $company->name }}</p>
</td>
<td>
<p class="heading-date-range">{{ $from_date }} - {{ $to_date }}</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text text-center">Sales Report: By Item</p>
</td>
</tr>
</table>
{{-- <table class="income-table">
<tr>
<td>
<p class="income-title">Income</p>
</td>
<td>
<p class="income-money">{{ $income }}</p>
</td>
</tr>
</table> --}}
<p class="expenses-title">Items</p>
@foreach ($items as $item)
<div class="expenses-table-container">
<table class="expenses-table">
<tr>
<td>
<p class="expense-title">
{{ $item->name }}
</p>
</td>
<td>
<p class="expense-money">
{!! format_money_pdf($item->total_amount) !!}
</p>
</td>
</tr>
</table>
</div>
@endforeach
<table class="expense-total-table">
<div class="sub-container">
<table class="report-header">
<tr>
<td>
<p class="heading-text">{{ $company->name }}</p>
</td>
<td>
<p class="heading-date-range">{{ $from_date }} - {{ $to_date }}</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text text-center">Sales Report: By Item</p>
</td>
</tr>
</table>
<p class="sales-items-title">Items</p>
@foreach ($items as $item)
<div class="items-table-container">
<table class="items-table">
<tr>
<td class="expense-total-cell">
<p class="expense-total">
{!! format_money_pdf($totalAmount) !!}
<td>
<p class="item-title">
{{ $item->name }}
</p>
</td>
<td>
<p class="item-sales-amount">
{!! format_money_pdf($item->total_amount) !!}
</p>
</td>
</tr>
</table>
</div>
</div>
@endforeach
<table class="profit-table">
<tr>
<td>
<p class="profit-title">TOTAL SALES</p>
</td>
<td>
<p class="profit-money">
{!! format_money_pdf($totalAmount) !!}
</p>
</td>
</tr>
</table>
<table class="sales-total-indicator-table">
<tr>
<td class="sales-total-cell">
<p class="sales-total-amount">
{!! format_money_pdf($totalAmount) !!}
</p>
</td>
</tr>
</table>
</div>
<table class="report-footer">
<tr>
<td>
<p class="report-footer-label">TOTAL SALES</p>
</td>
<td>
<p class="report-footer-value">
{!! format_money_pdf($totalAmount) !!}
</p>
</td>
</tr>
</table>
</body>
</html>

View File

@ -2,36 +2,25 @@
<html lang="en">
<head>
<title>Tax Summary Report</title>
{{-- <link href="https://fonts.googleapis.com/css?family=Poppins&display=swap" rel="stylesheet"> --}}
<style type="text/css">
body {
font-family: "DejaVu Sans";
}
/* html {
margin: 0px;
padding: 0px;
} */
table {
border-collapse: collapse;
}
.main-container {
/* padding: 30px 60px; */
}
.sub-container{
padding: 0px 20px;
}
.header {
.report-header {
width: 100%;
margin-bottom: 60px
}
.heading-text {
font-style: normal;
font-weight: 600;
font-size: 24px;
color: #5851D8;
@ -42,7 +31,6 @@
}
.heading-date-range {
font-style: normal;
font-weight: 600;
font-size: 15px;
color: #A5ACC1;
@ -53,31 +41,17 @@
}
.sub-heading-text {
font-style: normal;
font-weight: 600;
font-size: 16px;
/* line-height: 21px; */
color: #595959;
padding: 0px;
margin: 0px;
margin-top: 6px;
}
.types-title {
.tax-types-title {
margin-top: 20px;
padding-left: 3px;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
color: #040405;
}
.tax-title {
margin-top: 60px;
padding-left: 3px;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
color: #040405;
@ -95,18 +69,14 @@
.tax-title {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
color: #595959;
}
.tax-money {
.tax-amount {
padding: 0px;
margin: 0px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 21px;
text-align: right;
@ -129,7 +99,6 @@
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 21px;
@ -137,7 +106,7 @@
color: #040405;
}
.total-tax-table {
.report-footer {
width: 100%;
margin-top: 40px;
padding: 15px 20px;
@ -145,22 +114,20 @@
box-sizing: border-box;
}
.total-tax-title {
.report-footer-label {
padding: 0px;
margin: 0px;
text-align: left;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 21px;
color: #595959;
}
.total-tax-money {
.report-footer-value {
padding: 0px;
margin: 0px;
text-align: right;
font-style: normal;
font-weight: 500;
font-size: 20px;
line-height: 21px;
@ -169,70 +136,68 @@
</style>
</head>
<body>
<div class="main-container">
<div class="sub-container">
<table class="header">
<tr>
<td>
<p class="heading-text">
{{ $company->name }}
</p>
</td>
<td>
<p class="heading-date-range">
{{ $from_date }} - {{ $to_date }}
</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text">TAX REPORT</p>
</td>
</tr>
<div class="sub-container">
<table class="report-header">
<tr>
<td>
<p class="heading-text">
{{ $company->name }}
</p>
</td>
<td>
<p class="heading-date-range">
{{ $from_date }} - {{ $to_date }}
</p>
</td>
</tr>
<tr>
<td colspan="2">
<p class="sub-heading-text">TAX REPORT</p>
</td>
</tr>
</table>
<p class="tax-types-title">Tax Types</p>
<div class="tax-table-container">
<table class="tax-table">
@foreach ($taxTypes as $tax)
<tr>
<td>
<p class="tax-title">
{{ $tax->taxType->name }}
</p>
</td>
<td>
<p class="tax-amount">
{!! format_money_pdf($tax->total_tax_amount) !!}
</p>
</td>
</tr>
@endforeach
</table>
<p class="types-title">Tax Types</p>
<div class="tax-table-container">
<table class="tax-table">
@foreach ($taxTypes as $tax)
<tr>
<td>
<p class="tax-title">
{{ $tax->taxType->name }}
</p>
</td>
<td>
<p class="tax-money">
{!! format_money_pdf($tax->total_tax_amount) !!}
</p>
</td>
</tr>
@endforeach
</table>
</div>
</div>
<table class="tax-total-table">
<tr>
<td class="tax-total-cell">
<p class="tax-total">
{!! format_money_pdf($totalTaxAmount) !!}
</p>
</td>
</tr>
</table>
<table class="total-tax-table">
<tr>
<td>
<p class="total-tax-title">TOTAL TAX</p>
</td>
<td>
<p class="total-tax-money">
{!! format_money_pdf($totalTaxAmount) !!}
</p>
</td>
</tr>
</table>
</div>
<table class="tax-total-table">
<tr>
<td class="tax-total-cell">
<p class="tax-total">
{!! format_money_pdf($totalTaxAmount) !!}
</p>
</td>
</tr>
</table>
<table class="report-footer">
<tr>
<td>
<p class="report-footer-label">TOTAL TAX</p>
</td>
<td>
<p class="report-footer-value">
{!! format_money_pdf($totalTaxAmount) !!}
</p>
</td>
</tr>
</table>
</body>
</html>

View File

@ -1,6 +1,6 @@
@component('mail::message')
# Introduction
Customer viewed this Estimate.
{{ $data['user']['name'] }} viewed this Estimate.
@component('mail::button', ['url' => url('/admin/estimates/'.$data['estimate']['id'].'/view')])
Estimate

View File

@ -1,6 +1,6 @@
@component('mail::message')
# Introduction
Customer viewed this Invoice.
{{ $data['user']['name'] }} viewed this Invoice.
@component('mail::button', ['url' => url('/admin/invoices/'.$data['invoice']['id'].'/view')])
Invoice

View File

@ -122,23 +122,41 @@ Route::group(['middleware' => 'api'], function () {
'middleware' => 'admin'
], function () {
// Auto update routes
// Self Update
//----------------------------------
Route::post('/update', [
'as' => 'auto.update',
'uses' => 'UpdateController@update'
Route::get('/check/update', [
'as' => 'update.check',
'uses' => 'UpdateController@checkLatestVersion'
]);
Route::post('/update/download', [
'as' => 'update.download',
'uses' => 'UpdateController@download'
]);
Route::post('/update/unzip', [
'as' => 'update.unzip',
'uses' => 'UpdateController@unzip'
]);
Route::post('/update/copy', [
'as' => 'update.copy',
'uses' => 'UpdateController@copyFiles'
]);
Route::post('/update/migrate', [
'as' => 'update.migrate',
'uses' => 'UpdateController@migrate'
]);
Route::post('/update/finish', [
'as' => 'auto.update.finish',
'as' => 'update.finish',
'uses' => 'UpdateController@finishUpdate'
]);
Route::get('/check/update', [
'as' => 'check.update',
'uses' => 'UpdateController@checkLatestVersion'
]);
// Bootstrap
//----------------------------------
Route::get('/bootstrap', [
'as' => 'bootstrap',

View File

@ -6,6 +6,7 @@
|--------------------------------------------------------------------------
|
*/
Route::group(['prefix' => 'reports'], function () {
// sales report by customer
@ -46,7 +47,6 @@ Route::group(['prefix' => 'reports'], function () {
'as' => 'get.profit.loss',
'uses' => 'ReportController@profitLossReport'
]);
});
@ -88,7 +88,7 @@ Route::get('/expenses/{id}/receipt/{hash}', [
'uses' => 'ExpensesController@downloadReceipt'
]);
// Setup for instalation of app
// Setup for installation of app
// ----------------------------------------------
Route::get('/on-boarding', function () {
return view('app');