mirror of
https://github.com/crater-invoice/crater.git
synced 2025-12-15 01:42:54 -05:00
Merge pull request #2 from bytefury/master
Merge pull request #2 from bytefury/master
This commit is contained in:
51
app/Console/Commands/ResetApp.php
Normal file
51
app/Console/Commands/ResetApp.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
|
||||
class ResetApp extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'reset:app';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Clean database, database_created and public/storage folder';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->confirm('Do you wish to continue? This will delete your tables')) {
|
||||
Artisan::call('migrate:reset --force');
|
||||
|
||||
\Storage::disk('local')->delete('database_created');
|
||||
|
||||
// $file = new Filesystem;
|
||||
// $file->cleanDirectory('public/storage');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ class Kernel extends ConsoleKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
|
||||
Commands\ResetApp::class
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -148,6 +148,7 @@ class CompanyController extends Controller
|
||||
["code"=>"fr", "name" => "French"],
|
||||
["code"=>"es", "name" => "Spanish"],
|
||||
["code"=>"ar", "name" => "العربية"],
|
||||
["code"=>"de", "name" => "German"],
|
||||
["code"=>"pt_BR", "name" => "Brazilian Portuguese"],
|
||||
];
|
||||
|
||||
|
||||
@@ -406,6 +406,10 @@ class EstimatesController extends Controller
|
||||
{
|
||||
$estimate = Estimate::with(['items', 'items.taxes', 'user', 'estimateTemplate', 'taxes'])->find($id);
|
||||
$invoice_date = Carbon::parse($estimate->estimate_date);
|
||||
$invoice_prefix = CompanySetting::getSetting(
|
||||
'invoice_prefix',
|
||||
$request->header('company')
|
||||
);
|
||||
$due_date = Carbon::parse($estimate->estimate_date)->addDays(7);
|
||||
$tax_per_item = CompanySetting::getSetting(
|
||||
'tax_per_item',
|
||||
@@ -425,7 +429,7 @@ class EstimatesController extends Controller
|
||||
$invoice = Invoice::create([
|
||||
'invoice_date' => $invoice_date,
|
||||
'due_date' => $due_date,
|
||||
'invoice_number' => "INV-".Invoice::getNextInvoiceNumber(),
|
||||
'invoice_number' => $invoice_prefix."-".Invoice::getNextInvoiceNumber($invoice_prefix),
|
||||
'reference_number' => $estimate->reference_number,
|
||||
'user_id' => $estimate->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
|
||||
@@ -6,6 +6,7 @@ use Crater\Invoice;
|
||||
use PDF;
|
||||
use Crater\CompanySetting;
|
||||
use Crater\Estimate;
|
||||
use Crater\Payment;
|
||||
use Crater\User;
|
||||
use Crater\Company;
|
||||
use Crater\InvoiceTemplate;
|
||||
@@ -376,4 +377,34 @@ class FrontendController extends Controller
|
||||
|
||||
return $pdf->stream();
|
||||
}
|
||||
|
||||
public function getPaymentPdf($id)
|
||||
{
|
||||
$payment = Payment::with([
|
||||
'user',
|
||||
'invoice',
|
||||
'paymentMethod'
|
||||
])
|
||||
->where('unique_hash', $id)
|
||||
->first();
|
||||
|
||||
$company = Company::find($payment->company_id);
|
||||
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
|
||||
|
||||
$logo = $company->getMedia('logo')->first();
|
||||
|
||||
if($logo) {
|
||||
$logo = $logo->getFullUrl();
|
||||
}
|
||||
|
||||
view()->share([
|
||||
'payment' => $payment,
|
||||
'company_address' => $companyAddress,
|
||||
'logo' => $logo ?? null
|
||||
]);
|
||||
|
||||
$pdf = PDF::loadView('app.pdf.payment.payment');
|
||||
|
||||
return $pdf->stream();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,4 +497,94 @@ class InvoicesController extends Controller
|
||||
'invoices' => $invoices
|
||||
]);
|
||||
}
|
||||
|
||||
public function cloneInvoice(Request $request)
|
||||
{
|
||||
$oldInvoice = Invoice::with([
|
||||
'items.taxes',
|
||||
'user',
|
||||
'invoiceTemplate',
|
||||
'taxes.taxType'
|
||||
])
|
||||
->find($request->id);
|
||||
|
||||
$date = Carbon::now();
|
||||
$invoice_prefix = CompanySetting::getSetting(
|
||||
'invoice_prefix',
|
||||
$request->header('company')
|
||||
);
|
||||
$tax_per_item = CompanySetting::getSetting(
|
||||
'tax_per_item',
|
||||
$request->header('company')
|
||||
) ? CompanySetting::getSetting(
|
||||
'tax_per_item',
|
||||
$request->header('company')
|
||||
) : 'NO';
|
||||
$discount_per_item = CompanySetting::getSetting(
|
||||
'discount_per_item',
|
||||
$request->header('company')
|
||||
) ? CompanySetting::getSetting(
|
||||
'discount_per_item',
|
||||
$request->header('company')
|
||||
) : 'NO';
|
||||
|
||||
$invoice = Invoice::create([
|
||||
'invoice_date' => $date,
|
||||
'due_date' => $date,
|
||||
'invoice_number' => $invoice_prefix."-".Invoice::getNextInvoiceNumber($invoice_prefix),
|
||||
'reference_number' => $oldInvoice->reference_number,
|
||||
'user_id' => $oldInvoice->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
'invoice_template_id' => 1,
|
||||
'status' => Invoice::STATUS_DRAFT,
|
||||
'paid_status' => Invoice::STATUS_UNPAID,
|
||||
'sub_total' => $oldInvoice->sub_total,
|
||||
'discount' => $oldInvoice->discount,
|
||||
'discount_type' => $oldInvoice->discount_type,
|
||||
'discount_val' => $oldInvoice->discount_val,
|
||||
'total' => $oldInvoice->total,
|
||||
'due_amount' => $oldInvoice->total,
|
||||
'tax_per_item' => $oldInvoice->tax_per_item,
|
||||
'discount_per_item' => $oldInvoice->discount_per_item,
|
||||
'tax' => $oldInvoice->tax,
|
||||
'notes' => $oldInvoice->notes,
|
||||
'unique_hash' => str_random(60)
|
||||
]);
|
||||
|
||||
$invoiceItems = $oldInvoice->items->toArray();
|
||||
|
||||
foreach ($invoiceItems as $invoiceItem) {
|
||||
$invoiceItem['company_id'] = $request->header('company');
|
||||
$invoiceItem['name'] = $invoiceItem['name'];
|
||||
$item = $invoice->items()->create($invoiceItem);
|
||||
|
||||
if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) {
|
||||
foreach ($invoiceItem['taxes'] as $tax) {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
|
||||
if ($tax['amount']) {
|
||||
$item->taxes()->create($tax);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($oldInvoice->taxes) {
|
||||
foreach ($oldInvoice->taxes->toArray() as $tax) {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
$invoice->taxes()->create($tax);
|
||||
}
|
||||
}
|
||||
|
||||
$invoice = Invoice::with([
|
||||
'items',
|
||||
'user',
|
||||
'invoiceTemplate',
|
||||
'taxes'
|
||||
])->find($invoice->id);
|
||||
|
||||
return response()->json([
|
||||
'invoice' => $invoice
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,17 @@ class ItemsController extends Controller
|
||||
{
|
||||
$limit = $request->has('limit') ? $request->limit : 10;
|
||||
|
||||
$items = Item::applyFilters($request->only([
|
||||
$items = Item::with(['taxes'])
|
||||
->leftJoin('units', 'units.id', '=', 'items.unit_id')
|
||||
->applyFilters($request->only([
|
||||
'search',
|
||||
'price',
|
||||
'unit',
|
||||
'unit_id',
|
||||
'orderByField',
|
||||
'orderBy'
|
||||
]))
|
||||
->whereCompany($request->header('company'))
|
||||
->select('items.*', 'units.name as unit_name')
|
||||
->latest()
|
||||
->paginate($limit);
|
||||
|
||||
@@ -33,7 +36,7 @@ class ItemsController extends Controller
|
||||
|
||||
public function edit(Request $request, $id)
|
||||
{
|
||||
$item = Item::with('taxes')->find($id);
|
||||
$item = Item::with(['taxes', 'unit'])->find($id);
|
||||
|
||||
return response()->json([
|
||||
'item' => $item,
|
||||
@@ -54,7 +57,7 @@ class ItemsController extends Controller
|
||||
{
|
||||
$item = new Item();
|
||||
$item->name = $request->name;
|
||||
$item->unit = $request->unit;
|
||||
$item->unit_id = $request->unit_id;
|
||||
$item->description = $request->description;
|
||||
$item->company_id = $request->header('company');
|
||||
$item->price = $request->price;
|
||||
@@ -85,7 +88,7 @@ class ItemsController extends Controller
|
||||
{
|
||||
$item = Item::find($id);
|
||||
$item->name = $request->name;
|
||||
$item->unit = $request->unit;
|
||||
$item->unit_id = $request->unit_id;
|
||||
$item->description = $request->description;
|
||||
$item->price = $request->price;
|
||||
$item->save();
|
||||
@@ -145,7 +148,7 @@ class ItemsController extends Controller
|
||||
$items = [];
|
||||
foreach ($request->id as $id) {
|
||||
$item = Item::deleteItem($id);
|
||||
if (!$item) {
|
||||
if ($item) {
|
||||
array_push($items, $id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,9 +44,13 @@ class OnboardingController extends Controller
|
||||
$date_formats = DateFormatter::get_list();
|
||||
$time_zones = TimeZones::get_list();
|
||||
$languages = [
|
||||
["code"=>"ar", "name" => "Arabic"],
|
||||
["code"=>"en", "name" => "English"],
|
||||
["code"=>"fr", "name" => "French"],
|
||||
["code"=>"es", "name" => "Spanish"]
|
||||
["code"=>"es", "name" => "Spanish"],
|
||||
["code"=>"ar", "name" => "العربية"],
|
||||
["code"=>"de", "name" => "German"],
|
||||
["code"=>"pt-br", "name" => "Portuguese (Brazilian)"]
|
||||
];
|
||||
$fiscal_years = [
|
||||
['key' => 'january-december' , 'value' => '1-12'],
|
||||
@@ -304,6 +308,10 @@ class OnboardingController extends Controller
|
||||
|
||||
Artisan::call('passport:install --force');
|
||||
|
||||
Artisan::call('db:seed', ['--class' => 'PaymentMethodSeeder', '--force' => true]);
|
||||
|
||||
Artisan::call('db:seed', ['--class' => 'UnitSeeder', '--force' => true]);
|
||||
|
||||
$client = DB::table('oauth_clients')->find(2);
|
||||
|
||||
$path = base_path('.env');
|
||||
|
||||
@@ -4,13 +4,16 @@ namespace Crater\Http\Controllers;
|
||||
use Illuminate\Http\Request;
|
||||
use Crater\CompanySetting;
|
||||
use Crater\Currency;
|
||||
use Crater\Company;
|
||||
use Crater\Invoice;
|
||||
use Crater\Payment;
|
||||
use Crater\PaymentMethod;
|
||||
use Carbon\Carbon;
|
||||
use function MongoDB\BSON\toJSON;
|
||||
use Crater\User;
|
||||
use Crater\Http\Requests\PaymentRequest;
|
||||
use Validator;
|
||||
use Crater\Mail\PaymentPdf;
|
||||
|
||||
class PaymentController extends Controller
|
||||
{
|
||||
@@ -23,19 +26,20 @@ class PaymentController extends Controller
|
||||
{
|
||||
$limit = $request->has('limit') ? $request->limit : 10;
|
||||
|
||||
$payments = Payment::with('user', 'invoice')
|
||||
$payments = Payment::with(['user', 'invoice', 'paymentMethod'])
|
||||
->join('users', 'users.id', '=', 'payments.user_id')
|
||||
->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id')
|
||||
->leftJoin('payment_methods', 'payment_methods.id', '=', 'payments.payment_method_id')
|
||||
->applyFilters($request->only([
|
||||
'search',
|
||||
'payment_number',
|
||||
'payment_mode',
|
||||
'payment_method_id',
|
||||
'customer_id',
|
||||
'orderByField',
|
||||
'orderBy'
|
||||
]))
|
||||
->whereCompany($request->header('company'))
|
||||
->select('payments.*', 'users.name', 'invoices.invoice_number')
|
||||
->select('payments.*', 'users.name', 'invoices.invoice_number', 'payment_methods.name as payment_mode')
|
||||
->latest()
|
||||
->paginate($limit);
|
||||
|
||||
@@ -66,6 +70,9 @@ class PaymentController extends Controller
|
||||
'customers' => User::where('role', 'customer')
|
||||
->whereCompany($request->header('company'))
|
||||
->get(),
|
||||
'paymentMethods' => PaymentMethod::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get(),
|
||||
'nextPaymentNumberAttribute' => $nextPaymentNumberAttribute,
|
||||
'nextPaymentNumber' => $payment_prefix.'-'.$nextPaymentNumber,
|
||||
'payment_prefix' => $payment_prefix
|
||||
@@ -113,13 +120,15 @@ class PaymentController extends Controller
|
||||
'user_id' => $request->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
'invoice_id' => $request->invoice_id,
|
||||
'payment_mode' => $request->payment_mode,
|
||||
'payment_method_id' => $request->payment_method_id,
|
||||
'amount' => $request->amount,
|
||||
'notes' => $request->notes,
|
||||
'unique_hash' => str_random(60)
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'payment' => $payment,
|
||||
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash),
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
@@ -132,7 +141,12 @@ class PaymentController extends Controller
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
//
|
||||
$payment = Payment::with(['user', 'invoice', 'paymentMethod'])->find($id);
|
||||
|
||||
return response()->json([
|
||||
'payment' => $payment,
|
||||
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,7 +157,7 @@ class PaymentController extends Controller
|
||||
*/
|
||||
public function edit(Request $request, $id)
|
||||
{
|
||||
$payment = Payment::with('user', 'invoice')->find($id);
|
||||
$payment = Payment::with(['user', 'invoice', 'paymentMethod'])->find($id);
|
||||
|
||||
$invoices = Invoice::where('paid_status', '<>', Invoice::STATUS_PAID)
|
||||
->where('user_id', $payment->user_id)->where('due_amount', '>', 0)
|
||||
@@ -154,8 +168,12 @@ class PaymentController extends Controller
|
||||
'customers' => User::where('role', 'customer')
|
||||
->whereCompany($request->header('company'))
|
||||
->get(),
|
||||
'paymentMethods' => PaymentMethod::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get(),
|
||||
'nextPaymentNumber' => $payment->getPaymentNumAttribute(),
|
||||
'payment_prefix' => $payment->getPaymentPrefixAttribute(),
|
||||
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash),
|
||||
'payment' => $payment,
|
||||
'invoices' => $invoices
|
||||
]);
|
||||
@@ -208,13 +226,14 @@ class PaymentController extends Controller
|
||||
$payment->payment_number = $number_attributes['payment_number'];
|
||||
$payment->user_id = $request->user_id;
|
||||
$payment->invoice_id = $request->invoice_id;
|
||||
$payment->payment_mode = $request->payment_mode;
|
||||
$payment->payment_method_id = $request->payment_method_id;
|
||||
$payment->amount = $request->amount;
|
||||
$payment->notes = $request->notes;
|
||||
$payment->save();
|
||||
|
||||
return response()->json([
|
||||
'payment' => $payment,
|
||||
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash),
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
@@ -276,4 +295,37 @@ class PaymentController extends Controller
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
|
||||
public function sendPayment(Request $request)
|
||||
{
|
||||
$payment = Payment::findOrFail($request->id);
|
||||
|
||||
$data['payment'] = $payment->toArray();
|
||||
$userId = $data['payment']['user_id'];
|
||||
$data['user'] = User::find($userId)->toArray();
|
||||
$data['company'] = Company::find($payment->company_id);
|
||||
$email = $data['user']['email'];
|
||||
$notificationEmail = CompanySetting::getSetting(
|
||||
'notification_email',
|
||||
$request->header('company')
|
||||
);
|
||||
|
||||
if (!$email) {
|
||||
return response()->json([
|
||||
'error' => 'user_email_does_not_exist'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$notificationEmail) {
|
||||
return response()->json([
|
||||
'error' => 'notification_email_does_not_exist'
|
||||
]);
|
||||
}
|
||||
|
||||
\Mail::to($email)->send(new PaymentPdf($data, $notificationEmail));
|
||||
|
||||
return response()->json([
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
119
app/Http/Controllers/PaymentMethodController.php
Normal file
119
app/Http/Controllers/PaymentMethodController.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Http\Controllers;
|
||||
|
||||
use Crater\PaymentMethod;
|
||||
use Illuminate\Http\Request;
|
||||
use Crater\Http\Requests\PaymentMethodRequest;
|
||||
|
||||
class PaymentMethodController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$paymentMethods = PaymentMethod::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'paymentMethods' => $paymentMethods
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(PaymentMethodRequest $request)
|
||||
{
|
||||
$paymentMethod = new PaymentMethod;
|
||||
$paymentMethod->name = $request->name;
|
||||
$paymentMethod->company_id = $request->header('company');
|
||||
$paymentMethod->save();
|
||||
|
||||
return response()->json([
|
||||
'paymentMethod' => $paymentMethod
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Crater\PaymentMethod $paymentMethod
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(PaymentMethod $paymentMethod)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \Crater\PaymentMethod $paymentMethod
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(PaymentMethod $paymentMethod)
|
||||
{
|
||||
return response()->json([
|
||||
'paymentMethod' => $paymentMethod
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Crater\PaymentMethod $paymentMethod
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(PaymentMethodRequest $request, PaymentMethod $paymentMethod)
|
||||
{
|
||||
$paymentMethod->name = $request->name;
|
||||
$paymentMethod->company_id = $request->header('company');
|
||||
$paymentMethod->save();
|
||||
|
||||
return response()->json([
|
||||
'paymentMethod' => $paymentMethod
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \Crater\PaymentMethod $paymentMethod
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(PaymentMethod $paymentMethod)
|
||||
{
|
||||
$payments = $paymentMethod->payments;
|
||||
|
||||
if ($payments->count() > 0) {
|
||||
return response()->json([
|
||||
'error' => 'payments_attached'
|
||||
]);
|
||||
}
|
||||
|
||||
$paymentMethod->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => 'Payment method deleted successfully'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ namespace Crater\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Crater\Setting;
|
||||
use Crater\Mail\TestMail;
|
||||
use Mail;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
@@ -23,4 +25,18 @@ class SettingsController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function testEmailConfig(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'to' => 'required|email',
|
||||
'subject' => 'required',
|
||||
'message' => 'required'
|
||||
]);
|
||||
|
||||
Mail::to($request->to)->send(new TestMail($request->subject, $request->message));
|
||||
|
||||
return response()->json([
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
119
app/Http/Controllers/UnitController.php
Normal file
119
app/Http/Controllers/UnitController.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Http\Controllers;
|
||||
|
||||
use Crater\Unit;
|
||||
use Illuminate\Http\Request;
|
||||
use Crater\Http\Requests\UnitRequest;
|
||||
|
||||
class UnitController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$units = Unit::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'units' => $units
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(UnitRequest $request)
|
||||
{
|
||||
$unit = new Unit;
|
||||
$unit->name = $request->name;
|
||||
$unit->company_id = $request->header('company');
|
||||
$unit->save();
|
||||
|
||||
return response()->json([
|
||||
'unit' => $unit
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Crater\Unit $unit
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Unit $unit)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \Crater\Unit $unit
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Unit $unit)
|
||||
{
|
||||
return response()->json([
|
||||
'unit' => $unit
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Crater\Unit $unit
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UnitRequest $request, Unit $unit)
|
||||
{
|
||||
$unit->name = $request->name;
|
||||
$unit->company_id = $request->header('company');
|
||||
$unit->save();
|
||||
|
||||
return response()->json([
|
||||
'unit' => $unit
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \Crater\Unit $unit
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Unit $unit)
|
||||
{
|
||||
$items = $unit->items;
|
||||
|
||||
if ($items->count() > 0) {
|
||||
return response()->json([
|
||||
'error' => 'items_attached'
|
||||
]);
|
||||
}
|
||||
|
||||
$unit->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => 'Unit deleted successfully'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ use Crater\User;
|
||||
use Crater\Currency;
|
||||
use Crater\Setting;
|
||||
use Crater\Item;
|
||||
use Crater\PaymentMethod;
|
||||
use Crater\Unit;
|
||||
use Crater\TaxType;
|
||||
use DB;
|
||||
use Carbon\Carbon;
|
||||
@@ -46,10 +48,18 @@ class UsersController extends Controller
|
||||
$request->header('company')
|
||||
);
|
||||
|
||||
$items = Item::all();
|
||||
$items = Item::with('taxes')->get();
|
||||
|
||||
$taxTypes = TaxType::latest()->get();
|
||||
|
||||
$paymentMethods = PaymentMethod::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
$units = Unit::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'user' => $user,
|
||||
'customers' => $customers,
|
||||
@@ -61,6 +71,8 @@ class UsersController extends Controller
|
||||
'items' => $items,
|
||||
'taxTypes' => $taxTypes,
|
||||
'moment_date_format' => $moment_date_format,
|
||||
'paymentMethods' => $paymentMethods,
|
||||
'units' => $units,
|
||||
'fiscal_year' => $fiscal_year,
|
||||
]);
|
||||
}
|
||||
|
||||
40
app/Http/Requests/PaymentMethodRequest.php
Normal file
40
app/Http/Requests/PaymentMethodRequest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class PaymentMethodRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$data = [
|
||||
'name' => 'required|unique:payment_methods,name'
|
||||
];
|
||||
|
||||
if ($this->getMethod() == 'PUT') {
|
||||
$data['name'] = [
|
||||
'required',
|
||||
Rule::unique('payment_methods')->ignore($this->route('payment_method'), 'id')
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
40
app/Http/Requests/UnitRequest.php
Normal file
40
app/Http/Requests/UnitRequest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UnitRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$data = [
|
||||
'name' => 'required|unique:units,name'
|
||||
];
|
||||
|
||||
if ($this->getMethod() == 'PUT') {
|
||||
$data['name'] = [
|
||||
'required',
|
||||
Rule::unique('units')->ignore($this->route('unit'), 'id')
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
19
app/Item.php
19
app/Item.php
@@ -24,19 +24,24 @@ class Item extends Model
|
||||
'formattedCreatedAt'
|
||||
];
|
||||
|
||||
public function unit()
|
||||
{
|
||||
return $this->belongsTo(Unit::class);
|
||||
}
|
||||
|
||||
public function scopeWhereSearch($query, $search)
|
||||
{
|
||||
return $query->where('name', 'LIKE', '%'.$search.'%');
|
||||
return $query->where('items.name', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
|
||||
public function scopeWherePrice($query, $price)
|
||||
{
|
||||
return $query->where('price', $price);
|
||||
return $query->where('items.price', $price);
|
||||
}
|
||||
|
||||
public function scopeWhereUnit($query, $unit)
|
||||
public function scopeWhereUnit($query, $unit_id)
|
||||
{
|
||||
return $query->where('unit', $unit);
|
||||
return $query->where('items.unit_id', $unit_id);
|
||||
}
|
||||
|
||||
public function scopeWhereOrder($query, $orderByField, $orderBy)
|
||||
@@ -56,8 +61,8 @@ class Item extends Model
|
||||
$query->wherePrice($filters->get('price'));
|
||||
}
|
||||
|
||||
if ($filters->get('unit')) {
|
||||
$query->whereUnit($filters->get('unit'));
|
||||
if ($filters->get('unit_id')) {
|
||||
$query->whereUnit($filters->get('unit_id'));
|
||||
}
|
||||
|
||||
if ($filters->get('orderByField') || $filters->get('orderBy')) {
|
||||
@@ -80,7 +85,7 @@ class Item extends Model
|
||||
|
||||
public function scopeWhereCompany($query, $company_id)
|
||||
{
|
||||
$query->where('company_id', $company_id);
|
||||
$query->where('items.company_id', $company_id);
|
||||
}
|
||||
|
||||
public function invoiceItems()
|
||||
|
||||
162
app/Listeners/Updates/v2/Version220.php
Normal file
162
app/Listeners/Updates/v2/Version220.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Listeners\Updates\v2;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Crater\Setting;
|
||||
use Crater\Unit;
|
||||
use Crater\PaymentMethod;
|
||||
use Crater\Currency;
|
||||
use Crater\Payment;
|
||||
use Crater\Item;
|
||||
use Crater\User;
|
||||
use Crater\Listeners\Updates\Listener;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class Version220 extends Listener
|
||||
{
|
||||
const VERSION = '2.2.0';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
if ($this->isListenerFired($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->changeMigrations();
|
||||
|
||||
$this->addSeederData();
|
||||
|
||||
$this->databaseChanges();
|
||||
|
||||
$this->changeMigrations(true);
|
||||
|
||||
Setting::setSetting('version', static::VERSION);
|
||||
}
|
||||
|
||||
public function changeMigrations($removeColumn = false)
|
||||
{
|
||||
if ($removeColumn) {
|
||||
\Schema::table('items', function (Blueprint $table) {
|
||||
$table->dropColumn('unit');
|
||||
});
|
||||
|
||||
\Schema::table('payments', function (Blueprint $table) {
|
||||
$table->dropColumn('payment_mode');
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
\Schema::create('units', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
\Schema::table('items', function (Blueprint $table) {
|
||||
$table->integer('unit_id')->unsigned()->nullable();
|
||||
$table->foreign('unit_id')->references('id')->on('units')->onDelete('cascade');
|
||||
});
|
||||
|
||||
\Schema::create('payment_methods', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
\Schema::table('payments', function (Blueprint $table) {
|
||||
$table->string('unique_hash')->nullable();
|
||||
$table->integer('payment_method_id')->unsigned()->nullable();
|
||||
$table->foreign('payment_method_id')->references('id')->on('payment_methods')->onDelete('cascade');
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function addSeederData()
|
||||
{
|
||||
$company_id = User::where('role', 'admin')->first()->company_id;
|
||||
|
||||
Unit::create(['name' => 'box', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'cm', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'dz', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'ft', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'g', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'in', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'kg', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'km', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'lb', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'mg', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'pc', 'company_id' => $company_id]);
|
||||
|
||||
PaymentMethod::create(['name' => 'Cash', 'company_id' => $company_id]);
|
||||
PaymentMethod::create(['name' => 'Check', 'company_id' => $company_id]);
|
||||
PaymentMethod::create(['name' => 'Credit Card', 'company_id' => $company_id]);
|
||||
PaymentMethod::create(['name' => 'Bank Transfer', 'company_id' => $company_id]);
|
||||
|
||||
Currency::create([
|
||||
'name' => 'Serbian Dinar',
|
||||
'code' => 'RSD',
|
||||
'symbol' => 'RSD',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => '.',
|
||||
'decimal_separator' => ','
|
||||
]);
|
||||
}
|
||||
|
||||
public function databaseChanges()
|
||||
{
|
||||
$payments = Payment::all();
|
||||
|
||||
if ($payments) {
|
||||
foreach ($payments as $payment) {
|
||||
$payment->unique_hash = str_random(60);
|
||||
$payment->save();
|
||||
|
||||
$paymentMethod = PaymentMethod::where('name', $payment->payment_mode)
|
||||
->first();
|
||||
|
||||
if ($paymentMethod) {
|
||||
$payment->payment_method_id = $paymentMethod->id;
|
||||
$payment->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$items = Item::all();
|
||||
|
||||
if ($items) {
|
||||
foreach ($items as $item) {
|
||||
$unit = Unit::where('name', $item->unit)
|
||||
->first();
|
||||
|
||||
if ($unit) {
|
||||
$item->unit_id = $unit->id;
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
app/Mail/PaymentPdf.php
Normal file
38
app/Mail/PaymentPdf.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class PaymentPdf extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $data = [];
|
||||
|
||||
public $notificationEmail = '';
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($data, $notificationEmail)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->notificationEmail = $notificationEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->from($this->notificationEmail)->markdown('emails.send.payment', ['data', $this->data]);
|
||||
}
|
||||
}
|
||||
38
app/Mail/TestMail.php
Normal file
38
app/Mail/TestMail.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace Crater\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class TestMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
public $subject;
|
||||
public $message;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param $subject
|
||||
* @param $message
|
||||
*/
|
||||
public function __construct($subject, $message)
|
||||
{
|
||||
$this->subject = $subject;
|
||||
$this->message = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->subject($this->subject)->markdown('emails.test')->with([
|
||||
'my_message' => $this->message
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ use Crater\User;
|
||||
use Crater\Invoice;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\PaymentMethod;
|
||||
|
||||
class Payment extends Model
|
||||
{
|
||||
@@ -19,9 +20,11 @@ class Payment extends Model
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'invoice_id',
|
||||
'payment_method_id',
|
||||
'payment_date',
|
||||
'company_id',
|
||||
'notes',
|
||||
'unique_hash',
|
||||
'payment_number',
|
||||
'payment_mode',
|
||||
'amount'
|
||||
@@ -84,7 +87,6 @@ class Payment extends Model
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
|
||||
public function invoice()
|
||||
{
|
||||
return $this->belongsTo(Invoice::class);
|
||||
@@ -95,6 +97,11 @@ class Payment extends Model
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function paymentMethod()
|
||||
{
|
||||
return $this->belongsTo(PaymentMethod::class);
|
||||
}
|
||||
|
||||
public function getFormattedCreatedAtAttribute($value)
|
||||
{
|
||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||
@@ -123,9 +130,9 @@ class Payment extends Model
|
||||
return $query->where('payments.payment_number', 'LIKE', '%'.$paymentNumber.'%');
|
||||
}
|
||||
|
||||
public function scopePaymentMode($query, $paymentMode)
|
||||
public function scopePaymentMethod($query, $paymentMethodId)
|
||||
{
|
||||
return $query->where('payments.payment_mode', $paymentMode);
|
||||
return $query->where('payments.payment_method_id', $paymentMethodId);
|
||||
}
|
||||
|
||||
public function scopeApplyFilters($query, array $filters)
|
||||
@@ -140,8 +147,8 @@ class Payment extends Model
|
||||
$query->paymentNumber($filters->get('payment_number'));
|
||||
}
|
||||
|
||||
if ($filters->get('payment_mode')) {
|
||||
$query->paymentMode($filters->get('payment_mode'));
|
||||
if ($filters->get('payment_method_id')) {
|
||||
$query->paymentMethod($filters->get('payment_method_id'));
|
||||
}
|
||||
|
||||
if ($filters->get('customer_id')) {
|
||||
|
||||
25
app/PaymentMethod.php
Normal file
25
app/PaymentMethod.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Crater;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class PaymentMethod extends Model
|
||||
{
|
||||
protected $fillable = ['name', 'company_id'];
|
||||
|
||||
public function payments()
|
||||
{
|
||||
return $this->hasMany(Payment::class);
|
||||
}
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function scopeWhereCompany($query, $company_id)
|
||||
{
|
||||
$query->where('company_id', $company_id);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use Crater\Listeners\Updates\v2\Version200;
|
||||
use Crater\Listeners\Updates\v2\Version201;
|
||||
use Crater\Listeners\Updates\v2\Version202;
|
||||
use Crater\Listeners\Updates\v2\Version210;
|
||||
use Crater\Listeners\Updates\v2\Version220;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -25,6 +26,7 @@ class EventServiceProvider extends ServiceProvider
|
||||
Version201::class,
|
||||
Version202::class,
|
||||
Version210::class,
|
||||
Version220::class,
|
||||
],
|
||||
Registered::class => [
|
||||
SendEmailVerificationNotification::class,
|
||||
|
||||
26
app/Unit.php
Normal file
26
app/Unit.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Crater;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\Item;
|
||||
|
||||
class Unit extends Model
|
||||
{
|
||||
protected $fillable = ['name', 'company_id'];
|
||||
|
||||
public function items()
|
||||
{
|
||||
return $this->hasMany(Item::class);
|
||||
}
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function scopeWhereCompany($query, $company_id)
|
||||
{
|
||||
$query->where('company_id', $company_id);
|
||||
}
|
||||
}
|
||||
34
database/migrations/2017_04_11_064308_create_units_table.php
Normal file
34
database/migrations/2017_04_11_064308_create_units_table.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateUnitsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('units');
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ class CreateItemsTable extends Migration
|
||||
$table->unsignedBigInteger('price');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->integer('unit_id')->unsigned()->nullable();
|
||||
$table->foreign('unit_id')->references('id')->on('units')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,6 +30,6 @@ class CreateExpenseCategoriesTable extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('expenses_categories');
|
||||
Schema::dropIfExists('expense_categories');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,6 @@ class CreateAddressesTable extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('address');
|
||||
Schema::dropIfExists('addresses');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreatePaymentMethodsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('payment_methods', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('payment_methods');
|
||||
}
|
||||
}
|
||||
@@ -16,16 +16,18 @@ class CreatePaymentsTable extends Migration
|
||||
Schema::create('payments', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('payment_number');
|
||||
$table->string('payment_mode')->nullable();
|
||||
$table->date('payment_date');
|
||||
$table->text('notes')->nullable();
|
||||
$table->unsignedBigInteger('amount');
|
||||
$table->string('unique_hash')->nullable();
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->integer('invoice_id')->unsigned()->nullable();
|
||||
$table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->integer('payment_method_id')->unsigned()->nullable();
|
||||
$table->foreign('payment_method_id')->references('id')->on('payment_methods')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
20
database/seeds/PaymentMethodSeeder.php
Normal file
20
database/seeds/PaymentMethodSeeder.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Crater\PaymentMethod;
|
||||
|
||||
class PaymentMethodSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
PaymentMethod::create(['name' => 'Cash', 'company_id' => 1]);
|
||||
PaymentMethod::create(['name' => 'Check', 'company_id' => 1]);
|
||||
PaymentMethod::create(['name' => 'Credit Card', 'company_id' => 1]);
|
||||
PaymentMethod::create(['name' => 'Bank Transfer', 'company_id' => 1]);
|
||||
}
|
||||
}
|
||||
27
database/seeds/UnitSeeder.php
Normal file
27
database/seeds/UnitSeeder.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Crater\Unit;
|
||||
|
||||
class UnitSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Unit::create(['name' => 'box', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'cm', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'dz', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'ft', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'g', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'in', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'kg', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'km', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'lb', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'mg', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'pc', 'company_id' => 1]);
|
||||
}
|
||||
}
|
||||
15
package-lock.json
generated
15
package-lock.json
generated
@@ -17428,6 +17428,16 @@
|
||||
"resolved": "https://registry.npmjs.org/v-money/-/v-money-0.8.1.tgz",
|
||||
"integrity": "sha512-raz87AP5F2YEpv1GAocI3SC/y9af1+TQeZQIhAK5UNovho6dnh6RQBa5UG8ZNC+BPLpUh5VECi7EWTjr4+4s1g=="
|
||||
},
|
||||
"v-tooltip": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/v-tooltip/-/v-tooltip-2.0.2.tgz",
|
||||
"integrity": "sha512-xQ+qzOFfywkLdjHknRPgMMupQNS8yJtf9Utd5Dxiu/0n4HtrxqsgDtN2MLZ0LKbburtSAQgyypuE/snM8bBZhw==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.11",
|
||||
"popper.js": "^1.15.0",
|
||||
"vue-resize": "^0.4.5"
|
||||
}
|
||||
},
|
||||
"v8-compile-cache": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
|
||||
@@ -17515,6 +17525,11 @@
|
||||
"resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-2.1.6.tgz",
|
||||
"integrity": "sha512-s7jmZPlm9FeueJg1RwJtnE9KNPtME/7C8uRWSfp9/yEN4M8XcS/d+bddoyVwVnvFyRh9msFo0HWeW0vTL8Qv+w=="
|
||||
},
|
||||
"vue-resize": {
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.4.5.tgz",
|
||||
"integrity": "sha512-bhP7MlgJQ8TIkZJXAfDf78uJO+mEI3CaLABLjv0WNzr4CcGRGPIAItyWYnP6LsPA4Oq0WE+suidNs6dgpO4RHg=="
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-2.7.0.tgz",
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"toastr": "^2.1.4",
|
||||
"upgrade": "^1.1.0",
|
||||
"v-money": "^0.8.1",
|
||||
"v-tooltip": "^2.0.2",
|
||||
"vue": "^2.5.17",
|
||||
"vue-avatar-cropper": "^1.0.5",
|
||||
"vue-i18n": "^8.14.0",
|
||||
|
||||
2
public/assets/css/crater.css
vendored
2
public/assets/css/crater.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"/assets/js/app.js": "/assets/js/app.js?id=a9f802b3fe774e87bf0c",
|
||||
"/assets/css/crater.css": "/assets/css/crater.css?id=193e5770a0e7a8604f35"
|
||||
"/assets/js/app.js": "/assets/js/app.js?id=b20880c1aac2aeab3640",
|
||||
"/assets/css/crater.css": "/assets/css/crater.css?id=ade5377bd8ec409249bf"
|
||||
}
|
||||
|
||||
2
resources/assets/js/bootstrap.js
vendored
2
resources/assets/js/bootstrap.js
vendored
@@ -12,6 +12,7 @@ import CustomerModal from './components/base/modal/CustomerModal.vue'
|
||||
import TaxTypeModal from './components/base/modal/TaxTypeModal.vue'
|
||||
import CategoryModal from './components/base/modal/CategoryModal.vue'
|
||||
import money from 'v-money'
|
||||
import VTooltip from 'v-tooltip'
|
||||
|
||||
/**
|
||||
* Global css plugins
|
||||
@@ -107,6 +108,7 @@ window.toastr = require('toastr')
|
||||
|
||||
Vue.use(VueRouter)
|
||||
Vue.use(Vuex)
|
||||
Vue.use(VTooltip)
|
||||
|
||||
// register directive v-money and component <money>
|
||||
Vue.use(money, {precision: 2})
|
||||
|
||||
@@ -21,6 +21,9 @@ import EstimateTemplate from './EstimateTemplate'
|
||||
import InvoiceTemplate from './InvoiceTemplate'
|
||||
import CustomerModal from './CustomerModal'
|
||||
import CategoryModal from './CategoryModal'
|
||||
import PaymentMode from './PaymentModeModal'
|
||||
import ItemUnit from './ItemUnitModal'
|
||||
import MailTestModal from './MailTestModal'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -29,7 +32,10 @@ export default {
|
||||
EstimateTemplate,
|
||||
InvoiceTemplate,
|
||||
CustomerModal,
|
||||
CategoryModal
|
||||
CategoryModal,
|
||||
PaymentMode,
|
||||
ItemUnit,
|
||||
MailTestModal
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
@@ -341,6 +341,7 @@ export default {
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
isEdit: false,
|
||||
isLoading: false,
|
||||
countryList: [],
|
||||
billingCountry: null,
|
||||
@@ -399,9 +400,22 @@ export default {
|
||||
...mapGetters('currency', [
|
||||
'defaultCurrency',
|
||||
'currencies'
|
||||
]),
|
||||
...mapGetters('modal', [
|
||||
'modalDataID',
|
||||
'modalData',
|
||||
'modalActive'
|
||||
])
|
||||
},
|
||||
watch: {
|
||||
'modalDataID' (val) {
|
||||
if (val) {
|
||||
this.isEdit = true
|
||||
this.setData()
|
||||
} else {
|
||||
this.isEdit = false
|
||||
}
|
||||
},
|
||||
billingCountry () {
|
||||
if (this.billingCountry) {
|
||||
this.billing.country_id = this.billingCountry.id
|
||||
@@ -419,6 +433,9 @@ export default {
|
||||
this.$refs.name.focus = true
|
||||
this.currency = this.defaultCurrency
|
||||
this.fetchCountry()
|
||||
if (this.modalDataID) {
|
||||
this.setData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('invoice', {
|
||||
@@ -493,6 +510,24 @@ export default {
|
||||
this.formData.addresses = [{...this.shipping, type: 'shipping'}]
|
||||
return true
|
||||
},
|
||||
async setData () {
|
||||
this.formData.id = this.modalData.id
|
||||
this.formData.name = this.modalData.name
|
||||
this.formData.email = this.modalData.email
|
||||
this.formData.contact_name = this.modalData.contact_name
|
||||
this.formData.phone = this.modalData.phone
|
||||
this.formData.website = this.modalData.website
|
||||
this.currency = this.modalData.currency
|
||||
|
||||
if (this.modalData.billing_address) {
|
||||
this.billing = this.modalData.billing_address
|
||||
this.billingCountry = this.modalData.billing_address.country
|
||||
}
|
||||
if (this.modalData.shipping_address) {
|
||||
this.shipping = this.modalData.shipping_address
|
||||
this.shippingCountry = this.modalData.shipping_address.country
|
||||
}
|
||||
},
|
||||
async submitCustomerData () {
|
||||
this.$v.formData.$touch()
|
||||
|
||||
@@ -510,14 +545,23 @@ export default {
|
||||
this.formData.currency_id = this.defaultCurrency.id
|
||||
}
|
||||
try {
|
||||
let response = await this.addCustomer(this.formData)
|
||||
let response = null
|
||||
if (this.modalDataID) {
|
||||
response = await this.updateCustomer(this.formData)
|
||||
} else {
|
||||
response = await this.addCustomer(this.formData)
|
||||
}
|
||||
if (response.data) {
|
||||
window.toastr['success'](this.$tc('customers.created_message'))
|
||||
if (this.modalDataID) {
|
||||
window.toastr['success'](this.$tc('customers.updated_message'))
|
||||
} else {
|
||||
window.toastr['success'](this.$tc('customers.created_message'))
|
||||
}
|
||||
this.isLoading = false
|
||||
if (this.$route.name === 'invoices.create') {
|
||||
if (this.$route.name === 'invoices.create' || this.$route.name === 'invoices.edit') {
|
||||
this.setInvoiceCustomer(response.data.customer.id)
|
||||
}
|
||||
if (this.$route.name === 'estimates.create') {
|
||||
if (this.$route.name === 'estimates.create' || this.$route.name === 'estimates.edit') {
|
||||
this.setEstimateCustomer(response.data.customer.id)
|
||||
}
|
||||
this.resetData()
|
||||
|
||||
@@ -45,14 +45,34 @@
|
||||
<div class="col-sm-7">
|
||||
<base-select
|
||||
v-model="formData.unit"
|
||||
:options="units"
|
||||
:options="itemUnits"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
label="name"
|
||||
>
|
||||
<div slot="afterList">
|
||||
<button type="button" class="list-add-button" @click="addItemUnit">
|
||||
<font-awesome-icon class="icon" icon="cart-plus" />
|
||||
<label>{{ $t('settings.customization.items.add_item_unit') }}</label>
|
||||
</button>
|
||||
</div>
|
||||
</base-select>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isTexPerItem" class="form-group row">
|
||||
<label class="col-sm-4 col-form-label input-label">{{ $t('items.taxes') }}</label>
|
||||
<div class="col-sm-7">
|
||||
<base-select
|
||||
v-model="formData.taxes"
|
||||
:options="getTaxTypes"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="true"
|
||||
:multiple="true"
|
||||
label="tax_name"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label input-label">{{ $t('items.description') }}</label>
|
||||
<div class="col-sm-7">
|
||||
@@ -124,11 +144,13 @@ export default {
|
||||
{ name: 'mg', value: 'mg' },
|
||||
{ name: 'pc', value: 'pc' }
|
||||
],
|
||||
taxes: [],
|
||||
formData: {
|
||||
name: null,
|
||||
price: null,
|
||||
description: null,
|
||||
unit: null
|
||||
unit: null,
|
||||
taxes: []
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -161,12 +183,28 @@ export default {
|
||||
this.formData.price = newValue * 100
|
||||
}
|
||||
},
|
||||
// itemUnits () {
|
||||
// return this.units
|
||||
// },
|
||||
...mapGetters('modal', [
|
||||
'modalDataID'
|
||||
'modalDataID',
|
||||
'modalData'
|
||||
]),
|
||||
...mapGetters('item', [
|
||||
'getItemById'
|
||||
])
|
||||
'getItemById',
|
||||
'itemUnits'
|
||||
]),
|
||||
...mapGetters('taxType', [
|
||||
'taxTypes'
|
||||
]),
|
||||
isTexPerItem () {
|
||||
return this.modalData.taxPerItem === 'YES'
|
||||
},
|
||||
getTaxTypes () {
|
||||
return this.taxTypes.map(tax => {
|
||||
return {...tax, tax_name: tax.name + ' (' + tax.percent + '%)'}
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modalDataID () {
|
||||
@@ -179,12 +217,17 @@ export default {
|
||||
this.isEdit = true
|
||||
this.fetchEditData()
|
||||
}
|
||||
|
||||
if (this.isEdit) {
|
||||
this.loadEditData()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$refs.name.focus = true
|
||||
},
|
||||
methods: {
|
||||
...mapActions('modal', [
|
||||
'openModal',
|
||||
'closeModal',
|
||||
'resetModalData'
|
||||
]),
|
||||
@@ -203,7 +246,6 @@ export default {
|
||||
unit: null,
|
||||
id: null
|
||||
}
|
||||
|
||||
this.$v.$reset()
|
||||
},
|
||||
fetchEditData () {
|
||||
@@ -230,9 +272,20 @@ export default {
|
||||
if (this.isEdit) {
|
||||
response = await this.updateItem(this.formData)
|
||||
} else {
|
||||
response = await this.addItem(this.formData)
|
||||
let data = {
|
||||
...this.formData,
|
||||
taxes: this.formData.taxes.map(tax => {
|
||||
return {
|
||||
tax_type_id: tax.id,
|
||||
amount: ((this.formData.price * tax.percent) / 100),
|
||||
percent: tax.percent,
|
||||
name: tax.name,
|
||||
collective_tax: 0
|
||||
}
|
||||
})
|
||||
}
|
||||
response = await this.addItem(data)
|
||||
}
|
||||
|
||||
if (response.data) {
|
||||
window.toastr['success'](this.$tc('items.created_message'))
|
||||
this.setItem(response.data.item)
|
||||
@@ -245,6 +298,12 @@ export default {
|
||||
}
|
||||
window.toastr['error'](response.data.error)
|
||||
},
|
||||
async addItemUnit () {
|
||||
this.openModal({
|
||||
'title': 'Add Item Unit',
|
||||
'componentName': 'ItemUnit'
|
||||
})
|
||||
},
|
||||
closeItemModal () {
|
||||
this.resetFormData()
|
||||
this.closeModal()
|
||||
|
||||
148
resources/assets/js/components/base/modal/ItemUnitModal.vue
Normal file
148
resources/assets/js/components/base/modal/ItemUnitModal.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<div class="item-unit-modal">
|
||||
<form action="" @submit.prevent="submitItemUnit">
|
||||
<div class="card-body">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label input-label">{{ $t('settings.customization.items.unit_name') }} <span class="required"> *</span></label>
|
||||
<div class="col-sm-7">
|
||||
<base-input
|
||||
ref="name"
|
||||
:invalid="$v.formData.name.$error"
|
||||
v-model="formData.name"
|
||||
type="text"
|
||||
@input="$v.formData.name.$touch()"
|
||||
/>
|
||||
<div v-if="$v.formData.name.$error">
|
||||
<span v-if="!$v.formData.name.required" class="form-group__message text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<base-button
|
||||
:outline="true"
|
||||
class="mr-3"
|
||||
color="theme"
|
||||
type="button"
|
||||
@click="closePaymentModeModal"
|
||||
>
|
||||
{{ $t('general.cancel') }}
|
||||
</base-button>
|
||||
<base-button
|
||||
:loading="isLoading"
|
||||
color="theme"
|
||||
icon="save"
|
||||
type="submit"
|
||||
>
|
||||
{{ !isEdit ? $t('general.save') : $t('general.update') }}
|
||||
</base-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
const { required, minLength } = require('vuelidate/lib/validators')
|
||||
export default {
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
isEdit: false,
|
||||
isLoading: false,
|
||||
formData: {
|
||||
id: null,
|
||||
name: null
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('modal', [
|
||||
'modalDataID',
|
||||
'modalData',
|
||||
'modalActive'
|
||||
])
|
||||
},
|
||||
validations: {
|
||||
formData: {
|
||||
name: {
|
||||
required,
|
||||
minLength: minLength(2)
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
this.$refs.name.focus = true
|
||||
if (this.modalDataID) {
|
||||
this.isEdit = true
|
||||
this.setData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('modal', [
|
||||
'closeModal',
|
||||
'resetModalData'
|
||||
]),
|
||||
...mapActions('item', [
|
||||
'addItemUnit',
|
||||
'updateItemUnit',
|
||||
'fatchItemUnit'
|
||||
]),
|
||||
resetFormData () {
|
||||
this.formData = {
|
||||
id: null,
|
||||
name: null
|
||||
}
|
||||
this.$v.formData.$reset()
|
||||
},
|
||||
async submitItemUnit () {
|
||||
this.$v.formData.$touch()
|
||||
if (this.$v.$invalid) {
|
||||
return true
|
||||
}
|
||||
this.isLoading = true
|
||||
|
||||
let response
|
||||
|
||||
if (this.isEdit) {
|
||||
response = await this.updateItemUnit(this.formData)
|
||||
|
||||
if (response.data) {
|
||||
window.toastr['success'](this.$t('settings.customization.items.item_unit_updated'))
|
||||
this.closePaymentModeModal()
|
||||
return true
|
||||
}
|
||||
|
||||
window.toastr['error'](response.data.error)
|
||||
} else {
|
||||
try {
|
||||
response = await this.addItemUnit(this.formData)
|
||||
if (response.data) {
|
||||
this.isLoading = false
|
||||
window.toastr['success'](this.$t('settings.customization.items.item_unit_added'))
|
||||
this.closePaymentModeModal()
|
||||
return true
|
||||
} window.toastr['error'](response.data.error)
|
||||
} catch (err) {
|
||||
if (err.response.data.errors.name) {
|
||||
this.isLoading = true
|
||||
window.toastr['error'](this.$t('validation.item_unit_already_taken'))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async setData () {
|
||||
this.formData = {
|
||||
id: this.modalData.id,
|
||||
name: this.modalData.name
|
||||
}
|
||||
},
|
||||
closePaymentModeModal () {
|
||||
this.resetModalData()
|
||||
this.resetFormData()
|
||||
this.closeModal()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
166
resources/assets/js/components/base/modal/MailTestModal.vue
Normal file
166
resources/assets/js/components/base/modal/MailTestModal.vue
Normal file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<div class="mail-test-modal">
|
||||
<form action="" @submit.prevent="onTestMailSend">
|
||||
<div class="card-body">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label input-label">{{ $t('general.to') }} <span class="required"> *</span></label>
|
||||
<div class="col-sm-7">
|
||||
<base-input
|
||||
ref="to"
|
||||
:invalid="$v.formData.to.$error"
|
||||
v-model="formData.to"
|
||||
type="text"
|
||||
@input="$v.formData.to.$touch()"
|
||||
/>
|
||||
<div v-if="$v.formData.to.$error">
|
||||
<span v-if="!$v.formData.to.required" class="form-group__message text-danger">{{ $tc('validation.required') }}</span>
|
||||
<span v-if="!$v.formData.to.email" class="form-group__message text-danger"> {{ $t('validation.email_incorrect') }} </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label input-label">{{ $t('general.subject') }} <span class="required"> *</span></label>
|
||||
<div class="col-sm-7">
|
||||
<div class="base-input">
|
||||
<base-input
|
||||
:invalid="$v.formData.subject.$error"
|
||||
v-model="formData.subject"
|
||||
type="text"
|
||||
@input="$v.formData.subject.$touch()"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="$v.formData.subject.$error">
|
||||
<span v-if="!$v.formData.subject.required" class="text-danger">{{ $t('validation.required') }}</span>
|
||||
<span v-if="!$v.formData.subject.maxLength" class="text-danger">{{ $t('validation.subject_maxlength') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label input-label">{{ $t('general.message') }}<span class="required"> *</span></label>
|
||||
<div class="col-sm-7">
|
||||
<base-text-area
|
||||
v-model="formData.message"
|
||||
:invalid="$v.formData.message.$error"
|
||||
rows="4"
|
||||
cols="50"
|
||||
@input="$v.formData.message.$touch()"
|
||||
/>
|
||||
<div v-if="$v.formData.message.$error">
|
||||
<span v-if="!$v.formData.message.required" class="text-danger">{{ $t('validation.required') }}</span>
|
||||
<span v-if="!$v.formData.message.maxLength" class="text-danger">{{ $t('validation.message_maxlength') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<base-button
|
||||
:outline="true"
|
||||
class="mr-3"
|
||||
color="theme"
|
||||
type="button"
|
||||
@click="closeTaxModal"
|
||||
>
|
||||
{{ $t('general.cancel') }}
|
||||
</base-button>
|
||||
<base-button
|
||||
:loading="isLoading"
|
||||
color="theme"
|
||||
icon="save"
|
||||
type="submit"
|
||||
>
|
||||
{{ !isEdit ? $t('general.save') : $t('general.update') }}
|
||||
</base-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
const { required, minLength, email, maxLength } = require('vuelidate/lib/validators')
|
||||
export default {
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
isEdit: false,
|
||||
isLoading: false,
|
||||
formData: {
|
||||
to: null,
|
||||
subject: null,
|
||||
message: null
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('modal', [
|
||||
'modalDataID',
|
||||
'modalData',
|
||||
'modalActive'
|
||||
])
|
||||
},
|
||||
validations: {
|
||||
formData: {
|
||||
to: {
|
||||
required,
|
||||
email
|
||||
},
|
||||
subject: {
|
||||
required,
|
||||
maxLength: maxLength(100)
|
||||
},
|
||||
message: {
|
||||
required,
|
||||
maxLength: maxLength(255)
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
this.$refs.to.focus = true
|
||||
},
|
||||
methods: {
|
||||
...mapActions('modal', [
|
||||
'closeModal',
|
||||
'resetModalData'
|
||||
]),
|
||||
resetFormData () {
|
||||
this.formData = {
|
||||
to: null,
|
||||
subject: null,
|
||||
message: null
|
||||
}
|
||||
this.$v.formData.$reset()
|
||||
},
|
||||
async onTestMailSend () {
|
||||
this.$v.formData.$touch()
|
||||
|
||||
if (this.$v.$invalid) {
|
||||
return true
|
||||
}
|
||||
|
||||
this.isLoading = true
|
||||
let response = await axios.post('/api/settings/test/mail', this.formData)
|
||||
if (response.data) {
|
||||
|
||||
if (response.data.success) {
|
||||
window.toastr['success'](this.$tc('general.send_mail_successfully'))
|
||||
this.closeTaxModal()
|
||||
this.isLoading = false
|
||||
return true
|
||||
}
|
||||
|
||||
window.toastr['error'](this.$tc('validation.something_went_wrong'))
|
||||
this.closeTaxModal()
|
||||
this.isLoading = false
|
||||
return true
|
||||
}
|
||||
window.toastr['error'](response.data.error)
|
||||
},
|
||||
closeTaxModal () {
|
||||
this.resetModalData()
|
||||
this.resetFormData()
|
||||
this.closeModal()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
143
resources/assets/js/components/base/modal/PaymentModeModal.vue
Normal file
143
resources/assets/js/components/base/modal/PaymentModeModal.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<div class="payment-modes-modal">
|
||||
<form action="" @submit.prevent="submitPaymentMode">
|
||||
<div class="card-body">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label input-label">{{ $t('settings.customization.payments.mode_name') }} <span class="required"> *</span></label>
|
||||
<div class="col-sm-7">
|
||||
<base-input
|
||||
ref="name"
|
||||
:invalid="$v.formData.name.$error"
|
||||
v-model="formData.name"
|
||||
type="text"
|
||||
@input="$v.formData.name.$touch()"
|
||||
/>
|
||||
<div v-if="$v.formData.name.$error">
|
||||
<span v-if="!$v.formData.name.required" class="form-group__message text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<base-button
|
||||
:outline="true"
|
||||
class="mr-3"
|
||||
color="theme"
|
||||
type="button"
|
||||
@click="closePaymentModeModal"
|
||||
>
|
||||
{{ $t('general.cancel') }}
|
||||
</base-button>
|
||||
<base-button
|
||||
:loading="isLoading"
|
||||
color="theme"
|
||||
icon="save"
|
||||
type="submit"
|
||||
>
|
||||
{{ !isEdit ? $t('general.save') : $t('general.update') }}
|
||||
</base-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
const { required, minLength } = require('vuelidate/lib/validators')
|
||||
|
||||
export default {
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
isEdit: false,
|
||||
isLoading: false,
|
||||
formData: {
|
||||
id: null,
|
||||
name: null
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('modal', [
|
||||
'modalDataID',
|
||||
'modalData',
|
||||
'modalActive'
|
||||
])
|
||||
},
|
||||
validations: {
|
||||
formData: {
|
||||
name: {
|
||||
required,
|
||||
minLength: minLength(2)
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
this.$refs.name.focus = true
|
||||
if (this.modalDataID) {
|
||||
this.isEdit = true
|
||||
this.setData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('modal', [
|
||||
'closeModal',
|
||||
'resetModalData'
|
||||
]),
|
||||
...mapActions('payment', [
|
||||
'addPaymentMode',
|
||||
'updatePaymentMode'
|
||||
]),
|
||||
resetFormData () {
|
||||
this.formData = {
|
||||
id: null,
|
||||
name: null
|
||||
}
|
||||
this.$v.formData.$reset()
|
||||
},
|
||||
async submitPaymentMode () {
|
||||
this.$v.formData.$touch()
|
||||
if (this.$v.$invalid) {
|
||||
return true
|
||||
}
|
||||
this.isLoading = true
|
||||
let response
|
||||
if (this.isEdit) {
|
||||
response = await this.updatePaymentMode(this.formData)
|
||||
if (response.data) {
|
||||
window.toastr['success'](this.$t('settings.customization.payments.payment_mode_updated'))
|
||||
this.closePaymentModeModal()
|
||||
return true
|
||||
} window.toastr['error'](response.data.error)
|
||||
} else {
|
||||
try {
|
||||
response = await this.addPaymentMode(this.formData)
|
||||
if (response.data) {
|
||||
this.isLoading = false
|
||||
window.toastr['success'](this.$t('settings.customization.payments.payment_mode_added'))
|
||||
this.closePaymentModeModal()
|
||||
return true
|
||||
} window.toastr['error'](response.data.error)
|
||||
} catch (err) {
|
||||
if (err.response.data.errors.name) {
|
||||
this.isLoading = true
|
||||
window.toastr['error'](this.$t('validation.payment_mode_already_taken'))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async setData () {
|
||||
this.formData = {
|
||||
id: this.modalData.id,
|
||||
name: this.modalData.name
|
||||
}
|
||||
},
|
||||
closePaymentModeModal () {
|
||||
this.resetModalData()
|
||||
this.resetFormData()
|
||||
this.closeModal()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -839,7 +839,7 @@
|
||||
}
|
||||
},
|
||||
"layout_login": {
|
||||
"copyright_crater": "حقوق الطبع والنشر @ كريتر - 2019",
|
||||
"copyright_crater": "حقوق الطبع والنشر @ كريتر - 2020",
|
||||
"super_simple_invoicing": "فوترة سهلة ومبسطة للغاية",
|
||||
"for_freelancer": "للمبرمجين المستقلين",
|
||||
"small_businesses": "والأعال الصغيرة ",
|
||||
@@ -852,6 +852,8 @@
|
||||
"email_incorrect": "بريد الكتروني غير صحيح.",
|
||||
"email_already_taken": "هذا البريد الالكتروني مستخدم مسبقاً",
|
||||
"email_does_not_exist": "لا يوجد كستخدم بهذا البريد الالكتروني",
|
||||
"item_unit_already_taken": "وحدة البند قد اتخذت بالفعل",
|
||||
"payment_mode_already_taken": "لقد تم بالفعل أخذ طريقة الدفع",
|
||||
"send_reset_link": "أرسال رابط استعادة كلمة المرور",
|
||||
"not_yet": "ليس بعد؟ أعد الإرسال الآن..",
|
||||
"password_min_length": "كلمة المرور يجب أن تتكون من {count} أحرف على الأقل",
|
||||
|
||||
877
resources/assets/js/plugins/de.json
Normal file
877
resources/assets/js/plugins/de.json
Normal file
@@ -0,0 +1,877 @@
|
||||
{
|
||||
"credit_notes": {
|
||||
"action": "Aktion",
|
||||
"amount": "Summe",
|
||||
"confirm_delete": "Wollen Sie diese Gutschrift löschen?",
|
||||
"contact": "Kontakt",
|
||||
"credit_notes": "Gutschriften",
|
||||
"credit_notes_list": "Gutschriften-Liste",
|
||||
"credit_number": "Kreditkarten-Nummer",
|
||||
"date": "Datum",
|
||||
"item": {
|
||||
"description": "Beschreibung",
|
||||
"discount": "Rabatt",
|
||||
"price": "Preis",
|
||||
"quantity": "Menge",
|
||||
"sub_total": "Zwischensumme",
|
||||
"tax": "Steuer",
|
||||
"title": "Titel",
|
||||
"total": "Gesamt",
|
||||
"total_discount": "Rabatt Gesamt"
|
||||
},
|
||||
"notes": "Hinweise",
|
||||
"title": "Gutschriften"
|
||||
},
|
||||
"customers": {
|
||||
"action": "Aktion",
|
||||
"add_customer": "Kunde hinzufügen",
|
||||
"add_new_customer": "Neuen Kunden hinzufügen",
|
||||
"added_on": "Hinzugefügt am",
|
||||
"address": "Adresse",
|
||||
"amount_due": "Offener Betrag",
|
||||
"basic_info": "Basisinformation",
|
||||
"billing_address": "Rechnungsadresse",
|
||||
"city": "Stadt",
|
||||
"confirm_delete": "Sie können diesen Kunden nicht wiederherstellen | Sie können diese Kunden nicht wiederherstellen",
|
||||
"contact_name": "Kontakt Name",
|
||||
"contacts_list": "Kunden-Liste",
|
||||
"copy_billing_address": "Rechnungsadresse kopieren",
|
||||
"country": "Land",
|
||||
"created_message": "Kunde erfolgreich erstellt",
|
||||
"customer": "Kunde | Kunden",
|
||||
"deleted_message": "Kunden erfolgreich gelöscht | Kunden erfolgreich gelöscht",
|
||||
"display_name": "Anzeige Name",
|
||||
"edit_customer": "Kunde bearbeiten",
|
||||
"email": "E-Mail",
|
||||
"list_of_customers": "Dieser Abschnitt enthält die Liste der Kunden.",
|
||||
"name": "Name",
|
||||
"new_customer": "Neuer Kunde",
|
||||
"no_customers": "Noch keine Kunden!",
|
||||
"no_customers_found": "Keine Kunden gefunden!",
|
||||
"password": "Passwort",
|
||||
"phone": "Telefon",
|
||||
"primary_contact_name": "Ansprechpartner",
|
||||
"primary_currency": "Primäre Währung",
|
||||
"primary_display_name": "Primärer Anzeige Name",
|
||||
"save_customer": "Kunde speichern",
|
||||
"select_a_customer": "Wählen Sie einen Kunden",
|
||||
"select_city": "Stadt wählen",
|
||||
"select_country": "Land wählen",
|
||||
"select_currency": "Währung wählen",
|
||||
"select_state": "Bundesland wählen",
|
||||
"shipping_address": "Versand-Adresse",
|
||||
"state": "Bundesland",
|
||||
"street_1": "Strasse",
|
||||
"street_2": "Adresszusatz",
|
||||
"street_number": "Hausnummer",
|
||||
"title": "Kunden",
|
||||
"type_or_click": "Eingeben oder anklicken zum auswählen",
|
||||
"update_customer": "Kunden ändern",
|
||||
"updated_message": "Kunde erfolgreich aktualisiert",
|
||||
"website": "Webseite",
|
||||
"zip_code": "PLZ"
|
||||
},
|
||||
"dashboard": {
|
||||
"cards": {
|
||||
"customers": "Kunden",
|
||||
"due_amount": "Offene Beträge",
|
||||
"estimates": "Kostenvoranschläge",
|
||||
"invoices": "Rechnungen"
|
||||
},
|
||||
"chart_info": {
|
||||
"net_income": "Einnahmen Netto",
|
||||
"total_expense": "Gesamtausgaben",
|
||||
"total_receipts": "Eingänge gesamt",
|
||||
"total_sales": "Verkäufe gesamt",
|
||||
"year": "Jahr"
|
||||
},
|
||||
"monthly_chart": {
|
||||
"title": "Umsatz & Kosten"
|
||||
},
|
||||
"recent_estimate_card": {
|
||||
"actions": "Aktionen",
|
||||
"amount_due": "Betrag",
|
||||
"customer": "Kunden",
|
||||
"date": "Datum",
|
||||
"title": "Aktuelle Kostenvoranschläge",
|
||||
"view_all": "Alle Anzeigen"
|
||||
},
|
||||
"recent_invoices_card": {
|
||||
"actions": "Aktionen",
|
||||
"amount_due": "Offener Betrag",
|
||||
"customer": "Kunden",
|
||||
"due_on": "Fällig am",
|
||||
"title": "Fällige Rechnungen",
|
||||
"view_all": "Alle Anzeigen"
|
||||
},
|
||||
"select_year": "Jahr wählen",
|
||||
"weekly_invoices": {
|
||||
"title": "Wöchentliche Rechnungen"
|
||||
}
|
||||
},
|
||||
"estimates": {
|
||||
"Estimate": "Kostenvoranschlag | Kostenvoranschläge",
|
||||
"accepted": "Angenommen",
|
||||
"action": "Aktion",
|
||||
"add_estimate": "Kostenvoranschlag hinzufügen",
|
||||
"add_item": "Fügen Sie ein Artikel hinzu",
|
||||
"add_new_estimate": "Neuen Kostenvoranschlag hinzufügen",
|
||||
"add_new_tax": "neuen Steuersatz hinzufügen",
|
||||
"add_tax": "Steuer hinzufügen",
|
||||
"all": "Alle",
|
||||
"amount": "Summe",
|
||||
"amount_due": "OFFENER BETRAG",
|
||||
"confirm_conversion": "Sie möchten, konvertieren Sie diese Schätzung in die Rechnung?",
|
||||
"confirm_delete": "Der Kostenvoranschlag kann nicht wiederhergestellt werden | Die Kostenvoranschläge können nicht wiederhergestellt werden",
|
||||
"confirm_mark_as_accepted": "Dieser Kostenvoranschlag wird als angenommen markiert",
|
||||
"confirm_mark_as_rejected": "Dieser Kostenvoranschlag wird als abgelehnt markiert",
|
||||
"confirm_mark_as_sent": "Dieser Kostenvoranschlag wird als gesendet markiert",
|
||||
"confirm_send_estimate": "Der Kostenvoranschlag wird per E-Mail an den Kunden gesendet",
|
||||
"contact": "Kontakt",
|
||||
"conversion_message": "Rechnung erfolgreich erstellt",
|
||||
"convert_to_invoice": "Konvertieren in Rechnung",
|
||||
"created_message": "Kostenvoranschlag erfolgreich erstellt",
|
||||
"customer": "KUNDEN",
|
||||
"date": "Datum",
|
||||
"days": "{days} Tage",
|
||||
"declined": "Abgelehnt",
|
||||
"deleted_message": "Kostenvoranschlag erfolgreich gelöscht | Kostenvoranschläge erfolgreich gelöscht",
|
||||
"discount": "Rabatt",
|
||||
"draft": "Entwurf",
|
||||
"due_date": "Fälligkeit",
|
||||
"edit_estimate": "Kostenvoranschlag ändern",
|
||||
"errors": {
|
||||
"required": "Feld ist erforderlich"
|
||||
},
|
||||
"estimate": "Kostenvoranschlag | Kostenvoranschläge",
|
||||
"estimate_number": "Kostenvoran. Nummer",
|
||||
"estimate_template": "Vorlage",
|
||||
"estimates_list": "Liste Kostenvoranschläge",
|
||||
"expiry_date": "Zahlungsziel",
|
||||
"item": {
|
||||
"amount": "Summe",
|
||||
"description": "Beschreibung",
|
||||
"discount": "Rabatt",
|
||||
"price": "Preis",
|
||||
"quantity": "Menge",
|
||||
"select_an_item": "Wählen Sie einen Artikel",
|
||||
"sub_total": "Zwischensumme",
|
||||
"tax": "Steuer",
|
||||
"title": "Titel",
|
||||
"total": "Gesamt",
|
||||
"total_discount": "Rabatt Gesamt",
|
||||
"type_item_description": "Artikel Beschreibung (optional)"
|
||||
},
|
||||
"items": "Artikel",
|
||||
"list_of_estimates": "Dieser Abschnitt enthält die Liste der Kostenvoranschläge.",
|
||||
"mark_as_accepted": "Markiert als angenommen",
|
||||
"mark_as_rejected": "Markiert als abgelehnt",
|
||||
"mark_as_sent": "Als gesendet markieren",
|
||||
"mark_as_sent_successfully": "Kostenvoranschlag als gesendet markiert.",
|
||||
"marked_as_accepted_message": "Kostenvoranschlag als angenommen markiert",
|
||||
"marked_as_rejected_message": "Kostenvoranschlag als abgelehnt markiert",
|
||||
"months": "{months} Monat",
|
||||
"new_estimate": "Neuer Kostenvoranschlag",
|
||||
"no_estimates": "Keine Kostenvoranschläge vorhanden!",
|
||||
"no_matching_estimates": "Es gibt keine übereinstimmenden Kostenvoranschläge!",
|
||||
"notes": "Hinweise",
|
||||
"number": "ANZAHL",
|
||||
"paid": "Bezahlt",
|
||||
"partially_paid": "Teilweise bezahlt",
|
||||
"record_payment": "Zahlung erfassen",
|
||||
"ref_no": "REF. - NR.",
|
||||
"ref_number": "Ref-Nummer",
|
||||
"save_estimate": "Kostenvoranschlag speichern",
|
||||
"send_estimate": "Kostenvoranschlag senden",
|
||||
"send_estimate_successfully": "Kostenvoranschlag erfolgreich gesendet",
|
||||
"sent": "Gesendet",
|
||||
"something_went_wrong": "Da ging etwas schief",
|
||||
"status": "Status",
|
||||
"sub_total": "Zwischensumme",
|
||||
"tax": "Steuer",
|
||||
"title": "Kostenvoranschläge",
|
||||
"total": "Gesamt",
|
||||
"unpaid": "Unbezahlte",
|
||||
"update_Estimate": "Kostenvoranschlag aktualisieren",
|
||||
"updated_message": "Kostenvoranschlag erfolgreich aktualisiert",
|
||||
"user_email_does_not_exist": "Benutzer-E-Mail nicht vorhanden",
|
||||
"years": "{years} Jahre"
|
||||
},
|
||||
"expenses": {
|
||||
"action": "Aktion",
|
||||
"add_expense": "Aufwendung hinzufügen",
|
||||
"add_new_expense": "Neue Aufwendung hinzufügen",
|
||||
"amount": "Summe",
|
||||
"categories": {
|
||||
"actions": "Aktionen",
|
||||
"add_category": "Kategorie hinzufügen",
|
||||
"amount": "Summe",
|
||||
"categories_list": "Liste der Kategorien",
|
||||
"category": "Kategorie | Kategorien",
|
||||
"description": "Beschreibung",
|
||||
"name": "Name",
|
||||
"new_category": "Neue Kategorie",
|
||||
"select_a_category": "Wählen Sie eine Kategorie",
|
||||
"title": "Titel"
|
||||
},
|
||||
"category": "Kategorie",
|
||||
"category_id": "Kategorie-Id",
|
||||
"confirm_delete": "Sie können diese Ausgabe nicht wiederherstellen. | Sie können diese Ausgaben nicht wiederherstellen.",
|
||||
"contact": "Kontakt",
|
||||
"created_message": "Aufwand erfolgreich erstellt",
|
||||
"date": "Aufwandsdatum",
|
||||
"deleted_message": "Aufwand erfolgreich gelöscht | Aufwand erfolgreich gelöscht",
|
||||
"description": "Beschreibung",
|
||||
"download_receipt": "Quittung herunterladen",
|
||||
"edit_expense": "Aufwendung ändern",
|
||||
"expense": "Aufwendung | Aufwendungen",
|
||||
"expense_date": "Datum",
|
||||
"expense_title": "Titel",
|
||||
"expenses_list": "Liste der Ausgaben",
|
||||
"from_date": "Von Datum",
|
||||
"list_of_expenses": "Dieser Abschnitt enthält die Liste der Ausgaben.",
|
||||
"new_expense": "Neue Aufwendung",
|
||||
"no_expenses": "Noch keine Ausgaben!",
|
||||
"note": "Hinweis",
|
||||
"receipt": "Eingang",
|
||||
"save_expense": "Aufwendung speichern",
|
||||
"title": "Aufwendungen/Ausgaben",
|
||||
"to_date": "bis Datum",
|
||||
"update_expense": "Aufwendung aktualisieren",
|
||||
"updated_message": "Aufwand erfolgreich aktualisiert"
|
||||
},
|
||||
"general": {
|
||||
"action_failed": "Aktion fehlgeschlagen",
|
||||
"actions": "Aktionen",
|
||||
"add_new_item": "Artikel hinzufügen",
|
||||
"all": "Alle",
|
||||
"are_you_sure": "Sind Sie sicher?",
|
||||
"back_to_login": "Zurück zum Login?",
|
||||
"bill_to": "Rechnungsempfänger",
|
||||
"bytefury": "Bytefury",
|
||||
"cancel": "Abrechen",
|
||||
"choose": "Wählen",
|
||||
"choose_file": "Klicken Sie hier, um eine Datei auszuwählen",
|
||||
"choose_template": "Wählen Sie eine Vorlage",
|
||||
"clear_all": "Alle entfernen",
|
||||
"delete": "Löschen",
|
||||
"discount": "RABATT",
|
||||
"download": "Download",
|
||||
"download_pdf": "Download PDF",
|
||||
"draft": "Entwurf",
|
||||
"due": "Fällig",
|
||||
"edit": "Ändern",
|
||||
"filter": "Filter",
|
||||
"fixed": "Behoben",
|
||||
"four_zero_four": "Vier hundert vier",
|
||||
"from": "Von",
|
||||
"from_date": "Von Datum",
|
||||
"go_back": "zurück",
|
||||
"go_home": "Geh zurück",
|
||||
"home": "Startseite",
|
||||
"list_is_empty": "Liste ist leer.",
|
||||
"no_tax_found": "Kein Steuersatz gefunden!",
|
||||
"of": "von",
|
||||
"percentage": "Prozentsatz",
|
||||
"powered_by": "Powered by",
|
||||
"remove": "Entfernen",
|
||||
"save": "Speichern",
|
||||
"search": "Suchen",
|
||||
"select_a_status": "Status wählen",
|
||||
"select_a_tax": "Steuersatz wählen",
|
||||
"select_all": "Alle auswählen",
|
||||
"select_city": "Stadt wählen",
|
||||
"select_country": "Land wählen",
|
||||
"select_state": "Bundesland wählen",
|
||||
"sent": "Gesendet",
|
||||
"setting_updated": "Einstellungen erfolgreich aktualisiert",
|
||||
"ship_to": "Versand ein",
|
||||
"showing": "Anzeigen",
|
||||
"street_1": "Straße",
|
||||
"street_2": "Zusatz Strasse",
|
||||
"subtotal": "ZWISCHENSUMME",
|
||||
"tax": "Steuer",
|
||||
"to": "bis",
|
||||
"to_date": "bis Datum",
|
||||
"total_amount": "GESAMTSUMME",
|
||||
"update": "Update",
|
||||
"view": "Anzeigen",
|
||||
"view_pdf": "PDF anzeigen",
|
||||
"you_got_lost": "Hoppla! Du hast dich verirrt!"
|
||||
},
|
||||
"invoices": {
|
||||
"action": "Aktion",
|
||||
"add_item": "Fügen Sie ein Artikel hinzu",
|
||||
"add_new_invoice": "Neue Rechnung hinzufügen",
|
||||
"add_new_tax": "Neuen Steuersatz hinzufügen",
|
||||
"add_tax": "Steuersatz hinzufügen",
|
||||
"all": "Alle",
|
||||
"amount": "Summe",
|
||||
"amount_due": "OFFENER BETRAG",
|
||||
"confirm_delete": "Sie können diese Rechnung nicht wiederherstellen. | Sie können diese Rechnungen nicht wiederherstellen.",
|
||||
"confirm_send": "Diese Rechnung wird per E-Mail an den Kunden gesendet",
|
||||
"confirm_send_invoice": "Diese Rechnung wird per E-Mail an den Kunden gesendet",
|
||||
"contact": "Kontakt",
|
||||
"created_message": "Rechnung erfolgreich erstellt",
|
||||
"customer": "KUNDEN",
|
||||
"date": "Datum",
|
||||
"days": "{days} Tage",
|
||||
"deleted_message": "Rechnung erfolgreich gelöscht | Rechnungen erfolgreich gelöscht",
|
||||
"discount": "Rabatt",
|
||||
"due_date": "Fälligkeit",
|
||||
"edit_invoice": "Rechnung bearbeiten",
|
||||
"invalid_due_amount_message": "Der Gesamtrechnungsbetrag darf nicht kleiner sein als der für diese Rechnung bezahlte Gesamtbetrag. Bitte aktualisieren Sie die Rechnung oder löschen Sie die zugehörigen Zahlungen um fortzufahren.",
|
||||
"invoice": "Rechnung | Rechnungen",
|
||||
"invoice_date": "Rechnungsdatum",
|
||||
"invoice_mark_as_sent": "Diese Rechnung wird als gesendet markiert",
|
||||
"invoice_number": "Rechnungsnummer",
|
||||
"invoice_template": "Rechnungs-Vorlage",
|
||||
"invoices_list": "Liste der Rechnungen",
|
||||
"item": {
|
||||
"amount": "Summe",
|
||||
"description": "Beschreibung",
|
||||
"discount": "Rabatt",
|
||||
"price": "Preis",
|
||||
"quantity": "Menge",
|
||||
"select_an_item": "Geben Sie oder wählen Sie ein Artikel",
|
||||
"sub_total": "Zwischensumme",
|
||||
"tax": "Steuer",
|
||||
"title": "Titel",
|
||||
"total": "Gesamt",
|
||||
"total_discount": "Rabatt Gesamt",
|
||||
"type_item_description": "Artikel Beschreibung (optional)"
|
||||
},
|
||||
"list_of_invoices": "Dieser Abschnitt enthält die Liste der Rechnungen.",
|
||||
"mark_as_sent": "Als gesendet markieren",
|
||||
"mark_as_sent_successfully": "Rechnung gekennzeichnet als erfolgreich gesendet",
|
||||
"marked_as_sent_message": "Rechnung als erfolgreich gesendet markiert",
|
||||
"months": "{months} Monat",
|
||||
"new_invoice": "Neue Rechnung",
|
||||
"no_invoices": "Keine Rechnungen vorhanden!",
|
||||
"no_matching_invoices": "Es gibt keine entsprechenden Rechnungen!",
|
||||
"notes": "Hinweise",
|
||||
"number": "ANZAHL",
|
||||
"paid": "Bezahlt",
|
||||
"paid_status": "BEZAHLT-STATUS",
|
||||
"partially_paid": "Teilzahlung",
|
||||
"payment_attached_message": "Einer der ausgewählten Rechnungen ist bereits eine Zahlung zugeordnet. Stellen Sie sicher, dass Sie zuerst die angehängten Zahlungen löschen, um mit dem Entfernen fortzufahren",
|
||||
"record_payment": "Zahlung erfassen",
|
||||
"ref_no": "REF. - NR.",
|
||||
"ref_number": "Ref-Nummer",
|
||||
"save_invoice": "Rechnung speichern",
|
||||
"select_invoice": "Wählen Sie eine Rechnung",
|
||||
"send_invoice": "Rechnung senden",
|
||||
"send_invoice_successfully": "Rechnung erfolgreich versendet",
|
||||
"something_went_wrong": "Da ist etwas schief gelaufen",
|
||||
"status": "Status",
|
||||
"sub_total": "Zwischensumme",
|
||||
"template": "Vorlage",
|
||||
"title": "Rechnungen",
|
||||
"total": "Gesamt",
|
||||
"unpaid": "Unbezahlte",
|
||||
"update_expense": "Kosten aktualisieren",
|
||||
"update_invoice": "Rechnung ändern",
|
||||
"updated_message": "Rechnung erfolgreich aktualisiert",
|
||||
"user_email_does_not_exist": "Benutzer-E-Mail existiert nicht",
|
||||
"view": "Anzeigen",
|
||||
"years": "{years} Jahre"
|
||||
},
|
||||
"items": {
|
||||
"action": "Aktion",
|
||||
"add_item": "Artikel hinzufügen",
|
||||
"add_new_item": "Neuen Artikel hinzufügen",
|
||||
"added_on": "Hinzugefügt am",
|
||||
"confirm_delete": "Sie können diesen Artikel nicht wiederherstellen | Sie können diese Artikel nicht wiederherstellen",
|
||||
"created_message": "Artikel erfolgreich erstellt",
|
||||
"date_of_creation": "Erstellt am",
|
||||
"deleted_message": "Artikel erfolgreich gelöscht | Artikel erfolgreich gelöscht",
|
||||
"description": "Beschreibung",
|
||||
"edit_item": "Artikel bearbeiten",
|
||||
"item": "Artikel | Artikel",
|
||||
"item_attached_message": "Ein Artikel der bereits verwendet wird kann nicht gelöscht werden",
|
||||
"items_list": "Artikel-Liste",
|
||||
"list_of_items": "Dieser Abschnitt enthält die Liste der Artikel.",
|
||||
"name": "Name",
|
||||
"new_item": "Neuer Artikel",
|
||||
"no_items": "Keine Artikel vorhanden!",
|
||||
"price": "Preis",
|
||||
"save_item": "Artikel speichern",
|
||||
"select_a_unit": "wählen Sie die Einheit",
|
||||
"title": "Artikel",
|
||||
"unit": "Einheit",
|
||||
"update_item": "Artikel ändern",
|
||||
"updated_message": "Artikel erfolgreich aktualisiert"
|
||||
},
|
||||
"layout_login": {
|
||||
"copyright_crater": "Copyright @ Crater - 2019",
|
||||
"crater_help": "Crater helps you track expenses, record payments & generate beautiful",
|
||||
"for_freelancer": "for Freelancers &",
|
||||
"invoices_and_estimates": "invoices & estimates with ability to choose multiple templates.",
|
||||
"small_businesses": "Small Businesses ",
|
||||
"super_simple_invoicing": "Super Simple Invoicing"
|
||||
},
|
||||
"login": {
|
||||
"email": "E-Mail",
|
||||
"enter_email": "Geben Sie Ihre E-Mail ein",
|
||||
"enter_password": "Geben Sie das Passwort ein",
|
||||
"forgot_password": "Passwort vergessen?",
|
||||
"login": "Anmelden",
|
||||
"login_placeholder": "mail@example.com",
|
||||
"or_signIn_with": "oder Anmelden mit",
|
||||
"password": "Passwort",
|
||||
"password_reset_successfully": "Passwort erfolgreich zurückgesetzt",
|
||||
"register": "Registrieren",
|
||||
"reset_password": "Passwort zurücksetzen",
|
||||
"retype_password": "Passwort bestätigen"
|
||||
},
|
||||
"navigation": {
|
||||
"customers": "Kunden",
|
||||
"dashboard": "Übersicht",
|
||||
"estimates": "Kostenvoranschläge",
|
||||
"expenses": "Kosten",
|
||||
"invoices": "Rechnungen",
|
||||
"items": "Artikel",
|
||||
"logout": "Abmelden",
|
||||
"payments": "Zahlungen",
|
||||
"reports": "Berichte",
|
||||
"settings": "Einstellungen"
|
||||
},
|
||||
"payments": {
|
||||
"action": "Aktion",
|
||||
"add_new_payment": "Neue Zahlung hinzufügen",
|
||||
"add_payment": "Zahlung hinzufügen",
|
||||
"amount": "Summe",
|
||||
"confirm_delete": "Sie können diese Zahlung nicht wiederherstellen. | Sie können diese Zahlungen nicht wiederherstellen.",
|
||||
"created_message": "Zahlung erfolgreich erstellt",
|
||||
"customer": "Kunden",
|
||||
"date": "Datum",
|
||||
"deleted_message": "Zahlung erfolgreich gelöscht | Zahlungen erfolgreich gelöscht",
|
||||
"edit_payment": "Zahlung bearbeiten",
|
||||
"invalid_amount_message": "Zahlungsbetrag ist ungültig",
|
||||
"invoice": "Rechnung",
|
||||
"list_of_payments": "Dieser Abschnitt enthält die Liste der Zahlungen.",
|
||||
"new_payment": "Neue Zahlung",
|
||||
"no_payments": "Keine Zahlungen vorhanden!",
|
||||
"note": "Hinweis",
|
||||
"payment": "Zahlung | Zahlungen",
|
||||
"payment_mode": "Zahlungsart",
|
||||
"payment_number": "Zahlungsnummer",
|
||||
"payments_list": "Liste der Zahlungen",
|
||||
"record_payment": "Zahlung eintragen",
|
||||
"save_payment": "Zahlung speichern",
|
||||
"select_payment_mode": "Wählen Sie den Zahlungsmodus",
|
||||
"title": "Zahlungen",
|
||||
"update_payment": "Zahlung ändern",
|
||||
"updated_message": "Zahlung erfolgreich aktualisiert",
|
||||
"view_payment": "Zahlung anzeigen"
|
||||
},
|
||||
"reports": {
|
||||
"download_pdf": "Download PDF",
|
||||
"errors": {
|
||||
"required": "Feld ist erforderlich"
|
||||
},
|
||||
"estimates": {
|
||||
"amount": "Summe",
|
||||
"contact_name": "Ansprechpartner",
|
||||
"due_date": "Fälligkeit",
|
||||
"estimate": "Kostenvoranschlag",
|
||||
"estimate_date": "Datum Kostenvoranschlag",
|
||||
"estimate_number": "Kostenvoranschlag-Nr.",
|
||||
"ref_number": "Ref-Nummer",
|
||||
"status": "Status"
|
||||
},
|
||||
"expenses": {
|
||||
"amount": "Summe",
|
||||
"category": "Kategorie",
|
||||
"date": "Datum",
|
||||
"date_range": "Datumsbereich auswählen",
|
||||
"expenses": "Aufwendungen",
|
||||
"from_date": "Ab Datum",
|
||||
"to_date": "bis Datum"
|
||||
},
|
||||
"from_date": "Ab Datum",
|
||||
"invoices": {
|
||||
"amount": "Summe",
|
||||
"contact_name": "Ansprechpartner",
|
||||
"due_date": "Fälligkeit",
|
||||
"invoice": "Rechnung",
|
||||
"invoice_date": "Rechnungsdatum",
|
||||
"status": "Status"
|
||||
},
|
||||
"paid": "Bezahlt",
|
||||
"profit_loss": {
|
||||
"date_range": "Datumsbereich auswählen",
|
||||
"from_date": "Ab Datum",
|
||||
"profit_loss": "Gewinn & Verlust",
|
||||
"to_date": "bis Datum"
|
||||
},
|
||||
"report": "Bericht | Berichte",
|
||||
"sales": {
|
||||
"date_range": "Datumsbereich auswählen",
|
||||
"from_date": "Ab Datum",
|
||||
"report_type": "Berichtstyp",
|
||||
"sales": "Vertrieb",
|
||||
"to_date": "bis Datum"
|
||||
},
|
||||
"status": "Status",
|
||||
"taxes": {
|
||||
"date_range": "Datumsbereich auswählen",
|
||||
"from_date": "Ab Datum",
|
||||
"taxes": "Steuern",
|
||||
"to_date": "bis Datum"
|
||||
},
|
||||
"title": "Bericht",
|
||||
"to_date": "bis Datum",
|
||||
"unpaid": "Unbezahlt",
|
||||
"update_report": "Bericht aktualisieren",
|
||||
"view_pdf": "PDF anzeigen"
|
||||
},
|
||||
"settings": {
|
||||
"account_settings": {
|
||||
"account_settings": "Konto-Einstellungen",
|
||||
"confirm_password": "Kennwort Bestätigen",
|
||||
"email": "E-Mail",
|
||||
"name": "Name",
|
||||
"password": "Passwort",
|
||||
"profile_picture": "Profil Bild",
|
||||
"save": "Speichern",
|
||||
"section_description": "Sie können Ihren Namen, Ihre E-Mail-Adresse und Ihr Passwort mit dem folgenden Formular aktualisieren.",
|
||||
"updated_message": "Kontoeinstellungen erfolgreich aktualisiert"
|
||||
},
|
||||
"company_info": {
|
||||
"address": "Adresse",
|
||||
"city": "Stadt",
|
||||
"company_info": "Firmeninfo",
|
||||
"company_logo": "Firmenlogo",
|
||||
"company_name": "Name des Unternehmens",
|
||||
"country": "Land",
|
||||
"phone": "Telefon",
|
||||
"save": "Speichern",
|
||||
"section_description": "Informationen zu Ihrem Unternehmen, die auf Rechnungen, Kostenvoranschlägen und anderen von Crater erstellten Dokumenten angezeigt werden.",
|
||||
"state": "Bundesland",
|
||||
"updated_message": "Unternehmensinformationen wurden erfolgreich aktualisiert",
|
||||
"zip": "PLZ"
|
||||
},
|
||||
"currencies": {
|
||||
"action": "Aktion",
|
||||
"add_currency": "Währung einfügen",
|
||||
"code": "Code",
|
||||
"currencies_list": "Währungen Liste",
|
||||
"currency": "Währung | Währungen",
|
||||
"decimal_separator": "Decimal-Separator",
|
||||
"left": "Links",
|
||||
"name": "Name",
|
||||
"position": "Position",
|
||||
"position_of_symbol": "Position des Währungssymbol",
|
||||
"precision": "Präzision",
|
||||
"right": "Rechts",
|
||||
"select_currency": "Währung wählen",
|
||||
"symbol": "Symbol",
|
||||
"thousand_separator": "Tausendertrennzeichen",
|
||||
"title": "Währungen"
|
||||
},
|
||||
"customization": {
|
||||
"addresses": {
|
||||
"address": "Adresse",
|
||||
"address_setting_updated": "Adresse-Einstellung erfolgreich aktualisiert",
|
||||
"address_street_1": "Strasse",
|
||||
"address_street_2": "Zusatz Strasse",
|
||||
"city": "Stadt",
|
||||
"company_address": "Firma Adresse",
|
||||
"company_name": "Name des Unternehmens",
|
||||
"contact": "Kontakt",
|
||||
"country": "Land",
|
||||
"customer_billing_address": "Rechnungsadresse des Kunden",
|
||||
"customer_shipping_address": "Versand-Adresse des Kunden",
|
||||
"display_name": "Anzeigename",
|
||||
"email": "E-Mail",
|
||||
"insert_fields": "Felder einfügen",
|
||||
"name": "Name",
|
||||
"phone": "Telefon",
|
||||
"primary_contact_name": "Ansprechpartner",
|
||||
"section_description": "Sie können die Rechnungsadresse und das Versandadressenformat des Kunden festlegen (nur in PDF angezeigt). ",
|
||||
"state": "Bundesland",
|
||||
"title": "Adressen",
|
||||
"website": "Website",
|
||||
"zip_code": "PLZ"
|
||||
},
|
||||
"customization": "Anpassung",
|
||||
"estimates": {
|
||||
"autogenerate_estimate_number": "Kostenvoranschlagsnummer automatisch generieren",
|
||||
"enter_estimate_prefix": "Geben Sie das Kostenvoranschlag Präfix ein",
|
||||
"estimate_prefix": "Kostenvoranschlag Präfix",
|
||||
"estimate_setting_description": "Deaktivieren Sie diese Option, wenn Sie nicht jedes Mal, wenn Sie einen neue Kostenvoranschlag erstellen, automatisch eine Schätzung generieren möchten.",
|
||||
"estimate_setting_updated": "Einstellungen Kostenvoranschläge erfolgreich aktualisiert",
|
||||
"estimate_settings": "Einstellungen Kostenvoranschlag",
|
||||
"title": "Kostenvoranschläge"
|
||||
},
|
||||
"invoices": {
|
||||
"autogenerate_invoice_number": "Rechnungsnummer automatisch generieren",
|
||||
"enter_invoice_prefix": "Rechnungspräfix eingeben",
|
||||
"invoice_prefix": "Rechnung Präfix",
|
||||
"invoice_setting_description": "Deaktivieren Sie diese Option, wenn Sie Rechnungsnummern nicht jedes Mal automatisch generieren möchten, wenn Sie eine neue Rechnung erstellen.",
|
||||
"invoice_setting_updated": "Rechnungseinstellung erfolgreich aktualisiert",
|
||||
"invoice_settings": "Rechnungseinstellungen",
|
||||
"notes": "Hinweise",
|
||||
"terms_and_conditions": "Allgemeine Geschäftsbedingungen",
|
||||
"title": "Rechnungen"
|
||||
},
|
||||
"payments": {
|
||||
"autogenerate_payment_number": "Zahlungsnummer automatisch generieren",
|
||||
"enter_payment_prefix": "Zahlungspräfix eingeben",
|
||||
"payment_prefix": "Zahlung Präfix",
|
||||
"payment_setting_description": "Deaktivieren Sie diese Option, wenn Sie nicht jedes Mal, wenn Sie eine neue Zahlung erstellen, automatisch Zahlungsnummern generieren möchten.",
|
||||
"payment_setting_updated": "Zahlungseinstellung erfolgreich aktualisiert",
|
||||
"payment_settings": "Zahlung Einstellungen",
|
||||
"title": "Zahlungen"
|
||||
},
|
||||
"save": "Speichern",
|
||||
"updated_message": "Unternehmensinformationen wurden erfolgreich aktualisiert"
|
||||
},
|
||||
"date_format": "Datum-Format",
|
||||
"expense_category": {
|
||||
"action": "Aktion",
|
||||
"add_new_category": "Neue Kategorie hinzufügen",
|
||||
"already_in_use": "Kategorie wird bereits verwendet",
|
||||
"category_description": "Beschreibung",
|
||||
"category_name": "Kategorie Name",
|
||||
"confirm_delete": "Sie können diese Ausgabenkategorie nicht wiederherstellen",
|
||||
"created_message": "Ausgabenkategorie erfolgreich erstellt",
|
||||
"deleted_message": "Ausgabenkategorie erfolgreich gelöscht",
|
||||
"description": "Für das Hinzufügen von Ausgabeneinträgen sind Kategorien erforderlich. Sie können diese Kategorien nach Ihren Wünschen hinzufügen oder entfernen.",
|
||||
"title": "Kategorien Kosten",
|
||||
"updated_message": "Ausgabenkategorie erfolgreich aktualisiert"
|
||||
},
|
||||
"general": "Allgemeine",
|
||||
"language": "Sprache",
|
||||
"mail": {
|
||||
"driver": "E-Mail Treiber",
|
||||
"encryption": "E-Mail-Verschlüsselung",
|
||||
"from_mail": "Von E-Mail-Adresse",
|
||||
"from_name": "Von E-Mail-Namen",
|
||||
"host": "E-Mail Mailserver",
|
||||
"mail_config": "E-Mail-Konfiguration",
|
||||
"mail_config_desc": "Unten finden Sie das Formular zum Konfigurieren des E-Mail-Treibers zum Senden von E-Mails über die App. Sie können auch Drittanbieter wie Sendgrid, SES usw. konfigurieren.",
|
||||
"mailgun_domain": "Domain",
|
||||
"mailgun_endpoint": "Mailgun-Endpunkt",
|
||||
"mailgun_secret": "Mailgun Verschlüsselung",
|
||||
"password": "E-Mail-Kennwort",
|
||||
"port": "E-Mail Port",
|
||||
"secret": "Verschlüsselung",
|
||||
"ses_key": "SES-Taste",
|
||||
"ses_secret": "SES Verschlüsselung",
|
||||
"username": "E-Mail-Benutzername"
|
||||
},
|
||||
"menu_title": {
|
||||
"account_settings": "Konto-Einstellungen",
|
||||
"company_information": "Informationen zum Unternehmen",
|
||||
"customization": "Anpassung",
|
||||
"expense_category": "Ausgabenkategorien",
|
||||
"notifications": "Benachrichtigungen",
|
||||
"preferences": "Einstellungen",
|
||||
"tax_types": "Steuersätze",
|
||||
"update_app": "Update App"
|
||||
},
|
||||
"notification": {
|
||||
"description": "Welche E-Mail-Benachrichtigungen möchten Sie erhalten wenn sich etwas ändert?",
|
||||
"email": "Benachrichtigungen senden an",
|
||||
"email_save_message": "Email erfolgreich gespeichert",
|
||||
"estimate_viewed": "Kostenvoranschlag angesehen",
|
||||
"estimate_viewed_desc": "Wenn Ihr Kunde den gesendeten Kostenvoranschlag anzeigt bekommt.",
|
||||
"invoice_viewed": "Rechnung angezeigt",
|
||||
"invoice_viewed_desc": "Wenn Ihr Kunde die gesendete Rechnung anzeigt bekommt.",
|
||||
"please_enter_email": "Bitte E-Mail eingeben",
|
||||
"save": "Speichern",
|
||||
"title": "Benachrichtigung"
|
||||
},
|
||||
"pdf": {
|
||||
"footer_text": "Fußzeile Text",
|
||||
"pdf_layout": "PDF-Layout",
|
||||
"title": "PDF-Einstellung"
|
||||
},
|
||||
"preferences": {
|
||||
"currency": "Währung",
|
||||
"date_format": "Datum-Format",
|
||||
"discount_per_item": "Rabatt pro Artikel ",
|
||||
"discount_setting": "Einstellung Rabatt",
|
||||
"discount_setting_description": "Aktivieren Sie diese Option, wenn Sie einzelnen Rechnungspositionen einen Rabatt hinzufügen möchten. Standardmäßig wird der Rabatt direkt zur Rechnung hinzugefügt.",
|
||||
"fiscal_year": "Geschäftsjahr",
|
||||
"general_settings": "Standardeinstellungen für das System.",
|
||||
"language": "Sprache",
|
||||
"preference": "Präferenz | Präferenzen",
|
||||
"save": "Speichern",
|
||||
"select_date_formate": "select Date Formate",
|
||||
"select_financial_year": "Geschäftsjahr auswählen",
|
||||
"select_language": "Sprache auswählen",
|
||||
"select_time_zone": "Zeitzone auswählen",
|
||||
"time_zone": "Zeitzone",
|
||||
"updated_message": "Einstellungen erfolgreich aktualisiert"
|
||||
},
|
||||
"primary_currency": "Primäre Währung",
|
||||
"setting": "Einstellung | Einstellungen",
|
||||
"tax_types": {
|
||||
"action": "Aktion",
|
||||
"add_new_tax": "Neuen Steuersatz hinzufügen",
|
||||
"add_tax": "Steuersätze hinzufügen",
|
||||
"already_in_use": "Steuersatz wird bereits verwendet",
|
||||
"compound_tax": "Compound Tax",
|
||||
"confirm_delete": "Sie können diesen Steuersatz nicht wiederherstellen",
|
||||
"created_message": "Steuersatz erfolgreich erstellt",
|
||||
"deleted_message": "Steuersatz erfolgreich gelöscht",
|
||||
"description": "Sie können Steuern nach Belieben hinzufügen oder entfernen. Crater unterstützt Steuern auf einzelne Artikel sowie auf die Rechnung.",
|
||||
"percent": "Prozent",
|
||||
"tax_name": "Name des Steuersatzes",
|
||||
"tax_per_item": "Steuersatz pro Artikel",
|
||||
"tax_setting_description": "Aktivieren Sie diese Option, wenn Sie den Steuersatz zu einzelnen Rechnungspositionen hinzufügen möchten. Standardmäßig wird der Steuersatz direkt zur Rechnung hinzugefügt.",
|
||||
"tax_settings": "Einstellungen Steuersatz",
|
||||
"title": "Steuersätze",
|
||||
"updated_message": "Steuersatz erfolgreich aktualisiert"
|
||||
},
|
||||
"timezone": "Zeitzone",
|
||||
"title": "Einstellungen",
|
||||
"update_app": {
|
||||
"avail_update": "Neues Update verfügbar",
|
||||
"check_update": "Nach Updates suchen",
|
||||
"current_version": "Aktuelle Version",
|
||||
"description": "Sie können Crater ganz einfach aktualisieren, indem Sie auf die Schaltfläche unten klicken, um nach einem neuen Update zu suchen.",
|
||||
"latest_message": "Kein Update verfügbar! Du bist auf der neuesten Version.",
|
||||
"next_version": "Nächste Version",
|
||||
"progress_text": "Es dauert nur ein paar Minuten. Bitte aktualisieren Sie den Bildschirm nicht und schließen Sie das Fenster nicht, bevor das Update abgeschlossen ist.",
|
||||
"title": "Update App",
|
||||
"update": "Jetzt aktualisieren",
|
||||
"update_progress": "Update läuft ...",
|
||||
"update_success": "App wurde aktualisiert! Bitte warten Sie, während Ihr Browserfenster automatisch neu geladen wird."
|
||||
},
|
||||
"user_profile": {
|
||||
"confirm_password": "Kennwort bestätigen",
|
||||
"email": "E-Mail",
|
||||
"name": "Name",
|
||||
"password": "Passwort"
|
||||
}
|
||||
},
|
||||
"tax_types": {
|
||||
"compound_tax": "zusammengesetzte Steuer",
|
||||
"description": "Beschreibung",
|
||||
"name": "Name",
|
||||
"percent": "Prozent"
|
||||
},
|
||||
"validation": {
|
||||
"address_maxlength": "Die Adresse sollte nicht länger als 255 Zeichen sein.",
|
||||
"amount_maxlength": "Der Betrag sollte nicht größer als 20 Ziffern sein.",
|
||||
"amount_minvalue": "Betrag sollte größer als 0 sein.",
|
||||
"characters_only": "Nur Zeichen.",
|
||||
"description_maxlength": "Die Beschreibung sollte nicht länger als 255 Zeichen sein.",
|
||||
"email_already_taken": "Die E-Mail ist bereits vergeben.",
|
||||
"email_does_not_exist": "Benutzer mit der angegebenen E-Mail existiert nicht",
|
||||
"email_incorrect": "Falsche E-Mail.",
|
||||
"item_unit_already_taken": "Die Artikeleinheit wurde bereits vergeben",
|
||||
"payment_mode_already_taken": "Der Zahlungsmodus wurde bereits verwendet",
|
||||
"enter_valid_tax_rate": "Geben Sie einen gültige Steuersatz ein",
|
||||
"invalid_url": "Ungültige URL (Bsp.: http://www.crater.com)",
|
||||
"maximum_options_error": "Maximal {max} Optionen ausgewählt. Entfernen Sie zuerst eine ausgewählte Option, um eine andere auszuwählen.",
|
||||
"name_min_length": "Name muss mindestens {count} Zeichen enthalten.",
|
||||
"not_yet": "Noch erhalten? Erneut senden",
|
||||
"notes_maxlength": "Notizen sollten nicht länger als 255 Zeichen sein.",
|
||||
"numbers_only": "Nur Zahlen.",
|
||||
"password_incorrect": "Passwörter müssen identisch sein",
|
||||
"password_length": "Passwort muss {count} Zeichen lang sein.",
|
||||
"password_min_length": "Password muß {count} Zeichen enthalten",
|
||||
"payment_greater_than_due_amount": "Die eingegebene Zahlung ist mehr als der fällige Betrag dieser Rechnung.",
|
||||
"payment_greater_than_zero": "Die Zahlung muss größer als 0 sein.",
|
||||
"prefix_maxlength": "Das Präfix sollte nicht länger als 5 Zeichen sein.",
|
||||
"price_greater_than_zero": "Preis muss größer als 0 sein.",
|
||||
"price_maxlength": "Der Preis sollte nicht größer als 20 Ziffern sein.",
|
||||
"price_minvalue": "Der Preis sollte größer als 0 sein.",
|
||||
"qty_must_greater_than_zero": "Die Menge muss größer als 0 sein.",
|
||||
"quantity_maxlength": "Die Menge sollte nicht größer als 20 Ziffern sein.",
|
||||
"ref_number_maxlength": "Ref Number sollte nicht länger als 255 Zeichen sein.",
|
||||
"required": "Feld ist erforderlich",
|
||||
"send_reset_link": "Link zum Zurücksetzen senden"
|
||||
},
|
||||
"wizard": {
|
||||
"account_info": "Account-Informationen",
|
||||
"account_info_desc": "Die folgenden Details werden zum Erstellen des Hauptadministratorkontos verwendet. Sie können die Details auch jederzeit nach dem Anmelden ändern.",
|
||||
"address": "Adresse",
|
||||
"city": "Stadt",
|
||||
"company_info": "Unternehmensinformationen",
|
||||
"company_info_desc": "Diese Informationen werden auf Rechnungen angezeigt. Beachten Sie, dass Sie diese später auf der Einstellungsseite bearbeiten können.",
|
||||
"company_logo": "Firmenlogo",
|
||||
"company_name": "Firmenname",
|
||||
"confirm_password": "Passwort bestätigen",
|
||||
"continue": "Weiter",
|
||||
"country": "Land",
|
||||
"currency": "Currency",
|
||||
"database": {
|
||||
"app_url": "App-URL",
|
||||
"connection": "Datenbank Verbindung",
|
||||
"database": "URL der Seite & Datenbank",
|
||||
"db_name": "Datenbank Name",
|
||||
"desc": "Erstellen Sie eine Datenbank auf Ihrem Server und legen Sie die Anmeldeinformationen mithilfe des folgenden Formulars fest.",
|
||||
"host": "Datenbank Host",
|
||||
"password": "Datenbank Passwort",
|
||||
"port": "Datenbank Port",
|
||||
"username": "Datenbank Benutzername"
|
||||
},
|
||||
"date_format": "Datumsformat",
|
||||
"email": "Email",
|
||||
"errors": {
|
||||
"connection_failed": "Datenbankverbindung fehlgeschlagen",
|
||||
"database_should_be_empty": "Datenbank sollte leer sein",
|
||||
"database_variables_save_error": "Konfiguration kann nicht in EN.env-Datei geschrieben werden. Bitte überprüfen Sie die Dateiberechtigungen.",
|
||||
"mail_variables_save_error": "E-Mail-Konfiguration fehlgeschlagen.",
|
||||
"migrate_failed": "Migration ist Fehlgeschlagen"
|
||||
},
|
||||
"fiscal_year": "Geschäftsjahr",
|
||||
"from_address": "From Address",
|
||||
"go_back": "Zurück",
|
||||
"language": "Sprache",
|
||||
"logo_preview": "Vorschau Logo",
|
||||
"mail": {
|
||||
"driver": "E-Mail-Treiber",
|
||||
"encryption": "E-Mail-Verschlüsselung",
|
||||
"from_mail": "Von E-Mail-Absenderadresse",
|
||||
"from_name": "Von E-Mail-Absendername",
|
||||
"host": "E-Mail-Host",
|
||||
"mail_config": "E-Mail-Konfiguration",
|
||||
"mail_config_desc": "Unten finden Sie das Formular zum Konfigurieren des E-Mail-Treibers zum Senden von E-Mails über die App. Sie können auch Drittanbieter wie Sendgrid, SES usw. konfigurieren.",
|
||||
"mailgun_domain": "Domain",
|
||||
"mailgun_endpoint": "Mailgun-Endpunkt",
|
||||
"mailgun_secret": "Mailgun Verschlüsselung",
|
||||
"password": "E-Mail-Passwort",
|
||||
"port": "E-Mail-Port",
|
||||
"secret": "Verschlüsselung",
|
||||
"ses_key": "SES-Taste",
|
||||
"ses_secret": "SES Verschlüsselung",
|
||||
"username": "E-Mail-Benutzername"
|
||||
},
|
||||
"name": "Name",
|
||||
"next": "Next",
|
||||
"password": "Passwort",
|
||||
"permissions": {
|
||||
"permission_confirm_desc": "Prüfung der Berechtigung der Ordner fehlgeschlagen.",
|
||||
"permission_confirm_title": "Sind Sie sicher, dass Sie fortfahren möchten?",
|
||||
"permission_desc": "Unten finden Sie eine Liste der Ordnerberechtigungen, die erforderlich sind, damit die App funktioniert. Wenn die Berechtigungsprüfung fehlschlägt, müssen Sie Ihre Ordnerberechtigungen aktualisieren.",
|
||||
"permissions": "Berechtigungen"
|
||||
},
|
||||
"phone": "Telefon",
|
||||
"preferences": "Einstellungen",
|
||||
"preferences_desc": "Standardeinstellungen für das System.",
|
||||
"req": {
|
||||
"check_req": "Anforderungen prüfen",
|
||||
"php_req_version": "Php (version {version} erforderlich)",
|
||||
"system_req": "System Anforderungen",
|
||||
"system_req_desc": "Crater hat einige Serveranforderungen. Stellen Sie sicher, dass Ihr Server die erforderliche PHP-Version und alle unten genannten Erweiterungen hat."
|
||||
},
|
||||
"save_cont": "Speichern und weiter",
|
||||
"skip": "Überspringen",
|
||||
"state": "Bundesland",
|
||||
"street": "Straße1 | Straße2",
|
||||
"success": {
|
||||
"database_variables_save_successfully": "Datenbank erfolgreich konfiguriert.",
|
||||
"mail_variables_save_successfully": "E-Mail erfolgreich konfiguriert"
|
||||
},
|
||||
"time_zone": "Zeitzone",
|
||||
"username": "Benutzername",
|
||||
"zip_code": "Postleitzahl"
|
||||
}
|
||||
}
|
||||
@@ -17,11 +17,17 @@
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
"update": "Update",
|
||||
"deselect": "Deselect",
|
||||
"download": "Download",
|
||||
"from_date": "From Date",
|
||||
"to_date": "To Date",
|
||||
"from": "From",
|
||||
"to": "To",
|
||||
"sort_by": "Sort By",
|
||||
"ascending": "Ascending",
|
||||
"descending": "Descending",
|
||||
"subject": "Subject",
|
||||
"message": "Message",
|
||||
"go_back": "Go Back",
|
||||
"back_to_login": "Back to Login?",
|
||||
"home": "Home",
|
||||
@@ -62,6 +68,8 @@
|
||||
"four_zero_four": "404",
|
||||
"you_got_lost": "Whoops! You got Lost!",
|
||||
"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",
|
||||
@@ -180,7 +188,7 @@
|
||||
"no_items": "No items yet!",
|
||||
"list_of_items": "This section will contain the list of items.",
|
||||
"select_a_unit": "select unit",
|
||||
|
||||
"taxes": "Taxes",
|
||||
"item_attached_message": "Cannot delete an item which is already in use",
|
||||
"confirm_delete": "You will not be able to recover this Item | You will not be able to recover these Items",
|
||||
"created_message": "Item created successfully",
|
||||
@@ -225,7 +233,7 @@
|
||||
"record_payment": "Record Payment",
|
||||
"add_estimate": "Add Estimate",
|
||||
"save_estimate": "Save Estimate",
|
||||
"confirm_conversion": "You want to convert this Estimate into Invoice?",
|
||||
"confirm_conversion": "This estimate will be used to create a new Invoice.",
|
||||
"conversion_message": "Invoice created successful",
|
||||
"confirm_send_estimate": "This estimate will be sent via email to the customer",
|
||||
"confirm_mark_as_sent": "This estimate will be marked as sent",
|
||||
@@ -329,6 +337,9 @@
|
||||
"no_matching_invoices": "There are no matching invoices!",
|
||||
"mark_as_sent_successfully": "Invoice marked as sent successfully",
|
||||
"send_invoice_successfully": "Invoice sent successfully",
|
||||
"cloned_successfully": "Invoice cloned successfully",
|
||||
"clone_invoice": "Clone Invoice",
|
||||
"confirm_clone": "This invoice will be cloned into a new Invoice",
|
||||
"item": {
|
||||
"title": "Item Title",
|
||||
"description": "Description",
|
||||
@@ -343,7 +354,6 @@
|
||||
"select_an_item": "Type or click to select an item",
|
||||
"type_item_description": "Type Item Description (optional)"
|
||||
},
|
||||
|
||||
"payment_attached_message": "One of the selected invoices already have a payment attached to it. Make sure to delete the attached payments first in order to go ahead with the removal",
|
||||
"confirm_delete": "You will not be able to recover this Invoice | You will not be able to recover these Invoices",
|
||||
"created_message": "Invoice created successfully",
|
||||
@@ -394,12 +404,17 @@
|
||||
"edit_payment": "Edit Payment",
|
||||
"view_payment": "View Payment",
|
||||
"add_new_payment": "Add New Payment",
|
||||
"send_payment_receipt": "Send Payment Receipt",
|
||||
"save_payment": "Save Payment",
|
||||
"update_payment": "Update Payment",
|
||||
"payment": "Payment | Payments",
|
||||
"no_payments": "No payments yet!",
|
||||
"list_of_payments": "This section will contain the list of payments.",
|
||||
"select_payment_mode": "Select payment mode",
|
||||
"confirm_send_payment": "This payment will be sent via email to the customer",
|
||||
"send_payment_successfully": "Payment sent successfully",
|
||||
"user_email_does_not_exist": "User email does not exist",
|
||||
"something_went_wrong": "something went wrong",
|
||||
|
||||
"confirm_delete": "You will not be able to recover this Payment | You will not be able to recover these Payments",
|
||||
"created_message": "Payment created successfully",
|
||||
@@ -633,7 +648,7 @@
|
||||
"notes": "Notes",
|
||||
"invoice_prefix": "Invoice Prefix",
|
||||
"invoice_settings": "Invoice Settings",
|
||||
"autogenerate_invoice_number": "Autogenerate Invoice Number",
|
||||
"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",
|
||||
@@ -644,7 +659,7 @@
|
||||
"title": "Estimates",
|
||||
"estimate_prefix": "Estimate Prefix",
|
||||
"estimate_settings": "Estimate Settings",
|
||||
"autogenerate_estimate_number": "Autogenerate Estimate Number",
|
||||
"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"
|
||||
@@ -654,10 +669,30 @@
|
||||
"title": "Payments",
|
||||
"payment_prefix": "Payment Prefix",
|
||||
"payment_settings": "Payment Settings",
|
||||
"autogenerate_payment_number": "Autogenerate Payment Number",
|
||||
"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_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"
|
||||
}
|
||||
},
|
||||
"account_settings": {
|
||||
@@ -839,7 +874,7 @@
|
||||
}
|
||||
},
|
||||
"layout_login": {
|
||||
"copyright_crater": "Copyright @ Crater - 2019",
|
||||
"copyright_crater": "Copyright @ Crater - 2020",
|
||||
"super_simple_invoicing": "Super Simple Invoicing",
|
||||
"for_freelancer": "for Freelancers &",
|
||||
"small_businesses": "Small Businesses ",
|
||||
@@ -852,6 +887,8 @@
|
||||
"email_incorrect": "Incorrect Email.",
|
||||
"email_already_taken": "The email has already been taken.",
|
||||
"email_does_not_exist": "User with given email doesn't exist",
|
||||
"item_unit_already_taken": "This item unit name has already been taken",
|
||||
"payment_mode_already_taken": "This payment mode name has already been taken",
|
||||
"send_reset_link": "Send Reset Link",
|
||||
"not_yet": "Not yet? Send it again",
|
||||
"password_min_length": "Password must contain {count} characters",
|
||||
@@ -871,10 +908,13 @@
|
||||
"amount_maxlength": "Amount should not be greater than 20 digits.",
|
||||
"amount_minvalue": "Amount should be greater than 0.",
|
||||
"description_maxlength": "Description should not be greater than 255 characters.",
|
||||
"subject_maxlength": "Subject should not be greater than 100 characters.",
|
||||
"message_maxlength": "Message should not be greater than 255 characters.",
|
||||
"maximum_options_error": "Maximum of {max} options selected. First remove a selected option to select another.",
|
||||
"notes_maxlength": "Notes should not be greater than 255 characters.",
|
||||
"address_maxlength": "Address should not be greater than 255 characters.",
|
||||
"ref_number_maxlength": "Ref Number should not be greater than 255 characters.",
|
||||
"prefix_maxlength": "Prefix should not be greater than 5 characters."
|
||||
"prefix_maxlength": "Prefix should not be greater than 5 characters.",
|
||||
"something_went_wrong": "something went wrong"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,44 +14,44 @@
|
||||
"general": {
|
||||
"view_pdf": "Ver PDF",
|
||||
"download_pdf": "Descargar PDF",
|
||||
"save": "Salvar",
|
||||
"save": "Guardar",
|
||||
"cancel": "Cancelar",
|
||||
"update": "Actualizar",
|
||||
"download": "Descargar",
|
||||
"from_date": "Partir de la fecha",
|
||||
"from_date": "Desde la fecha",
|
||||
"to_date": "Hasta la fecha",
|
||||
"from": "De",
|
||||
"to": "A",
|
||||
"go_back": "Regresa",
|
||||
"back_to_login": "¿Atrás para iniciar sesión?",
|
||||
"home": "Casa",
|
||||
"go_back": "Volver",
|
||||
"back_to_login": "¿Volver al inicio de sesión?",
|
||||
"home": "Inicio",
|
||||
"filter": "Filtrar",
|
||||
"delete": "Eliminar",
|
||||
"edit": "Editar",
|
||||
"view": "Ver",
|
||||
"add_new_item": "Agregar ítem nuevo",
|
||||
"clear_all": "Limpiar todo",
|
||||
"showing": "Demostración",
|
||||
"showing": "Mostrando",
|
||||
"of": "de",
|
||||
"actions": "Comportamiento",
|
||||
"subtotal": "TOTAL PARCIAL",
|
||||
"actions": "Acciones",
|
||||
"subtotal": "SUBTOTAL",
|
||||
"discount": "DESCUENTO",
|
||||
"fixed": "Fija",
|
||||
"fixed": "Fijo",
|
||||
"percentage": "Porcentaje",
|
||||
"tax": "IMPUESTO",
|
||||
"total_amount": "CANTIDAD TOTAL",
|
||||
"bill_to": "Cobrar a",
|
||||
"ship_to": "Envie a",
|
||||
"due": "Debida",
|
||||
"draft": "Sequía",
|
||||
"sent": "Expedida",
|
||||
"ship_to": "Enviar a",
|
||||
"due": "Debido",
|
||||
"draft": "Borrador",
|
||||
"sent": "Enviado",
|
||||
"all": "Todas",
|
||||
"select_all": "Seleccionar todo",
|
||||
"choose_file": "Haga clic aquí para elegir un archivo.",
|
||||
"choose_file": "Haga clic aquí para elegir un archivo",
|
||||
"choose_template": "Elige una plantilla",
|
||||
"choose": "Escoger",
|
||||
"remove": "Eliminar",
|
||||
"powered_by": "Energizado por",
|
||||
"powered_by": "Impulsado por",
|
||||
"bytefury": "Bytefury",
|
||||
"select_a_status": "Selecciona un estado",
|
||||
"select_a_tax": "Selecciona un impuesto",
|
||||
@@ -61,20 +61,20 @@
|
||||
"no_tax_found": "¡No se encontraron impuestos!",
|
||||
"four_zero_four": "404",
|
||||
"you_got_lost": "Whoops! ¡Te perdiste!",
|
||||
"go_home": "Vete a casa",
|
||||
"go_home": "Volver al Inicio",
|
||||
|
||||
"setting_updated": "Configuración actualizada con éxito",
|
||||
"select_state": "Seleccione estado",
|
||||
"select_state": "Seleccionar estado",
|
||||
"select_country": "Seleccionar país",
|
||||
"select_city": "Ciudad selecta",
|
||||
"select_city": "Seleccionar ciudad",
|
||||
"street_1": "Calle 1",
|
||||
"street_2": "Calle # 2",
|
||||
"action_failed": "Accion: Fallida"
|
||||
"street_2": "Calle 2",
|
||||
"action_failed": "Accion Fallida"
|
||||
},
|
||||
"dashboard": {
|
||||
"select_year": "Seleccione año",
|
||||
"select_year": "Seleccionar año",
|
||||
"cards": {
|
||||
"due_amount": "Monto adeudado",
|
||||
"due_amount": "Cantidad Debida",
|
||||
"customers": "Clientes",
|
||||
"invoices": "Facturas",
|
||||
"estimates": "Estimadas"
|
||||
@@ -83,7 +83,7 @@
|
||||
"total_sales": "Ventas",
|
||||
"total_receipts": "Ingresos",
|
||||
"total_expense": "Gastos",
|
||||
"net_income": "Lngresos netos",
|
||||
"net_income": "Ingresos netos",
|
||||
"year": "Seleccione año"
|
||||
},
|
||||
"weekly_invoices": {
|
||||
@@ -96,16 +96,16 @@
|
||||
"title": "Facturas adeudadas",
|
||||
"due_on": "Debido a",
|
||||
"customer": "Cliente",
|
||||
"amount_due": "Monto adeudado",
|
||||
"actions": "Comportamiento",
|
||||
"amount_due": "Cantidad Debida",
|
||||
"actions": "Acciones",
|
||||
"view_all": "Ver todo"
|
||||
},
|
||||
"recent_estimate_card": {
|
||||
"title": "Estimaciones recientes",
|
||||
"date": "Fecha",
|
||||
"customer": "Cliente",
|
||||
"amount_due": "Monto adeudado",
|
||||
"actions": "Comportamiento",
|
||||
"amount_due": "Cantidad Debida",
|
||||
"actions": "Acciones",
|
||||
"view_all": "Ver todo"
|
||||
}
|
||||
},
|
||||
@@ -123,16 +123,16 @@
|
||||
"display_name": "Nombre para mostrar",
|
||||
"primary_contact_name": "Nombre de contacto primario",
|
||||
"contact_name": "Nombre de contacto",
|
||||
"amount_due": "Monto adeudado",
|
||||
"amount_due": "Cantidad Debida",
|
||||
"email": "Email",
|
||||
"address": "Habla a",
|
||||
"address": "Dirección",
|
||||
"phone": "Teléfono",
|
||||
"website": "Sitio web",
|
||||
"country": "País",
|
||||
"state": "Estado",
|
||||
"city": "Ciudad",
|
||||
"zip_code": "Código postal",
|
||||
"added_on": "Añadido",
|
||||
"added_on": "Añadido el",
|
||||
"action": "Acción",
|
||||
"password": "Contraseña",
|
||||
"street_number": "Número de calle",
|
||||
@@ -144,19 +144,14 @@
|
||||
"new_customer": "Nuevo cliente",
|
||||
"edit_customer": "Editar cliente",
|
||||
"basic_info": "Información básica",
|
||||
"billing_address": "Dirección de Envio",
|
||||
"billing_address": "Dirección de Facturación",
|
||||
"shipping_address": "Dirección de Envío",
|
||||
"copy_billing_address": "Copia de facturación",
|
||||
"no_customers": "¡Aún no hay clientes!",
|
||||
"no_customers_found": "No se encontraron clientes!",
|
||||
"list_of_customers": "Esta sección contendrá la lista de clientes.",
|
||||
"primary_display_name": "Nombre de visualización principal",
|
||||
"select_state": "Seleccione estado",
|
||||
"select_country": "Seleccionar país",
|
||||
"select_city": "Ciudad selecta",
|
||||
"select_currency": "Seleccione el tipo de moneda",
|
||||
"street_1": "Calle 1",
|
||||
"street_2": "Calle 2",
|
||||
"select_a_customer": "Selecciona un cliente",
|
||||
"type_or_click": "Escriba o haga clic para seleccionar",
|
||||
|
||||
@@ -184,7 +179,7 @@
|
||||
"edit_item": "Editar elemento",
|
||||
"no_items": "¡Aún no hay artículos!",
|
||||
"list_of_items": "Esta sección contendrá la lista de artículos.",
|
||||
"select_a_unit": "seleccione unidad",
|
||||
"select_a_unit": "seleccionar unidad",
|
||||
|
||||
"item_attached_message": "No se puede eliminar un elemento que ya está en uso.",
|
||||
"confirm_delete": "No podrá recuperar este artículo | No podrás recuperar estos elementos",
|
||||
@@ -194,9 +189,9 @@
|
||||
},
|
||||
"estimates": {
|
||||
"title": "Estimadas",
|
||||
"estimate": "Estimación | Estimados",
|
||||
"estimate": "Estimación | Estimaciones",
|
||||
"estimates_list": "Lista de estimaciones",
|
||||
"days": "{días} días",
|
||||
"days": "{días} Días",
|
||||
"months": "{meses} Mes",
|
||||
"years": "{años} Año",
|
||||
"all": "Todas",
|
||||
@@ -236,14 +231,15 @@
|
||||
"confirm_mark_as_sent": "Esta estimación se marcará como enviada",
|
||||
"confirm_mark_as_accepted": "Esta estimación se marcará como Aceptada",
|
||||
"confirm_mark_as_rejected": "Esta estimación se marcará como Rechazada",
|
||||
"no_matching_estimates": "¡No hay estimaciones coincidentes!",
|
||||
"mark_as_sent_successfully": "Estimación marcada como enviada correctamente",
|
||||
"send_estimate_successfully": "Estimación enviada con éxito",
|
||||
"errors": {
|
||||
"required": "Se requiere campo"
|
||||
},
|
||||
"accepted": "Aceptada",
|
||||
"sent": "Expedida",
|
||||
"draft": "Sequía",
|
||||
"sent": "Enviado",
|
||||
"draft": "Borrador",
|
||||
"declined": "Rechazada",
|
||||
"new_estimate": "Nueva estimación",
|
||||
"add_new_estimate": "Añadir nuevo presupuesto",
|
||||
@@ -263,10 +259,12 @@
|
||||
"created_message": "Estimación creada con éxito",
|
||||
"updated_message": "Estimación actualizada con éxito",
|
||||
"deleted_message": "Estimación eliminada con éxito | Estimaciones eliminadas exitosamente",
|
||||
"user_email_does_not_exist": "El email del usuario no existe",
|
||||
"something_went_wrong": "Algo fue mal",
|
||||
"item": {
|
||||
"title": "Título del artículo",
|
||||
"description": "Descripción",
|
||||
"quantity": "Quantity",
|
||||
"quantity": "Cantidad",
|
||||
"price": "Precio",
|
||||
"discount": "Descuento",
|
||||
"total": "Total",
|
||||
@@ -281,7 +279,7 @@
|
||||
"invoices": {
|
||||
"title": "Facturas",
|
||||
"invoices_list": "Lista de facturas",
|
||||
"days": "{días} días",
|
||||
"days": "{días} Días",
|
||||
"months": "{meses} Mes",
|
||||
"years": "{años} Año",
|
||||
"all": "Todas",
|
||||
@@ -309,11 +307,12 @@
|
||||
"action": "Acción",
|
||||
"notes": "Notas",
|
||||
"view": "Ver",
|
||||
"send_invoice": "Enviará la factura",
|
||||
"send_invoice": "Enviar la factura",
|
||||
"invoice_template": "Plantilla de factura",
|
||||
"template": "Modelo",
|
||||
"mark_as_sent": "Marcar como enviado",
|
||||
"invoice_mark_as_sent": "Esta factura se marcará como enviada",
|
||||
"confirm_send_invoice": "Esta factura será enviada por email al cliente",
|
||||
"confirm_send": "Estas facturas se enviarán por correo electrónico al cliente.",
|
||||
"invoice_date": "Fecha de la factura",
|
||||
"record_payment": "Registro de pago",
|
||||
@@ -327,6 +326,7 @@
|
||||
"no_invoices": "¡Aún no hay facturas!",
|
||||
"list_of_invoices": "Esta sección contendrá la lista de facturas.",
|
||||
"select_invoice": "Seleccionar factura",
|
||||
"no_matching_invoices": "There are no matching invoices!",
|
||||
"mark_as_sent_successfully": "Factura marcada como enviada con éxito",
|
||||
"send_invoice_successfully": "Factura enviada exitosamente",
|
||||
"item": {
|
||||
@@ -349,7 +349,9 @@
|
||||
"updated_message": "Factura actualizada exitosamente",
|
||||
"deleted_message": "Factura eliminada con éxito | Facturas borradas exitosamente",
|
||||
"marked_as_sent_message": "Factura marcada como enviada con éxito",
|
||||
"invalid_due_amount_message": "El pago ingresado es mayor que el monto total adeudado por esta factura. Por favor verifique y vuelva a intentar"
|
||||
"user_email_does_not_exist": "El email del usuario no existe",
|
||||
"something_went_wrong": "Algo fue mal",
|
||||
"invalid_due_amount_message": "El pago ingresado es mayor que la cantidad total debida por esta factura. Por favor verificalo y vuelve a intentarlo"
|
||||
},
|
||||
"credit_notes": {
|
||||
"title": "Notas de credito",
|
||||
@@ -410,7 +412,7 @@
|
||||
"expense_title": "Título",
|
||||
"contact": "Contacto",
|
||||
"category": "Categoría",
|
||||
"from_date": "Partir de la fecha",
|
||||
"from_date": "Desde la fecha",
|
||||
"to_date": "Hasta la fecha",
|
||||
"expense_date": "Fecha",
|
||||
"description": "Descripción",
|
||||
@@ -456,9 +458,10 @@
|
||||
"login": "Iniciar sesión",
|
||||
"register": "Registro",
|
||||
"reset_password": "Restablecer la contraseña",
|
||||
"enter_email": "Ingrese correo electrónico",
|
||||
"enter_password": "Introducir la contraseña",
|
||||
"retype_password": "Retype Password",
|
||||
"password_reset_successfully": "Password Reset Successfully",
|
||||
"enter_email": "Escriba el correo electrónico",
|
||||
"enter_password": "Escriba la contraseña",
|
||||
"retype_password": "Reescriba la contraseña",
|
||||
"login_placeholder": "mail@example.com"
|
||||
},
|
||||
"reports": {
|
||||
@@ -526,6 +529,7 @@
|
||||
"menu_title": {
|
||||
"account_settings": "Configuraciones de la cuenta",
|
||||
"company_information": "Información de la empresa",
|
||||
"customization": "Customization",
|
||||
"preferences": "Preferencias",
|
||||
"notifications": "Notificaciones",
|
||||
"tax_types": "Tipos de impuestos",
|
||||
@@ -548,7 +552,7 @@
|
||||
"code": "Código",
|
||||
"symbol": "Símbolo",
|
||||
"precision": "Precisión",
|
||||
"thousand_separator": "Mil separadores",
|
||||
"thousand_separator": "Separador de miles",
|
||||
"decimal_separator": "Separador decimal",
|
||||
"position": "Posición",
|
||||
"position_of_symbol": "Posición del símbolo",
|
||||
@@ -566,7 +570,7 @@
|
||||
"username": "Nombre de usuario de correo",
|
||||
"mailgun_secret": "Mailgun Secreto",
|
||||
"mailgun_domain": "Domino",
|
||||
"mailgun_endpoint": "Mailgun Punto Final",
|
||||
"mailgun_endpoint": "Mailgun endpoint",
|
||||
"ses_secret": "SES Secreto",
|
||||
"ses_key": "SES llave",
|
||||
"from_name": "Del nombre del correo",
|
||||
@@ -582,18 +586,79 @@
|
||||
},
|
||||
"company_info": {
|
||||
"company_info": "Información de la compañía",
|
||||
"company_name": "nombre de empresa",
|
||||
"company_name": "Nombre de Empresa",
|
||||
"company_logo": "Logo de la compañía",
|
||||
"section_description": "Información sobre su empresa que se mostrará en las facturas, estimaciones y otros documentos creados por Crater.",
|
||||
"phone": "Teléfono",
|
||||
"country": "País",
|
||||
"state": "Estado",
|
||||
"city": "Ciudad",
|
||||
"address": "Habla a",
|
||||
"address": "Dirección",
|
||||
"zip": "Código Postal",
|
||||
"save": "Salvar",
|
||||
"save": "Guardar",
|
||||
"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",
|
||||
|
||||
"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 las estimaciones",
|
||||
"estimate_settings": "Ajustes de estimaciones",
|
||||
"autogenerate_estimate_number": "Autogenerar número de estimacion",
|
||||
"estimate_setting_description": "Desactive esto, si no desea generar automáticamente números de estimaciones cada vez que cree una nueva estimación.",
|
||||
"enter_estimate_prefix": "Introduzca el prefijo de estimación",
|
||||
"estimate_setting_updated": "Configuración de estimaciones 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",
|
||||
"name": "Nombre",
|
||||
@@ -601,7 +666,7 @@
|
||||
"password": "Contraseña",
|
||||
"confirm_password": "Confirmar contraseña",
|
||||
"account_settings": "Configuraciones de la cuenta",
|
||||
"save": "Salvar",
|
||||
"save": "Guardar",
|
||||
"section_description": "Puede actualizar su nombre, correo electrónico y contraseña utilizando el siguiente formulario.",
|
||||
"updated_message": "Configuración de la cuenta actualizada correctamente"
|
||||
},
|
||||
@@ -619,7 +684,7 @@
|
||||
"invoice_viewed_desc": "Cuando su cliente ve la factura enviada a través del panel de control del cráter.",
|
||||
"estimate_viewed": "Estimación vista",
|
||||
"estimate_viewed_desc": "Cuando su cliente ve la estimación enviada a través del panel de control del cráter.",
|
||||
"save": "Salvar",
|
||||
"save": "Guardar",
|
||||
"email_save_message": "Correo electrónico guardado con éxito",
|
||||
"please_enter_email": "Por favor, introduzca su correo electrónico"
|
||||
},
|
||||
@@ -663,7 +728,7 @@
|
||||
"discount_setting": "Ajuste de descuento",
|
||||
"discount_per_item": "Descuento por artículo",
|
||||
"discount_setting_description": "Habilítelo si desea agregar Descuento a artículos de factura individuales. Por defecto, los descuentos se agregan directamente a la factura.",
|
||||
"save": "Salvar",
|
||||
"save": "Guardar",
|
||||
"preference": "Preferencia | Preferencias",
|
||||
"general_settings": "Preferencias predeterminadas para el sistema.",
|
||||
"updated_message": "Preferencias actualizadas exitosamente",
|
||||
@@ -704,8 +769,8 @@
|
||||
"country": "País",
|
||||
"state": "Estado",
|
||||
"city": "Ciudad",
|
||||
"address": "Habla a",
|
||||
"street": "Calle1 | Calle # 2",
|
||||
"address": "Dirección",
|
||||
"street": "Calle1 | Calle2",
|
||||
"phone": "Teléfono",
|
||||
"zip_code": "Código postal",
|
||||
"go_back": "Regresa",
|
||||
@@ -714,10 +779,11 @@
|
||||
"time_zone": "Zona horaria",
|
||||
"fiscal_year": "Año financiero",
|
||||
"date_format": "Formato de fecha",
|
||||
"from_address": "De la Dirección",
|
||||
"from_address": "Desde la Dirección",
|
||||
"username": "Nombre de usuario",
|
||||
"next": "Próximo",
|
||||
"continue": "Hacer continuación",
|
||||
"next": "Siguiente",
|
||||
"continue": "Continuar",
|
||||
"skip": "Saltar",
|
||||
"database": {
|
||||
"database": "URL del sitio y base de datose",
|
||||
"connection": "Conexión de base de datos",
|
||||
@@ -740,16 +806,16 @@
|
||||
"port": "Puerto de correo",
|
||||
"driver": "Conductor de correo",
|
||||
"secret": "Secreto",
|
||||
"password": "Contraseña de correo",
|
||||
"username": "Nombre de usuario de correo",
|
||||
"mailgun_secret": "Mailgun Secreto",
|
||||
"mailgun_domain": "Domino",
|
||||
"mailgun_endpoint": "Mailgun Punto Final",
|
||||
"mailgun_endpoint": "Mailgun endpoint",
|
||||
"password": "Contraseña de correo",
|
||||
"username": "Nombre de usuario de correo",
|
||||
"ses_secret": "SES Secreto",
|
||||
"ses_key": "SES llave",
|
||||
"mail_config": "Configuración de correo",
|
||||
"from_name": "Del nombre del correo",
|
||||
"from_mail": "Desde la dirección de correo",
|
||||
"mail_config": "Configuración de correo",
|
||||
"encryption": "Cifrado de correo",
|
||||
"mail_config_desc": "Los detalles a continuación se utilizarán para actualizar el entorno de correo. También puede cambiar los detalles en cualquier momento después de iniciar sesión."
|
||||
},
|
||||
@@ -763,7 +829,8 @@
|
||||
"migrate_failed": "La migración falló",
|
||||
"database_variables_save_error": "No se puede conectar a la base de datos con los valores proporcionados.",
|
||||
"mail_variables_save_error": "La configuración del correo electrónico ha fallado.",
|
||||
"connection_failed": "Conexión de base de datos fallida"
|
||||
"connection_failed": "Conexión de base de datos fallida",
|
||||
"database_should_be_empty": "Database should be empty"
|
||||
},
|
||||
"success": {
|
||||
"mail_variables_save_successfully": "Correo electrónico configurado correctamente",
|
||||
@@ -771,32 +838,33 @@
|
||||
}
|
||||
},
|
||||
"layout_login": {
|
||||
"copyright_crater": "Copyright @ Crater - 2019",
|
||||
"copyright_crater": "Copyright @ Crater - 2020",
|
||||
"super_simple_invoicing": "Facturación super simple",
|
||||
"for_freelancer": "para autónomos y",
|
||||
"small_businesses": "Pequeñas empresas",
|
||||
"crater_help": "Crater te ayuda a rastrear gastos, registrar pagos y generar hermosos",
|
||||
"small_businesses": "pequeñas empresas",
|
||||
"crater_help": "Crater te ayuda a rastrear gastos, registrar pagos y generar hermosas",
|
||||
"invoices_and_estimates": "facturas y presupuestos con capacidad para elegir múltiples plantillas."
|
||||
|
||||
},
|
||||
"validation": {
|
||||
"invalid_url": "URL no válida (por ejemplo, http://www.crater.com)",
|
||||
"required": "Se requiere campo",
|
||||
"email_incorrect": "Email incorrecto.",
|
||||
"email_does_not_exist": " Usuario con correo electrónico dado no existe",
|
||||
"send_reset_link": "Enviar restablecer enlace",
|
||||
"email_already_taken": "Este email ya esta en uso",
|
||||
"email_does_not_exist": "El usuario con correo electrónico dado no existe",
|
||||
"send_reset_link": "Enviar enlace de restablecimiento",
|
||||
"payment_mode_already_taken": "El modo de pago ya ha sido tomado",
|
||||
"not_yet": "¿Aún no? Envialo de nuevo",
|
||||
"password_min_length": "La contraseña debe contener {count} caracteres",
|
||||
"name_min_length": "El nombre debe tener al menos {count} letras.",
|
||||
"enter_valid_tax_rate": "Ingrese una tasa impositiva válida",
|
||||
"numbers_only": "Solo numeros.",
|
||||
"characters_only": "Solo personajes.",
|
||||
"characters_only": "Solo caracteres.",
|
||||
"password_incorrect": "Las contraseñas deben ser idénticas",
|
||||
"password_length": "La contraseña debe tener 5 caracteres de longitud.",
|
||||
"qty_must_greater_than_zero": "La cantidad debe ser mayor que cero.",
|
||||
"price_greater_than_zero": "El precio debe ser mayor que cero.",
|
||||
"payment_greater_than_zero": "El pago debe ser mayor que cero.",
|
||||
"payment_greater_than_due_amount": "El pago ingresado es mayor al monto adeudado de esta factura.",
|
||||
"payment_greater_than_due_amount": "El pago ingresado es mayor a la cantidad debida de esta factura.",
|
||||
"quantity_maxlength": "La cantidad no debe ser mayor de 20 dígitos.",
|
||||
"price_maxlength": "El precio no debe ser mayor de 20 dígitos.",
|
||||
"price_minvalue": "El precio debe ser mayor que 0 dígitos",
|
||||
@@ -806,6 +874,7 @@
|
||||
"maximum_options_error": "Máximo de {max} opciones seleccionadas. Primero elimine una opción seleccionada para seleccionar otra.",
|
||||
"notes_maxlength": "Las notas no deben tener más de 255 caracteres.",
|
||||
"address_maxlength": "La dirección no debe tener más de 255 caracteres.",
|
||||
"ref_number_maxlength": "El número de referencia no debe tener más de 255 caracteres."
|
||||
"ref_number_maxlength": "El número de referencia no debe tener más de 255 caracteres.",
|
||||
"prefix_maxlength": "El prefijo no debe tener mas de 5 caracteres."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -774,7 +774,7 @@
|
||||
}
|
||||
},
|
||||
"layout_login": {
|
||||
"copyright_crater": "Copyright @ Crater - 2019",
|
||||
"copyright_crater": "Copyright @ Crater - 2020",
|
||||
"super_simple_invoicing": "Super Simple Facturation",
|
||||
"for_freelancer": "pour les pigistes et",
|
||||
"small_businesses": "Petites entreprises ",
|
||||
@@ -787,6 +787,8 @@
|
||||
"required": "Champ requis",
|
||||
"email_incorrect": "Adresse Email incorrecte.",
|
||||
"email_does_not_exist": "L'utilisateur avec un email donné n'existe pas",
|
||||
"item_unit_already_taken": "L'unité d'article a déjà été prise",
|
||||
"payment_mode_already_taken": "Le mode de paiement a déjà été pris",
|
||||
"send_reset_link": "Envoyer le lien de réinitialisation",
|
||||
"not_yet": "Pas encore? Envoyer à nouveau",
|
||||
"password_min_length": "Le mot de passe doit contenir {nombre} caractères",
|
||||
|
||||
@@ -4,6 +4,7 @@ import en from './en.json'
|
||||
import fr from './fr.json'
|
||||
import es from './es.json'
|
||||
import ar from './ar.json'
|
||||
import de from './de.json'
|
||||
import pt_BR from './pt-br.json'
|
||||
|
||||
Vue.use(VueI18n)
|
||||
@@ -15,6 +16,7 @@ const i18n = new VueI18n({
|
||||
fr,
|
||||
es,
|
||||
ar,
|
||||
de,
|
||||
pt_BR
|
||||
}
|
||||
})
|
||||
|
||||
@@ -839,7 +839,7 @@
|
||||
}
|
||||
},
|
||||
"layout_login": {
|
||||
"copyright_crater": "Copyright @ Crater - 2019",
|
||||
"copyright_crater": "Copyright @ Crater - 2020",
|
||||
"super_simple_invoicing": "Faturamento super simples",
|
||||
"for_freelancer": "Para Freelancers &",
|
||||
"small_businesses": "Pequenos Negócios ",
|
||||
|
||||
@@ -46,6 +46,7 @@ import InvoiceView from './views/invoices/View.vue'
|
||||
// Payments
|
||||
import PaymentsIndex from './views/payments/Index.vue'
|
||||
import PaymentCreate from './views/payments/Create.vue'
|
||||
import PaymentView from './views/payments/View.vue'
|
||||
|
||||
// Estimates
|
||||
import EstimateIndex from './views/estimates/Index.vue'
|
||||
@@ -259,6 +260,11 @@ const routes = [
|
||||
name: 'payments.edit',
|
||||
component: PaymentCreate
|
||||
},
|
||||
{
|
||||
path: 'payments/:id/view',
|
||||
name: 'payments.view',
|
||||
component: PaymentView
|
||||
},
|
||||
|
||||
// Expenses
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@ import * as userTypes from './modules/user/mutation-types'
|
||||
import * as companyTypes from './modules/company/mutation-types'
|
||||
import * as preferencesTypes from './modules/settings/preferences/mutation-types'
|
||||
import * as taxTypeTypes from './modules/tax-type/mutation-types'
|
||||
import * as itemTypes from './modules/item/mutation-types'
|
||||
import * as paymentModes from './modules/payment/mutation-types'
|
||||
|
||||
export default {
|
||||
bootstrap ({ commit, dispatch, state }) {
|
||||
@@ -17,6 +19,8 @@ export default {
|
||||
commit('taxType/' + taxTypeTypes.BOOTSTRAP_TAX_TYPES, response.data.taxTypes)
|
||||
commit('preferences/' + preferencesTypes.SET_MOMENT_DATE_FORMAT, response.data.moment_date_format)
|
||||
commit('preferences/' + preferencesTypes.SET_LANGUAGE_FORMAT, response.data.default_language)
|
||||
commit('item/' + itemTypes.SET_ITEM_UNITS, response.data.units)
|
||||
commit('payment/' + paymentModes.SET_PAYMENT_MODES, response.data.paymentMethods)
|
||||
commit(types.UPDATE_APP_LOADING_STATUS, true)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as types from './mutation-types'
|
||||
|
||||
export const fetchCategories = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/categories/`).then((response) => {
|
||||
window.axios.get(`/api/categories`).then((response) => {
|
||||
commit(types.SET_CATEGORIES, response.data)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
|
||||
@@ -135,6 +135,16 @@ export const markAsSent = ({ commit, dispatch, state }, data) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const cloneInvoice = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.post(`/api/invoices/clone`, data).then((response) => {
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const searchInvoice = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/invoices?${data}`).then((response) => {
|
||||
|
||||
@@ -26,7 +26,6 @@ export const addItem = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.post('/api/items', data).then((response) => {
|
||||
commit(types.ADD_ITEM, response.data)
|
||||
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
@@ -90,3 +89,57 @@ export const selectItem = ({ commit, dispatch, state }, data) => {
|
||||
commit(types.SET_SELECT_ALL_STATE, false)
|
||||
}
|
||||
}
|
||||
|
||||
export const addItemUnit = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.post(`/api/units`, data).then((response) => {
|
||||
commit(types.ADD_ITEM_UNIT, response.data)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const updateItemUnit = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.put(`/api/units/${data.id}`, data).then((response) => {
|
||||
commit(types.UPDATE_ITEM_UNIT, response.data)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchItemUnits = ({ commit, dispatch, state }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/units`).then((response) => {
|
||||
commit(types.SET_ITEM_UNITS, response.data.units)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const fatchItemUnit = ({ commit, dispatch, state }, id) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/units/${id}`).then((response) => {
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteItemUnit = ({ commit, dispatch, state }, id) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.delete(`/api/units/${id}`).then((response) => {
|
||||
commit(types.DELETE_ITEM_UNIT, id)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@ export const items = (state) => state.items
|
||||
export const selectAllField = (state) => state.selectAllField
|
||||
export const selectedItems = (state) => state.selectedItems
|
||||
export const totalItems = (state) => state.totalItems
|
||||
export const itemUnits = (state) => state.itemUnits
|
||||
|
||||
@@ -6,7 +6,8 @@ const initialState = {
|
||||
items: [],
|
||||
totalItems: 0,
|
||||
selectAllField: false,
|
||||
selectedItems: []
|
||||
selectedItems: [],
|
||||
itemUnits: []
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -6,3 +6,7 @@ export const DELETE_MULTIPLE_ITEMS = 'DELETE_MULTIPLE_ITEMS'
|
||||
export const SET_SELECTED_ITEMS = 'SET_SELECTED_ITEMS'
|
||||
export const SET_TOTAL_ITEMS = 'SET_TOTAL_ITEMS'
|
||||
export const SET_SELECT_ALL_STATE = 'SET_SELECT_ALL_STATE'
|
||||
export const ADD_ITEM_UNIT = 'ADD_ITEM_UNIT'
|
||||
export const SET_ITEM_UNITS = 'SET_ITEM_UNITS'
|
||||
export const UPDATE_ITEM_UNIT = 'UPDATE_ITEM_UNIT'
|
||||
export const DELETE_ITEM_UNIT = 'DELETE_ITEM_UNIT'
|
||||
|
||||
@@ -39,6 +39,25 @@ export default {
|
||||
|
||||
[types.SET_SELECT_ALL_STATE] (state, data) {
|
||||
state.selectAllField = data
|
||||
}
|
||||
},
|
||||
|
||||
[types.ADD_ITEM_UNIT] (state, data) {
|
||||
state.itemUnits.push(data.unit)
|
||||
state.itemUnits = [data.unit, ...state.itemUnits]
|
||||
},
|
||||
|
||||
[types.SET_ITEM_UNITS] (state, data) {
|
||||
state.itemUnits = data
|
||||
},
|
||||
|
||||
[types.DELETE_ITEM_UNIT] (state, id) {
|
||||
let index = state.itemUnits.findIndex(unit => unit.id === id)
|
||||
state.itemUnits.splice(index, 1)
|
||||
},
|
||||
|
||||
[types.UPDATE_ITEM_UNIT] (state, data) {
|
||||
let pos = state.itemUnits.findIndex(unit => unit.id === data.unit.id)
|
||||
state.itemUnits.splice(pos, 1)
|
||||
state.itemUnits = [data.unit, ...state.itemUnits]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ export const fetchPayments = ({ commit, dispatch, state }, params) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchCreatePayment = ({ commit, dispatch }, page) => {
|
||||
export const fetchPayment = ({ commit, dispatch }, id) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/payments/create`).then((response) => {
|
||||
window.axios.get(`/api/payments/${id}`).then((response) => {
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
@@ -22,7 +22,7 @@ export const fetchCreatePayment = ({ commit, dispatch }, page) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchPayment = ({ commit, dispatch }, id) => {
|
||||
export const fetchEditPaymentData = ({ commit, dispatch }, id) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/payments/${id}/edit`).then((response) => {
|
||||
resolve(response)
|
||||
@@ -32,6 +32,16 @@ export const fetchPayment = ({ commit, dispatch }, id) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchCreatePayment = ({ commit, dispatch }, page) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/payments/create`).then((response) => {
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const addPayment = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.post('/api/payments', data).then((response) => {
|
||||
@@ -97,3 +107,78 @@ export const selectAllPayments = ({ commit, dispatch, state }) => {
|
||||
commit(types.SET_SELECT_ALL_STATE, true)
|
||||
}
|
||||
}
|
||||
|
||||
export const addPaymentMode = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.post(`/api/payment-methods`, data).then((response) => {
|
||||
commit(types.ADD_PAYMENT_MODE, response.data)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const updatePaymentMode = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.put(`/api/payment-methods/${data.id}`, data).then((response) => {
|
||||
commit(types.UPDATE_PAYMENT_MODE, response.data)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchPaymentModes = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/payment-methods`, data).then((response) => {
|
||||
commit(types.SET_PAYMENT_MODES, response.data.paymentMethods)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchPaymentMode = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/payment-methods/${data.id}`, data).then((response) => {
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const deletePaymentMode = ({ commit, dispatch, state }, id) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.delete(`/api/payment-methods/${id}`).then((response) => {
|
||||
commit(types.DELETE_PAYMENT_MODE, id)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const sendEmail = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.post(`/api/payments/send`, data).then((response) => {
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const searchPayment = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.axios.get(`/api/payments?${data}`).then((response) => {
|
||||
// commit(types.UPDATE_INVOICE, response.data)
|
||||
resolve(response)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@ export const payments = (state) => state.payments
|
||||
export const selectedPayments = (state) => state.selectedPayments
|
||||
export const selectAllField = (state) => state.selectAllField
|
||||
export const totalPayments = (state) => state.totalPayments
|
||||
export const paymentModes = (state) => state.paymentModes
|
||||
|
||||
@@ -6,7 +6,8 @@ const initialState = {
|
||||
payments: [],
|
||||
totalPayments: 0,
|
||||
selectAllField: false,
|
||||
selectedPayments: []
|
||||
selectedPayments: [],
|
||||
paymentModes: []
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -6,3 +6,7 @@ export const DELETE_MULTIPLE_PAYMENTS = 'DELETE_MULTIPLE_PAYMENTS'
|
||||
export const SET_SELECTED_PAYMENTS = 'SET_SELECTED_PAYMENTS'
|
||||
export const SET_TOTAL_PAYMENTS = 'SET_TOTAL_PAYMENTS'
|
||||
export const SET_SELECT_ALL_STATE = 'SET_SELECT_ALL_STATE'
|
||||
export const ADD_PAYMENT_MODE = 'ADD_PAYMENT_MODE'
|
||||
export const DELETE_PAYMENT_MODE = 'DELETE_PAYMENT_MODE'
|
||||
export const SET_PAYMENT_MODES = 'SET_PAYMENT_MODES'
|
||||
export const UPDATE_PAYMENT_MODE = 'UPDATE_PAYMENT_MODE'
|
||||
|
||||
@@ -33,5 +33,25 @@ export default {
|
||||
|
||||
[types.SET_SELECT_ALL_STATE] (state, data) {
|
||||
state.selectAllField = data
|
||||
},
|
||||
|
||||
[types.SET_PAYMENT_MODES] (state, data) {
|
||||
state.paymentModes = data
|
||||
},
|
||||
|
||||
[types.ADD_PAYMENT_MODE] (state, data) {
|
||||
state.paymentModes.push(data.paymentMethod)
|
||||
state.paymentModes = [data.paymentMethod, ...state.paymentModes]
|
||||
},
|
||||
|
||||
[types.DELETE_PAYMENT_MODE] (state, id) {
|
||||
let index = state.paymentModes.findIndex(paymentMethod => paymentMethod.id === id)
|
||||
state.paymentModes.splice(index, 1)
|
||||
},
|
||||
|
||||
[types.UPDATE_PAYMENT_MODE] (state, data) {
|
||||
let pos = state.paymentModes.findIndex(paymentMethod => paymentMethod.id === data.paymentMethod.id)
|
||||
state.paymentModes.splice(pos, 1)
|
||||
state.paymentModes = [data.paymentMethod, ...state.paymentModes]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,8 @@
|
||||
</div>
|
||||
<div class="customer-content mb-1">
|
||||
<label class="email">{{ selectedCustomer.name }}</label>
|
||||
<label class="action" @click="removeCustomer">{{ $t('general.remove') }}</label>
|
||||
<label class="action" @click="editCustomer">{{ $t('general.edit') }}</label>
|
||||
<label class="action" @click="removeCustomer">{{ $t('general.deselect') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -195,6 +196,7 @@
|
||||
:index="index"
|
||||
:item-data="item"
|
||||
:currency="currency"
|
||||
:estimate-items="newEstimate.items"
|
||||
:tax-per-item="taxPerItem"
|
||||
:discount-per-item="discountPerItem"
|
||||
@remove="removeItem"
|
||||
@@ -589,6 +591,14 @@ export default {
|
||||
removeCustomer () {
|
||||
this.resetSelectedCustomer()
|
||||
},
|
||||
editCustomer () {
|
||||
this.openModal({
|
||||
'title': this.$t('customers.edit_customer'),
|
||||
'componentName': 'CustomerModal',
|
||||
'id': this.selectedCustomer.id,
|
||||
'data': this.selectedCustomer
|
||||
})
|
||||
},
|
||||
openTemplateModal () {
|
||||
this.openModal({
|
||||
'title': this.$t('general.choose_template'),
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
:invalid="$v.item.name.$error"
|
||||
:invalid-description="$v.item.description.$error"
|
||||
:item="item"
|
||||
:tax-per-item="taxPerItem"
|
||||
:taxes="item.taxes"
|
||||
@search="searchVal"
|
||||
@select="onSelectItem"
|
||||
@deselect="deselectItem"
|
||||
@@ -108,7 +110,7 @@
|
||||
|
||||
<div class="remove-icon-wrapper">
|
||||
<font-awesome-icon
|
||||
v-if="index > 0"
|
||||
v-if="isShowRemoveItemIcon"
|
||||
class="remove-icon"
|
||||
icon="trash-alt"
|
||||
@click="removeItem"
|
||||
@@ -180,6 +182,10 @@ export default {
|
||||
discountPerItem: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
estimateItems: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -221,6 +227,12 @@ export default {
|
||||
return this.defaultCurrencyForInput
|
||||
}
|
||||
},
|
||||
isShowRemoveItemIcon () {
|
||||
if (this.estimateItems.length == 1) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
subtotal () {
|
||||
return this.item.price * this.item.quantity
|
||||
},
|
||||
@@ -324,6 +336,9 @@ export default {
|
||||
created () {
|
||||
window.hub.$on('checkItems', this.validateItem)
|
||||
window.hub.$on('newItem', (val) => {
|
||||
if (this.taxPerItem === 'YES') {
|
||||
this.item.taxes = val.taxes
|
||||
}
|
||||
if (!this.item.item_id && this.modalActive && this.isSelected) {
|
||||
this.onSelectItem(val)
|
||||
}
|
||||
@@ -363,7 +378,13 @@ export default {
|
||||
this.item.price = item.price
|
||||
this.item.item_id = item.id
|
||||
this.item.description = item.description
|
||||
|
||||
if (this.taxPerItem === 'YES' && item.taxes) {
|
||||
let index = 0
|
||||
item.taxes.forEach(tax => {
|
||||
this.updateTax({index, item: { ...tax }})
|
||||
index++
|
||||
})
|
||||
}
|
||||
// if (this.item.taxes.length) {
|
||||
// this.item.taxes = {...item.taxes}
|
||||
// }
|
||||
|
||||
@@ -68,6 +68,14 @@ export default {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
taxPerItem: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
taxes: {
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -129,7 +137,8 @@ export default {
|
||||
this.$emit('onSelectItem')
|
||||
this.openModal({
|
||||
'title': 'Add Item',
|
||||
'componentName': 'ItemModal'
|
||||
'componentName': 'ItemModal',
|
||||
'data': {taxPerItem: this.taxPerItem, taxes: this.taxes}
|
||||
})
|
||||
},
|
||||
deselectItem () {
|
||||
|
||||
@@ -69,7 +69,9 @@
|
||||
<font-awesome-icon icon="filter" />
|
||||
</base-button>
|
||||
</a>
|
||||
|
||||
<div class="filter-title">
|
||||
{{ $t('general.sort_by') }}
|
||||
</div>
|
||||
<div class="filter-items">
|
||||
<input
|
||||
id="filter_estimate_date"
|
||||
@@ -107,7 +109,7 @@
|
||||
<label class="inv-label" for="filter_estimate_number">{{ $t('estimates.estimate_number') }}</label>
|
||||
</div>
|
||||
</v-dropdown>
|
||||
<base-button 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>
|
||||
@@ -172,7 +174,12 @@ export default {
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
getOrderName () {
|
||||
if (this.getOrderBy) {
|
||||
return this.$t('general.ascending')
|
||||
}
|
||||
return this.$t('general.descending')
|
||||
},
|
||||
shareableLink () {
|
||||
return `/estimates/pdf/${this.estimate.unique_hash}`
|
||||
}
|
||||
|
||||
@@ -83,7 +83,8 @@
|
||||
</div>
|
||||
<div class="customer-content mb-1">
|
||||
<label class="email">{{ selectedCustomer.name }}</label>
|
||||
<label class="action" @click="removeCustomer">{{ $t('general.remove') }}</label>
|
||||
<label class="action" @click="editCustomer">{{ $t('general.edit') }}</label>
|
||||
<label class="action" @click="removeCustomer">{{ $t('general.deselect') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -193,6 +194,7 @@
|
||||
:key="item.id"
|
||||
:index="index"
|
||||
:item-data="item"
|
||||
:invoice-items="newInvoice.items"
|
||||
:currency="currency"
|
||||
:tax-per-item="taxPerItem"
|
||||
:discount-per-item="discountPerItem"
|
||||
@@ -589,6 +591,14 @@ export default {
|
||||
removeCustomer () {
|
||||
this.resetSelectedCustomer()
|
||||
},
|
||||
editCustomer () {
|
||||
this.openModal({
|
||||
'title': this.$t('customers.edit_customer'),
|
||||
'componentName': 'CustomerModal',
|
||||
'id': this.selectedCustomer.id,
|
||||
'data': this.selectedCustomer
|
||||
})
|
||||
},
|
||||
openTemplateModal () {
|
||||
this.openModal({
|
||||
'title': this.$t('general.choose_template'),
|
||||
|
||||
@@ -259,6 +259,18 @@
|
||||
{{ $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"/>
|
||||
{{ $t('payments.record_payment') }}
|
||||
</router-link>
|
||||
</v-dropdown-item>
|
||||
<v-dropdown-item>
|
||||
<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" />
|
||||
@@ -378,7 +390,8 @@ export default {
|
||||
'deleteMultipleInvoices',
|
||||
'sendEmail',
|
||||
'markAsSent',
|
||||
'setSelectAllState'
|
||||
'setSelectAllState',
|
||||
'cloneInvoice'
|
||||
]),
|
||||
...mapActions('customer', [
|
||||
'fetchCustomers'
|
||||
@@ -429,6 +442,27 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
async onCloneInvoice (id) {
|
||||
swal({
|
||||
title: this.$t('general.are_you_sure'),
|
||||
text: this.$t('invoices.confirm_clone'),
|
||||
icon: '/assets/icon/check-circle-solid.svg',
|
||||
buttons: true,
|
||||
dangerMode: true
|
||||
}).then(async (value) => {
|
||||
if (value) {
|
||||
const data = {
|
||||
id: id
|
||||
}
|
||||
let response = await this.cloneInvoice(data)
|
||||
this.refreshTable()
|
||||
if (response.data) {
|
||||
window.toastr['success'](this.$tc('invoices.cloned_successfully'))
|
||||
this.$router.push(`/admin/invoices/${response.data.invoice.id}/edit`)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
getStatus (val) {
|
||||
this.filters.status = {
|
||||
name: val,
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
:invalid="$v.item.name.$error"
|
||||
:invalid-description="$v.item.description.$error"
|
||||
:item="item"
|
||||
:tax-per-item="taxPerItem"
|
||||
:taxes="item.taxes"
|
||||
@search="searchVal"
|
||||
@select="onSelectItem"
|
||||
@deselect="deselectItem"
|
||||
@@ -109,7 +111,7 @@
|
||||
|
||||
<div class="remove-icon-wrapper">
|
||||
<font-awesome-icon
|
||||
v-if="index > 0"
|
||||
v-if="showRemoveItemIcon"
|
||||
class="remove-icon"
|
||||
icon="trash-alt"
|
||||
@click="removeItem"
|
||||
@@ -181,6 +183,10 @@ export default {
|
||||
discountPerItem: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
invoiceItems: {
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -222,6 +228,12 @@ export default {
|
||||
return this.defaultCurrenctForInput
|
||||
}
|
||||
},
|
||||
showRemoveItemIcon () {
|
||||
if (this.invoiceItems.length == 1) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
subtotal () {
|
||||
return this.item.price * this.item.quantity
|
||||
},
|
||||
@@ -325,6 +337,9 @@ export default {
|
||||
created () {
|
||||
window.hub.$on('checkItems', this.validateItem)
|
||||
window.hub.$on('newItem', (val) => {
|
||||
if (this.taxPerItem === 'YES') {
|
||||
this.item.taxes = val.taxes
|
||||
}
|
||||
if (!this.item.item_id && this.modalActive && this.isSelected) {
|
||||
this.onSelectItem(val)
|
||||
}
|
||||
@@ -364,7 +379,13 @@ export default {
|
||||
this.item.price = item.price
|
||||
this.item.item_id = item.id
|
||||
this.item.description = item.description
|
||||
|
||||
if (this.taxPerItem === 'YES' && item.taxes) {
|
||||
let index = 0
|
||||
item.taxes.forEach(tax => {
|
||||
this.updateTax({index, item: { ...tax }})
|
||||
index++
|
||||
})
|
||||
}
|
||||
// if (this.item.taxes.length) {
|
||||
// this.item.taxes = {...item.taxes}
|
||||
// }
|
||||
|
||||
@@ -66,6 +66,14 @@ export default {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
taxPerItem: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
taxes: {
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -118,7 +126,8 @@ export default {
|
||||
this.$emit('onSelectItem')
|
||||
this.openModal({
|
||||
'title': 'Add Item',
|
||||
'componentName': 'ItemModal'
|
||||
'componentName': 'ItemModal',
|
||||
'data': {taxPerItem: this.taxPerItem, taxes: this.taxes}
|
||||
})
|
||||
},
|
||||
deselectItem () {
|
||||
|
||||
@@ -73,7 +73,9 @@
|
||||
<font-awesome-icon icon="filter" />
|
||||
</base-button>
|
||||
</a>
|
||||
|
||||
<div class="filter-title">
|
||||
{{ $t('general.sort_by') }}
|
||||
</div>
|
||||
<div class="filter-items">
|
||||
<input
|
||||
id="filter_invoice_date"
|
||||
@@ -111,7 +113,7 @@
|
||||
<label class="inv-label" for="filter_invoice_number">{{ $t('invoices.invoice_number') }}</label>
|
||||
</div>
|
||||
</v-dropdown>
|
||||
<base-button 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>
|
||||
@@ -123,17 +125,19 @@
|
||||
v-for="(invoice,index) in invoices"
|
||||
:to="`/admin/invoices/${invoice.id}/view`"
|
||||
:key="index"
|
||||
class="side-invoice"
|
||||
class="side-invoice"
|
||||
>
|
||||
<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>
|
||||
<div class="right">
|
||||
<div class="inv-amount" v-html="$utils.formatMoney(invoice.due_amount, invoice.user.currency)" />
|
||||
<div class="inv-date">{{ invoice.formattedInvoiceDate }}</div>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
<div class="right">
|
||||
<div class="inv-amount" v-html="$utils.formatMoney(invoice.due_amount, invoice.user.currency)" />
|
||||
<div class="inv-date">{{ invoice.formattedInvoiceDate }}</div>
|
||||
</div>
|
||||
|
||||
</router-link>
|
||||
<p v-if="!invoices.length" class="no-result">
|
||||
{{ $t('invoices.no_matching_invoices') }}
|
||||
@@ -168,17 +172,22 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
getOrderBy () {
|
||||
if (this.searchData.orderBy === 'asc' || this.searchData.orderBy == null) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
getOrderName () {
|
||||
if (this.getOrderBy) {
|
||||
return this.$t('general.ascending')
|
||||
}
|
||||
return this.$t('general.descending')
|
||||
},
|
||||
shareableLink () {
|
||||
return `/invoices/pdf/${this.invoice.unique_hash}`
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
$route (to, from) {
|
||||
this.loadInvoice()
|
||||
|
||||
@@ -50,11 +50,31 @@
|
||||
<label>{{ $t('items.unit') }}</label>
|
||||
<base-select
|
||||
v-model="formData.unit"
|
||||
:options="units"
|
||||
:options="itemUnits"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('items.select_a_unit')"
|
||||
label="name"
|
||||
>
|
||||
<div slot="afterList">
|
||||
<button type="button" class="list-add-button" @click="addItemUnit">
|
||||
<font-awesome-icon class="icon" icon="cart-plus" />
|
||||
<label>{{ $t('settings.customization.items.add_item_unit') }}</label>
|
||||
</button>
|
||||
</div>
|
||||
</base-select>
|
||||
</div>
|
||||
<div v-if="isTaxPerItem" class="form-group">
|
||||
<label>{{ $t('items.taxes') }}</label>
|
||||
<base-select
|
||||
v-model="formData.taxes"
|
||||
:options="getTaxTypes"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="true"
|
||||
:multiple="true"
|
||||
track-by="tax_type_id"
|
||||
label="tax_name"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -66,7 +86,9 @@
|
||||
@input="$v.formData.description.$touch()"
|
||||
/>
|
||||
<div v-if="$v.formData.description.$error">
|
||||
<span v-if="!$v.formData.description.maxLength" class="text-danger">{{ $t('validation.description_maxlength') }}</span>
|
||||
<span v-if="!$v.formData.description.maxLength" class="text-danger">
|
||||
{{ $t('validation.description_maxlength') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -102,24 +124,17 @@ export default {
|
||||
return {
|
||||
isLoading: false,
|
||||
title: 'Add Item',
|
||||
units: [
|
||||
{ name: 'box', value: 'box' },
|
||||
{ name: 'cm', value: 'cm' },
|
||||
{ name: 'dz', value: 'dz' },
|
||||
{ name: 'ft', value: 'ft' },
|
||||
{ name: 'g', value: 'g' },
|
||||
{ name: 'in', value: 'in' },
|
||||
{ name: 'kg', value: 'kg' },
|
||||
{ name: 'km', value: 'km' },
|
||||
{ name: 'lb', value: 'lb' },
|
||||
{ name: 'mg', value: 'mg' },
|
||||
{ name: 'pc', value: 'pc' }
|
||||
],
|
||||
units: [],
|
||||
taxes: [],
|
||||
taxPerItem: '',
|
||||
formData: {
|
||||
name: '',
|
||||
description: '',
|
||||
price: '',
|
||||
unit: null
|
||||
unit_id: null,
|
||||
unit: null,
|
||||
taxes: [],
|
||||
tax_per_item: false
|
||||
},
|
||||
money: {
|
||||
decimal: '.',
|
||||
@@ -134,6 +149,9 @@ export default {
|
||||
...mapGetters('currency', [
|
||||
'defaultCurrencyForInput'
|
||||
]),
|
||||
...mapGetters('item', [
|
||||
'itemUnits'
|
||||
]),
|
||||
price: {
|
||||
get: function () {
|
||||
return this.formData.price / 100
|
||||
@@ -142,14 +160,26 @@ export default {
|
||||
this.formData.price = newValue * 100
|
||||
}
|
||||
},
|
||||
...mapGetters('taxType', [
|
||||
'taxTypes'
|
||||
]),
|
||||
isEdit () {
|
||||
if (this.$route.name === 'items.edit') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
isTaxPerItem () {
|
||||
return this.taxPerItem === 'YES' ? 1 : 0
|
||||
},
|
||||
getTaxTypes () {
|
||||
return this.taxTypes.map(tax => {
|
||||
return {...tax, tax_type_id: tax.id, tax_name: tax.name + ' (' + tax.percent + '%)'}
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.setTaxPerItem()
|
||||
if (this.isEdit) {
|
||||
this.loadEditData()
|
||||
}
|
||||
@@ -177,10 +207,26 @@ export default {
|
||||
'fetchItem',
|
||||
'updateItem'
|
||||
]),
|
||||
...mapActions('modal', [
|
||||
'openModal'
|
||||
]),
|
||||
async setTaxPerItem () {
|
||||
let res = await axios.get('/api/settings/get-setting?key=tax_per_item')
|
||||
if (res.data && res.data.tax_per_item === 'YES') {
|
||||
this.taxPerItem = 'YES'
|
||||
} else {
|
||||
this.taxPerItem = 'FALSE'
|
||||
}
|
||||
},
|
||||
async loadEditData () {
|
||||
let response = await this.fetchItem(this.$route.params.id)
|
||||
this.formData = response.data.item
|
||||
this.formData.unit = this.units.find(_unit => response.data.item.unit === _unit.name)
|
||||
|
||||
this.formData = {...response.data.item, unit: null}
|
||||
this.formData.taxes = response.data.item.taxes.map(tax => {
|
||||
return {...tax, tax_name: tax.name + ' (' + tax.percent + '%)'}
|
||||
})
|
||||
|
||||
this.formData.unit = this.itemUnits.find(_unit => response.data.item.unit_id === _unit.id)
|
||||
this.fractional_price = response.data.item.price
|
||||
},
|
||||
async submitItem () {
|
||||
@@ -189,30 +235,40 @@ export default {
|
||||
return false
|
||||
}
|
||||
if (this.formData.unit) {
|
||||
this.formData.unit = this.formData.unit.name
|
||||
this.formData.unit_id = this.formData.unit.id
|
||||
}
|
||||
let response
|
||||
if (this.isEdit) {
|
||||
this.isLoading = true
|
||||
let response = await this.updateItem(this.formData)
|
||||
if (response.data) {
|
||||
this.isLoading = false
|
||||
window.toastr['success'](this.$tc('items.updated_message'))
|
||||
this.$router.push('/admin/items')
|
||||
return true
|
||||
}
|
||||
window.toastr['error'](response.data.error)
|
||||
response = await this.updateItem(this.formData)
|
||||
} else {
|
||||
this.isLoading = true
|
||||
let response = await this.addItem(this.formData)
|
||||
|
||||
if (response.data) {
|
||||
window.toastr['success'](this.$tc('items.created_message'))
|
||||
this.$router.push('/admin/items')
|
||||
this.isLoading = false
|
||||
return true
|
||||
let data = {
|
||||
...this.formData,
|
||||
taxes: this.formData.taxes.map(tax => {
|
||||
return {
|
||||
tax_type_id: tax.id,
|
||||
amount: ((this.formData.price * tax.percent) / 100),
|
||||
percent: tax.percent,
|
||||
name: tax.name,
|
||||
collective_tax: 0
|
||||
}
|
||||
})
|
||||
}
|
||||
window.toastr['success'](response.data.success)
|
||||
response = await this.addItem(data)
|
||||
}
|
||||
if (response.data) {
|
||||
this.isLoading = false
|
||||
window.toastr['success'](this.$tc('items.updated_message'))
|
||||
this.$router.push('/admin/items')
|
||||
return true
|
||||
}
|
||||
window.toastr['error'](response.data.error)
|
||||
},
|
||||
async addItemUnit () {
|
||||
this.openModal({
|
||||
'title': 'Add Item Unit',
|
||||
'componentName': 'ItemUnit'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<label class="form-label"> {{ $tc('items.unit') }} </label>
|
||||
<base-select
|
||||
v-model="filters.unit"
|
||||
:options="units"
|
||||
:options="itemUnits"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('items.select_a_unit')"
|
||||
@@ -169,7 +169,7 @@
|
||||
/>
|
||||
<table-column
|
||||
:label="$t('items.unit')"
|
||||
show="unit"
|
||||
show="unit_name"
|
||||
/>
|
||||
<table-column
|
||||
:label="$t('items.price')"
|
||||
@@ -235,19 +235,6 @@ export default {
|
||||
id: null,
|
||||
showFilters: false,
|
||||
sortedBy: 'created_at',
|
||||
units: [
|
||||
{ name: 'box', value: 'box' },
|
||||
{ name: 'cm', value: 'cm' },
|
||||
{ name: 'dz', value: 'dz' },
|
||||
{ name: 'ft', value: 'ft' },
|
||||
{ name: 'g', value: 'g' },
|
||||
{ name: 'in', value: 'in' },
|
||||
{ name: 'kg', value: 'kg' },
|
||||
{ name: 'km', value: 'km' },
|
||||
{ name: 'lb', value: 'lb' },
|
||||
{ name: 'mg', value: 'mg' },
|
||||
{ name: 'pc', value: 'pc' }
|
||||
],
|
||||
isRequestOngoing: true,
|
||||
filtersApplied: false,
|
||||
filters: {
|
||||
@@ -262,7 +249,8 @@ export default {
|
||||
'items',
|
||||
'selectedItems',
|
||||
'totalItems',
|
||||
'selectAllField'
|
||||
'selectAllField',
|
||||
'itemUnits'
|
||||
]),
|
||||
...mapGetters('currency', [
|
||||
'defaultCurrency'
|
||||
@@ -296,6 +284,7 @@ export default {
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
|
||||
destroyed () {
|
||||
if (this.selectAllField) {
|
||||
this.selectAllItems()
|
||||
@@ -316,7 +305,7 @@ export default {
|
||||
async fetchData ({ page, filter, sort }) {
|
||||
let data = {
|
||||
search: this.filters.name !== null ? this.filters.name : '',
|
||||
unit: this.filters.unit !== null ? this.filters.unit.name : '',
|
||||
unit_id: this.filters.unit !== null ? this.filters.unit.id : '',
|
||||
price: this.filters.price * 100,
|
||||
orderByField: sort.fieldName || 'created_at',
|
||||
orderBy: sort.order || 'desc',
|
||||
@@ -395,7 +384,7 @@ export default {
|
||||
}).then(async (willDelete) => {
|
||||
if (willDelete) {
|
||||
let res = await this.deleteMultipleItems()
|
||||
if (res.data.success) {
|
||||
if (res.data.success || res.data.items) {
|
||||
window.toastr['success'](this.$tc('items.deleted_message', 2))
|
||||
this.$refs.table.refresh()
|
||||
} else if (res.data.error) {
|
||||
|
||||
@@ -109,12 +109,20 @@
|
||||
<div class="form-group">
|
||||
<label class="form-label">{{ $t('payments.payment_mode') }}</label>
|
||||
<base-select
|
||||
v-model="formData.payment_mode"
|
||||
:options="getPaymentMode"
|
||||
v-model="formData.payment_method"
|
||||
:options="paymentModes"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('payments.select_payment_mode')"
|
||||
/>
|
||||
label="name"
|
||||
>
|
||||
<div slot="afterList">
|
||||
<button type="button" class="list-add-button" @click="addPaymentMode">
|
||||
<font-awesome-icon class="icon" icon="cart-plus" />
|
||||
<label>{{ $t('settings.customization.payments.add_payment_mode') }}</label>
|
||||
</button>
|
||||
</div>
|
||||
</base-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 ">
|
||||
@@ -166,9 +174,10 @@ export default {
|
||||
payment_number: null,
|
||||
payment_date: null,
|
||||
amount: 0,
|
||||
payment_mode: null,
|
||||
payment_method: null,
|
||||
invoice_id: null,
|
||||
notes: null
|
||||
notes: null,
|
||||
payment_method_id: null
|
||||
},
|
||||
money: {
|
||||
decimal: '.',
|
||||
@@ -215,9 +224,9 @@ export default {
|
||||
...mapGetters('currency', [
|
||||
'defaultCurrencyForInput'
|
||||
]),
|
||||
getPaymentMode () {
|
||||
return ['Cash', 'Check', 'Credit Card', 'Bank Transfer']
|
||||
},
|
||||
...mapGetters('payment', [
|
||||
'paymentModes'
|
||||
]),
|
||||
amount: {
|
||||
get: function () {
|
||||
return this.formData.amount / 100
|
||||
@@ -286,14 +295,23 @@ export default {
|
||||
'fetchCreatePayment',
|
||||
'addPayment',
|
||||
'updatePayment',
|
||||
'fetchPayment'
|
||||
'fetchEditPaymentData'
|
||||
]),
|
||||
...mapActions('modal', [
|
||||
'openModal'
|
||||
]),
|
||||
invoiceWithAmount ({ invoice_number, due_amount }) {
|
||||
return `${invoice_number} (${this.$utils.formatGraphMoney(due_amount, this.customer.currency)})`
|
||||
},
|
||||
async addPaymentMode () {
|
||||
this.openModal({
|
||||
'title': 'Add Payment Mode',
|
||||
'componentName': 'PaymentMode'
|
||||
})
|
||||
},
|
||||
async loadData () {
|
||||
if (this.isEdit) {
|
||||
let response = await this.fetchPayment(this.$route.params.id)
|
||||
let response = await this.fetchEditPaymentData(this.$route.params.id)
|
||||
this.customerList = response.data.customers
|
||||
this.formData = { ...response.data.payment }
|
||||
this.customer = response.data.payment.user
|
||||
@@ -301,6 +319,7 @@ export default {
|
||||
this.formData.amount = parseFloat(response.data.payment.amount)
|
||||
this.paymentPrefix = response.data.payment_prefix
|
||||
this.paymentNumAttribute = response.data.nextPaymentNumber
|
||||
this.formData.payment_method = response.data.payment.payment_method
|
||||
if (response.data.payment.invoice !== null) {
|
||||
this.maxPayableAmount = parseInt(response.data.payment.amount) + parseInt(response.data.payment.invoice.due_amount)
|
||||
this.invoice = response.data.payment.invoice
|
||||
@@ -344,6 +363,7 @@ export default {
|
||||
let data = {
|
||||
editData: {
|
||||
...this.formData,
|
||||
payment_method_id: this.formData.payment_method.id,
|
||||
payment_date: moment(this.formData.payment_date).format('DD/MM/YYYY')
|
||||
},
|
||||
id: this.$route.params.id
|
||||
@@ -371,6 +391,7 @@ export default {
|
||||
} else {
|
||||
let data = {
|
||||
...this.formData,
|
||||
payment_method_id: this.formData.payment_method.id,
|
||||
payment_date: moment(this.formData.payment_date).format('DD/MM/YYYY')
|
||||
}
|
||||
this.isLoading = true
|
||||
|
||||
@@ -67,10 +67,11 @@
|
||||
<label class="form-label">{{ $t('payments.payment_mode') }}</label>
|
||||
<base-select
|
||||
v-model="filters.payment_mode"
|
||||
:options="payment_mode"
|
||||
:options="paymentModes"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('payments.payment_mode')"
|
||||
label="name"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -203,6 +204,14 @@
|
||||
{{ $t('general.edit') }}
|
||||
</router-link>
|
||||
|
||||
</v-dropdown-item>
|
||||
<v-dropdown-item>
|
||||
|
||||
<router-link :to="{path: `payments/${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>
|
||||
<div class="dropdown-item" @click="removePayment(row.id)">
|
||||
@@ -237,7 +246,6 @@ export default {
|
||||
sortedBy: 'created_at',
|
||||
filtersApplied: false,
|
||||
isRequestOngoing: true,
|
||||
payment_mode: ['Cash', 'Check', 'Credit Card', 'Bank Transfer'],
|
||||
filters: {
|
||||
customer: null,
|
||||
payment_mode: '',
|
||||
@@ -259,7 +267,8 @@ export default {
|
||||
'selectedPayments',
|
||||
'totalPayments',
|
||||
'payments',
|
||||
'selectAllField'
|
||||
'selectAllField',
|
||||
'paymentModes'
|
||||
]),
|
||||
selectField: {
|
||||
get: function () {
|
||||
@@ -308,7 +317,7 @@ export default {
|
||||
let data = {
|
||||
customer_id: this.filters.customer !== null ? this.filters.customer.id : '',
|
||||
payment_number: this.filters.payment_number,
|
||||
payment_mode: this.filters.payment_mode ? this.filters.payment_mode : '',
|
||||
payment_method_id: this.filters.payment_mode ? this.filters.payment_mode.id : '',
|
||||
orderByField: sort.fieldName || 'created_at',
|
||||
orderBy: sort.order || 'desc',
|
||||
page
|
||||
|
||||
286
resources/assets/js/views/payments/View.vue
Normal file
286
resources/assets/js/views/payments/View.vue
Normal file
@@ -0,0 +1,286 @@
|
||||
<template>
|
||||
<div v-if="payment" class="main-content payment-view-page">
|
||||
<div class="page-header">
|
||||
<h3 class="page-title"> {{ payment.payment_number }}</h3>
|
||||
<div class="page-actions row">
|
||||
<base-button
|
||||
:loading="isSendingEmail"
|
||||
:disabled="isSendingEmail"
|
||||
:outline="true"
|
||||
color="theme"
|
||||
@click="onPaymentSend"
|
||||
>
|
||||
{{ $t('payments.send_payment_receipt') }}
|
||||
</base-button>
|
||||
<v-dropdown :close-on-select="false" 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"/>
|
||||
{{ $t('general.edit') }}
|
||||
</router-link>
|
||||
<div class="dropdown-item" @click="removePayment($route.params.id)">
|
||||
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
|
||||
{{ $t('general.delete') }}
|
||||
</div>
|
||||
</v-dropdown-item>
|
||||
</v-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="payment-sidebar">
|
||||
<div class="side-header">
|
||||
<base-input
|
||||
v-model="searchData.searchText"
|
||||
:placeholder="$t('general.search')"
|
||||
input-class="inv-search"
|
||||
icon="search"
|
||||
type="text"
|
||||
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">
|
||||
<a slot="activator" href="#">
|
||||
<base-button class="inv-button inv-filter-fields-btn" color="default" size="medium">
|
||||
<font-awesome-icon icon="filter" />
|
||||
</base-button>
|
||||
</a>
|
||||
<div class="filter-title">
|
||||
{{ $t('general.sort_by') }}
|
||||
</div>
|
||||
<div class="filter-items">
|
||||
<input
|
||||
id="filter_invoice_number"
|
||||
v-model="searchData.orderByField"
|
||||
type="radio"
|
||||
name="filter"
|
||||
class="inv-radio"
|
||||
value="invoice_number"
|
||||
@change="onSearch"
|
||||
>
|
||||
<label class="inv-label" for="filter_invoice_number">{{ $t('invoices.title') }}</label>
|
||||
</div>
|
||||
<div class="filter-items">
|
||||
<input
|
||||
id="filter_payment_date"
|
||||
v-model="searchData.orderByField"
|
||||
type="radio"
|
||||
name="filter"
|
||||
class="inv-radio"
|
||||
value="payment_date"
|
||||
@change="onSearch"
|
||||
>
|
||||
<label class="inv-label" for="filter_payment_date">{{ $t('payments.date') }}</label>
|
||||
</div>
|
||||
<div class="filter-items">
|
||||
<input
|
||||
id="filter_payment_number"
|
||||
v-model="searchData.orderByField"
|
||||
type="radio"
|
||||
name="filter"
|
||||
class="inv-radio"
|
||||
value="payment_number"
|
||||
@change="onSearch"
|
||||
>
|
||||
<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">
|
||||
<font-awesome-icon v-if="getOrderBy" icon="sort-amount-up" />
|
||||
<font-awesome-icon v-else icon="sort-amount-down" />
|
||||
</base-button>
|
||||
</div>
|
||||
</div>
|
||||
<base-loader v-if="isSearching" />
|
||||
<div v-else class="side-content">
|
||||
<router-link
|
||||
v-for="(payment,index) in payments"
|
||||
:to="`/admin/payments/${payment.id}/view`"
|
||||
:key="index"
|
||||
class="side-payment"
|
||||
>
|
||||
<div class="left">
|
||||
<div class="inv-name">{{ payment.user.name }}</div>
|
||||
<div class="inv-number">{{ payment.payment_number }}</div>
|
||||
<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-date">{{ payment.formattedPaymentDate }}</div>
|
||||
<!-- <div class="inv-number">{{ payment.payment_method.name }}</div> -->
|
||||
</div>
|
||||
</router-link>
|
||||
<p v-if="!payments.length" class="no-result">
|
||||
{{ $t('payments.no_matching_invoices') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="payment-view-page-container" >
|
||||
<iframe :src="`${shareableLink}`" class="frame-style"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
const _ = require('lodash')
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
id: null,
|
||||
count: null,
|
||||
payments: [],
|
||||
payment: null,
|
||||
currency: null,
|
||||
searchData: {
|
||||
orderBy: null,
|
||||
orderByField: null,
|
||||
searchText: null
|
||||
},
|
||||
isRequestOnGoing: false,
|
||||
isSearching: false,
|
||||
isSendingEmail: false,
|
||||
isMarkingAsSent: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getOrderBy () {
|
||||
if (this.searchData.orderBy === 'asc' || this.searchData.orderBy == null) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
getOrderName () {
|
||||
if (this.getOrderBy) {
|
||||
return this.$t('general.ascending')
|
||||
}
|
||||
return this.$t('general.descending')
|
||||
},
|
||||
shareableLink () {
|
||||
return `/payments/pdf/${this.payment.unique_hash}`
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route (to, from) {
|
||||
this.loadPayment()
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.loadPayments()
|
||||
this.loadPayment()
|
||||
this.onSearch = _.debounce(this.onSearch, 500)
|
||||
},
|
||||
methods: {
|
||||
// ...mapActions('invoice', [
|
||||
// 'fetchInvoices',
|
||||
// 'getRecord',
|
||||
// 'searchInvoice',
|
||||
// 'markAsSent',
|
||||
// 'sendEmail',
|
||||
// 'deleteInvoice',
|
||||
// 'fetchViewInvoice'
|
||||
// ]),
|
||||
...mapActions('payment', [
|
||||
'fetchPayments',
|
||||
'fetchPayment',
|
||||
'sendEmail',
|
||||
'deletePayment',
|
||||
'searchPayment'
|
||||
]),
|
||||
async loadPayments () {
|
||||
let response = await this.fetchPayments()
|
||||
if (response.data) {
|
||||
this.payments = response.data.payments.data
|
||||
}
|
||||
},
|
||||
async loadPayment () {
|
||||
let response = await this.fetchPayment(this.$route.params.id)
|
||||
|
||||
if (response.data) {
|
||||
this.payment = response.data.payment
|
||||
}
|
||||
},
|
||||
async onSearch () {
|
||||
let data = ''
|
||||
if (this.searchData.searchText !== '' && this.searchData.searchText !== null && this.searchData.searchText !== undefined) {
|
||||
data += `search=${this.searchData.searchText}&`
|
||||
}
|
||||
|
||||
if (this.searchData.orderBy !== null && this.searchData.orderBy !== undefined) {
|
||||
data += `orderBy=${this.searchData.orderBy}&`
|
||||
}
|
||||
|
||||
if (this.searchData.orderByField !== null && this.searchData.orderByField !== undefined) {
|
||||
data += `orderByField=${this.searchData.orderByField}`
|
||||
}
|
||||
this.isSearching = true
|
||||
let response = await this.searchPayment(data)
|
||||
this.isSearching = false
|
||||
if (response.data) {
|
||||
this.payments = response.data.payments.data
|
||||
}
|
||||
},
|
||||
sortData () {
|
||||
if (this.searchData.orderBy === 'asc') {
|
||||
this.searchData.orderBy = 'desc'
|
||||
this.onSearch()
|
||||
return true
|
||||
}
|
||||
this.searchData.orderBy = 'asc'
|
||||
this.onSearch()
|
||||
return true
|
||||
},
|
||||
async onPaymentSend () {
|
||||
window.swal({
|
||||
title: this.$tc('general.are_you_sure'),
|
||||
text: this.$tc('payments.confirm_send_payment'),
|
||||
icon: '/assets/icon/paper-plane-solid.svg',
|
||||
buttons: true,
|
||||
dangerMode: true
|
||||
}).then(async (value) => {
|
||||
if (value) {
|
||||
this.isSendingEmail = true
|
||||
let response = await this.sendEmail({id: this.payment.id})
|
||||
this.isSendingEmail = false
|
||||
if (response.data.success) {
|
||||
window.toastr['success'](this.$tc('payments.send_payment_successfully'))
|
||||
return true
|
||||
}
|
||||
if (response.data.error === 'user_email_does_not_exist') {
|
||||
window.toastr['error'](this.$tc('payments.user_email_does_not_exist'))
|
||||
return false
|
||||
}
|
||||
window.toastr['error'](this.$tc('payments.something_went_wrong'))
|
||||
}
|
||||
})
|
||||
},
|
||||
async removePayment (id) {
|
||||
this.id = id
|
||||
window.swal({
|
||||
title: 'Deleted',
|
||||
text: 'you will not be able to recover this payment!',
|
||||
icon: '/assets/icon/trash-solid.svg',
|
||||
buttons: true,
|
||||
dangerMode: true
|
||||
}).then(async (value) => {
|
||||
if (value) {
|
||||
let request = await this.deletePayment(this.id)
|
||||
if (request.data.success) {
|
||||
window.toastr['success'](this.$tc('payments.deleted_message', 1))
|
||||
this.$router.push('/admin/payments')
|
||||
} else if (request.data.error) {
|
||||
window.toastr['error'](request.data.message)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -11,12 +11,15 @@
|
||||
<li class="tab" @click="setActiveTab('PAYMENTS')">
|
||||
<a :class="['tab-link', {'a-active': activeTab === 'PAYMENTS'}]" href="#">{{ $t('settings.customization.payments.title') }}</a>
|
||||
</li>
|
||||
<li class="tab" @click="setActiveTab('ITEMS')">
|
||||
<a :class="['tab-link', {'a-active': activeTab === 'ITEMS'}]" href="#">{{ $t('settings.customization.items.title') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Invoices Tab -->
|
||||
<transition name="fade-customize">
|
||||
<div v-if="activeTab === 'INVOICES'" class="invoice-tab">
|
||||
<form action="" class="form-section" @submit.prevent="updateInvoiceSetting">
|
||||
<form action="" class="mt-3" @submit.prevent="updateInvoiceSetting">
|
||||
<div class="row">
|
||||
<div class="col-md-12 mb-4">
|
||||
<label class="input-label">{{ $t('settings.customization.invoices.invoice_prefix') }}</label>
|
||||
@@ -32,7 +35,7 @@
|
||||
<span v-if="!$v.invoices.invoice_prefix.alpha" class="text-danger">{{ $t('validation.characters_only') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="row pb-3">
|
||||
<div class="col-md-12">
|
||||
<base-button
|
||||
icon="save"
|
||||
@@ -43,25 +46,23 @@
|
||||
</base-button>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
</form>
|
||||
<div class="col-md-12 mt-3">
|
||||
<div class="page-header">
|
||||
<h3 class="page-title">
|
||||
{{ $t('settings.customization.invoices.invoice_settings') }}
|
||||
</h3>
|
||||
<div class="flex-box">
|
||||
<div class="left">
|
||||
<base-switch
|
||||
v-model="invoiceAutogenerate"
|
||||
class="btn-switch"
|
||||
@change="setInvoiceSetting"
|
||||
/>
|
||||
</div>
|
||||
<div class="right ml-15">
|
||||
<p class="box-title"> {{ $t('settings.customization.invoices.autogenerate_invoice_number') }} </p>
|
||||
<p class="box-desc"> {{ $t('settings.customization.invoices.invoice_setting_description') }} </p>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="page-header pt-3">
|
||||
<h3 class="page-title">
|
||||
{{ $t('settings.customization.invoices.invoice_settings') }}
|
||||
</h3>
|
||||
<div class="flex-box">
|
||||
<div class="left">
|
||||
<base-switch
|
||||
v-model="invoiceAutogenerate"
|
||||
class="btn-switch"
|
||||
@change="setInvoiceSetting"
|
||||
/>
|
||||
</div>
|
||||
<div class="right ml-15">
|
||||
<p class="box-title"> {{ $t('settings.customization.invoices.autogenerate_invoice_number') }} </p>
|
||||
<p class="box-desc"> {{ $t('settings.customization.invoices.invoice_setting_description') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -71,7 +72,7 @@
|
||||
<!-- Estimates Tab -->
|
||||
<transition name="fade-customize">
|
||||
<div v-if="activeTab === 'ESTIMATES'" class="estimate-tab">
|
||||
<form action="" class="form-section" @submit.prevent="updateEstimateSetting">
|
||||
<form action="" class="mt-3" @submit.prevent="updateEstimateSetting">
|
||||
<div class="row">
|
||||
<div class="col-md-12 mb-4">
|
||||
<label class="input-label">{{ $t('settings.customization.estimates.estimate_prefix') }}</label>
|
||||
@@ -87,7 +88,7 @@
|
||||
<span v-if="!$v.estimates.estimate_prefix.alpha" class="text-danger">{{ $t('validation.characters_only') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="row pb-3">
|
||||
<div class="col-md-12">
|
||||
<base-button
|
||||
icon="save"
|
||||
@@ -100,23 +101,21 @@
|
||||
</div>
|
||||
<hr>
|
||||
</form>
|
||||
<div class="col-md-12 mt-3">
|
||||
<div class="page-header">
|
||||
<h3 class="page-title">
|
||||
{{ $t('settings.customization.estimates.estimate_settings') }}
|
||||
</h3>
|
||||
<div class="flex-box">
|
||||
<div class="left">
|
||||
<base-switch
|
||||
v-model="estimateAutogenerate"
|
||||
class="btn-switch"
|
||||
@change="setEstimateSetting"
|
||||
/>
|
||||
</div>
|
||||
<div class="right ml-15">
|
||||
<p class="box-title"> {{ $t('settings.customization.estimates.autogenerate_estimate_number') }} </p>
|
||||
<p class="box-desc"> {{ $t('settings.customization.estimates.estimate_setting_description') }} </p>
|
||||
</div>
|
||||
<div class="page-header pt-3">
|
||||
<h3 class="page-title">
|
||||
{{ $t('settings.customization.estimates.estimate_settings') }}
|
||||
</h3>
|
||||
<div class="flex-box">
|
||||
<div class="left">
|
||||
<base-switch
|
||||
v-model="estimateAutogenerate"
|
||||
class="btn-switch"
|
||||
@change="setEstimateSetting"
|
||||
/>
|
||||
</div>
|
||||
<div class="right ml-15">
|
||||
<p class="box-title"> {{ $t('settings.customization.estimates.autogenerate_estimate_number') }} </p>
|
||||
<p class="box-desc"> {{ $t('settings.customization.estimates.estimate_setting_description') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -126,7 +125,66 @@
|
||||
<!-- Payments Tab -->
|
||||
<transition name="fade-customize">
|
||||
<div v-if="activeTab === 'PAYMENTS'" class="payment-tab">
|
||||
<form action="" class="form-section" @submit.prevent="updatePaymentSetting">
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<!-- <h3 class="page-title">
|
||||
{{ $t('settings.customization.payments.payment_mode') }}
|
||||
</h3> -->
|
||||
</div>
|
||||
<div class="col-md-4 d-flex flex-row-reverse">
|
||||
<base-button
|
||||
outline
|
||||
class="add-new-tax"
|
||||
color="theme"
|
||||
@click="addPaymentMode"
|
||||
>
|
||||
{{ $t('settings.customization.payments.add_payment_mode') }}
|
||||
</base-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table-component
|
||||
ref="table"
|
||||
:show-filter="false"
|
||||
:data="paymentModes"
|
||||
table-class="table tax-table"
|
||||
class="mb-3"
|
||||
>
|
||||
<table-column
|
||||
:sortable="true"
|
||||
:label="$t('settings.customization.payments.payment_mode')"
|
||||
show="name"
|
||||
/>
|
||||
<table-column
|
||||
:sortable="false"
|
||||
:filterable="false"
|
||||
cell-class="action-dropdown"
|
||||
>
|
||||
<template slot-scope="row">
|
||||
<span>{{ $t('settings.tax_types.action') }}</span>
|
||||
<v-dropdown>
|
||||
<a slot="activator" href="#">
|
||||
<dot-icon />
|
||||
</a>
|
||||
<v-dropdown-item>
|
||||
<div class="dropdown-item" @click="editPaymentMode(row)">
|
||||
<font-awesome-icon :icon="['fas', 'pencil-alt']" class="dropdown-item-icon" />
|
||||
{{ $t('general.edit') }}
|
||||
</div>
|
||||
</v-dropdown-item>
|
||||
<v-dropdown-item>
|
||||
<div class="dropdown-item" @click="removePaymentMode(row.id)">
|
||||
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
|
||||
{{ $t('general.delete') }}
|
||||
</div>
|
||||
</v-dropdown-item>
|
||||
</v-dropdown>
|
||||
</template>
|
||||
</table-column>
|
||||
</table-component>
|
||||
<hr>
|
||||
<form action="" class="pt-3" @submit.prevent="updatePaymentSetting">
|
||||
<div class="row">
|
||||
<div class="col-md-12 mb-4">
|
||||
<label class="input-label">{{ $t('settings.customization.payments.payment_prefix') }}</label>
|
||||
@@ -142,7 +200,7 @@
|
||||
<span v-if="!$v.payments.payment_prefix.alpha" class="text-danger">{{ $t('validation.characters_only') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="row pb-3">
|
||||
<div class="col-md-12">
|
||||
<base-button
|
||||
icon="save"
|
||||
@@ -155,33 +213,97 @@
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<div class="col-md-12 mt-4">
|
||||
<div class="page-header">
|
||||
<h3 class="page-title">
|
||||
{{ $t('settings.customization.payments.payment_settings') }}
|
||||
</h3>
|
||||
<div class="flex-box">
|
||||
<div class="left">
|
||||
<base-switch
|
||||
v-model="paymentAutogenerate"
|
||||
class="btn-switch"
|
||||
@change="setPaymentSetting"
|
||||
/>
|
||||
</div>
|
||||
<div class="right ml-15">
|
||||
<p class="box-title"> {{ $t('settings.customization.payments.autogenerate_payment_number') }} </p>
|
||||
<p class="box-desc"> {{ $t('settings.customization.payments.payment_setting_description') }} </p>
|
||||
</div>
|
||||
<div class="page-header pt-3">
|
||||
<h3 class="page-title">
|
||||
{{ $t('settings.customization.payments.payment_settings') }}
|
||||
</h3>
|
||||
<div class="flex-box">
|
||||
<div class="left">
|
||||
<base-switch
|
||||
v-model="paymentAutogenerate"
|
||||
class="btn-switch"
|
||||
@change="setPaymentSetting"
|
||||
/>
|
||||
</div>
|
||||
<div class="right ml-15">
|
||||
<p class="box-title"> {{ $t('settings.customization.payments.autogenerate_payment_number') }} </p>
|
||||
<p class="box-desc"> {{ $t('settings.customization.payments.payment_setting_description') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<!-- Items Tab -->
|
||||
<transition name="fade-customize">
|
||||
<div v-if="activeTab === 'ITEMS'" class="item-tab">
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<!-- <h3 class="page-title">
|
||||
{{ $t('settings.customization.items.title') }}
|
||||
</h3> -->
|
||||
</div>
|
||||
<div class="col-md-4 d-flex flex-row-reverse">
|
||||
<base-button
|
||||
outline
|
||||
class="add-new-tax"
|
||||
color="theme"
|
||||
@click="addItemUnit"
|
||||
>
|
||||
{{ $t('settings.customization.items.add_item_unit') }}
|
||||
</base-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table-component
|
||||
ref="itemTable"
|
||||
:show-filter="false"
|
||||
:data="itemUnits"
|
||||
table-class="table tax-table"
|
||||
class="mb-3"
|
||||
>
|
||||
<table-column
|
||||
:sortable="true"
|
||||
:label="$t('settings.customization.items.units')"
|
||||
show="name"
|
||||
/>
|
||||
<table-column
|
||||
:sortable="false"
|
||||
:filterable="false"
|
||||
cell-class="action-dropdown"
|
||||
>
|
||||
<template slot-scope="row">
|
||||
<span>{{ $t('settings.tax_types.action') }}</span>
|
||||
<v-dropdown>
|
||||
<a slot="activator" href="#">
|
||||
<dot-icon />
|
||||
</a>
|
||||
<v-dropdown-item>
|
||||
<div class="dropdown-item" @click="editItemUnit(row)">
|
||||
<font-awesome-icon :icon="['fas', 'pencil-alt']" class="dropdown-item-icon" />
|
||||
{{ $t('general.edit') }}
|
||||
</div>
|
||||
</v-dropdown-item>
|
||||
<v-dropdown-item>
|
||||
<div class="dropdown-item" @click="removeItemUnit(row.id)">
|
||||
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
|
||||
{{ $t('general.delete') }}
|
||||
</div>
|
||||
</v-dropdown-item>
|
||||
</v-dropdown>
|
||||
</template>
|
||||
</table-column>
|
||||
</table-component>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { validationMixin } from 'vuelidate'
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
const { required, maxLength, alpha } = require('vuelidate/lib/validators')
|
||||
export default {
|
||||
mixins: [validationMixin],
|
||||
@@ -204,9 +326,20 @@ export default {
|
||||
payments: {
|
||||
payment_prefix: null
|
||||
},
|
||||
items: {
|
||||
units: []
|
||||
},
|
||||
currentData: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('item', [
|
||||
'itemUnits'
|
||||
]),
|
||||
...mapGetters('payment', [
|
||||
'paymentModes'
|
||||
])
|
||||
},
|
||||
watch: {
|
||||
activeTab () {
|
||||
this.loadData()
|
||||
@@ -239,6 +372,15 @@ export default {
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
...mapActions('modal', [
|
||||
'openModal'
|
||||
]),
|
||||
...mapActions('payment', [
|
||||
'deletePaymentMode'
|
||||
]),
|
||||
...mapActions('item', [
|
||||
'deleteItemUnit'
|
||||
]),
|
||||
async setInvoiceSetting () {
|
||||
let data = {
|
||||
key: 'invoice_auto_generate',
|
||||
@@ -259,6 +401,78 @@ export default {
|
||||
window.toastr['success'](this.$t('general.setting_updated'))
|
||||
}
|
||||
},
|
||||
async addItemUnit () {
|
||||
this.openModal({
|
||||
'title': 'Add Item Unit',
|
||||
'componentName': 'ItemUnit'
|
||||
})
|
||||
this.$refs.itemTable.refresh()
|
||||
},
|
||||
async editItemUnit (data) {
|
||||
this.openModal({
|
||||
'title': 'Edit Item Unit',
|
||||
'componentName': 'ItemUnit',
|
||||
'id': data.id,
|
||||
'data': data
|
||||
})
|
||||
this.$refs.itemTable.refresh()
|
||||
},
|
||||
async removeItemUnit (id) {
|
||||
swal({
|
||||
title: this.$t('general.are_you_sure'),
|
||||
text: this.$t('settings.customization.items.item_unit_confirm_delete'),
|
||||
icon: '/assets/icon/trash-solid.svg',
|
||||
buttons: true,
|
||||
dangerMode: true
|
||||
}).then(async (value) => {
|
||||
if (value) {
|
||||
let response = await this.deleteItemUnit(id)
|
||||
if (response.data.success) {
|
||||
window.toastr['success'](this.$t('settings.customization.items.deleted_message'))
|
||||
this.id = null
|
||||
this.$refs.itemTable.refresh()
|
||||
return true
|
||||
}
|
||||
window.toastr['error'](this.$t('settings.customization.items.already_in_use'))
|
||||
}
|
||||
})
|
||||
},
|
||||
async addPaymentMode () {
|
||||
this.openModal({
|
||||
'title': 'Add Payment Mode',
|
||||
'componentName': 'PaymentMode'
|
||||
})
|
||||
this.$refs.table.refresh()
|
||||
},
|
||||
async editPaymentMode (data) {
|
||||
this.openModal({
|
||||
'title': 'Edit Payment Mode',
|
||||
'componentName': 'PaymentMode',
|
||||
'id': data.id,
|
||||
'data': data
|
||||
})
|
||||
this.$refs.table.refresh()
|
||||
},
|
||||
removePaymentMode (id) {
|
||||
swal({
|
||||
title: this.$t('general.are_you_sure'),
|
||||
text: this.$t('settings.customization.payments.payment_mode_confirm_delete'),
|
||||
icon: '/assets/icon/trash-solid.svg',
|
||||
buttons: true,
|
||||
dangerMode: true
|
||||
}).then(async (value) => {
|
||||
if (value) {
|
||||
let response = await this.deletePaymentMode(id)
|
||||
if (response.data.success) {
|
||||
window.toastr['success'](this.$t('settings.customization.payments.deleted_message'))
|
||||
this.id = null
|
||||
this.$refs.table.refresh()
|
||||
return true
|
||||
}
|
||||
window.toastr['error'](this.$t('settings.customization.payments.already_in_use'))
|
||||
}
|
||||
})
|
||||
},
|
||||
changeToUppercase (currentTab) {
|
||||
if (currentTab === 'INVOICES') {
|
||||
this.invoices.invoice_prefix = this.invoices.invoice_prefix.toUpperCase()
|
||||
|
||||
@@ -15,7 +15,19 @@
|
||||
:mail-drivers="mail_drivers"
|
||||
@on-change-driver="(val) => mail_driver = mailConfigData.mail_driver = val"
|
||||
@submit-data="saveEmailConfig"
|
||||
/>
|
||||
>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
outline
|
||||
class="pull-right mt-4 ml-2"
|
||||
icon="check"
|
||||
color="theme"
|
||||
type="button"
|
||||
@click="openMailTestModal"
|
||||
>
|
||||
{{ $t('general.test_mail_conf') }}
|
||||
</base-button>
|
||||
</component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -27,6 +39,7 @@ import Smtp from './mailDriver/Smtp'
|
||||
import Mailgun from './mailDriver/Mailgun'
|
||||
import Ses from './mailDriver/Ses'
|
||||
import Basic from './mailDriver/Basic'
|
||||
import { mapActions } from 'vuex'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -50,6 +63,9 @@ export default {
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
...mapActions('modal', [
|
||||
'openModal'
|
||||
]),
|
||||
async loadData () {
|
||||
this.loading = true
|
||||
|
||||
@@ -79,6 +95,12 @@ export default {
|
||||
} catch (e) {
|
||||
window.toastr['error']('Something went wrong')
|
||||
}
|
||||
},
|
||||
openMailTestModal () {
|
||||
this.openModal({
|
||||
'title': 'Test Mail Configuration',
|
||||
'componentName': 'MailTestModal'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,15 +73,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('general.save') }}
|
||||
</base-button>
|
||||
<div class="d-flex">
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('general.save') }}
|
||||
</base-button>
|
||||
<slot/>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@@ -167,15 +167,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('general.save') }}
|
||||
</base-button>
|
||||
<div class="d-flex">
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('general.save') }}
|
||||
</base-button>
|
||||
<slot/>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@@ -146,15 +146,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('general.save') }}
|
||||
</base-button>
|
||||
<div class="d-flex">
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('general.save') }}
|
||||
</base-button>
|
||||
<slot/>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@@ -146,15 +146,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('general.save') }}
|
||||
</base-button>
|
||||
<div class="d-flex">
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('general.save') }}
|
||||
</base-button>
|
||||
<slot/>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
:placeholder="$t('general.select_country')"
|
||||
track-by="id"
|
||||
label="name"
|
||||
@input="fetchState()"
|
||||
/>
|
||||
<div v-if="$v.companyData.country_id.$error">
|
||||
<span v-if="!$v.companyData.country_id.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
|
||||
44
resources/assets/sass/components/item-unit-modal.scss
vendored
Normal file
44
resources/assets/sass/components/item-unit-modal.scss
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
.item-unit-modal {
|
||||
|
||||
.card-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 20px 20px;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
text-align: end;
|
||||
padding-right: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.required {
|
||||
position: absolute;
|
||||
// left: -10px;
|
||||
color: $ls-color-red;
|
||||
}
|
||||
|
||||
.compound-tax-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media(max-width: $x-small-breakpoint ) {
|
||||
|
||||
.base-modal {
|
||||
|
||||
.item-unit-modal {
|
||||
width: 100vw;
|
||||
|
||||
.input-label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
44
resources/assets/sass/components/mail-test-modal.scss
vendored
Normal file
44
resources/assets/sass/components/mail-test-modal.scss
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
.mail-test-modal {
|
||||
|
||||
.card-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 20px 20px;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
text-align: end;
|
||||
padding-right: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.required {
|
||||
position: absolute;
|
||||
margin-left: 4px;
|
||||
color: $ls-color-red;
|
||||
}
|
||||
|
||||
.compound-tax-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media(max-width: $x-small-breakpoint ) {
|
||||
|
||||
.base-modal {
|
||||
|
||||
.mail-test-modal {
|
||||
width: 100vw;
|
||||
|
||||
.input-label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
44
resources/assets/sass/components/payment-modes-modal.scss
vendored
Normal file
44
resources/assets/sass/components/payment-modes-modal.scss
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
.payment-modes-modal {
|
||||
|
||||
.card-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 20px 20px;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
text-align: end;
|
||||
padding-right: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.required {
|
||||
position: absolute;
|
||||
// left: -10px;
|
||||
color: $ls-color-red;
|
||||
}
|
||||
|
||||
.compound-tax-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media(max-width: $x-small-breakpoint ) {
|
||||
|
||||
.base-modal {
|
||||
|
||||
.payment-modes-modal-modal {
|
||||
width: 100vw;
|
||||
|
||||
.input-label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
109
resources/assets/sass/components/v-tooltips.scss
vendored
Normal file
109
resources/assets/sass/components/v-tooltips.scss
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
.tooltip {
|
||||
display: block !important;
|
||||
z-index: 10000;
|
||||
|
||||
.tooltip-inner {
|
||||
background: black;
|
||||
color: white;
|
||||
border-radius: 16px;
|
||||
padding: 5px 10px 4px;
|
||||
}
|
||||
|
||||
.tooltip-arrow {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-style: solid;
|
||||
position: absolute;
|
||||
margin: 5px;
|
||||
border-color: black;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&[x-placement^="top"] {
|
||||
margin-bottom: 5px;
|
||||
|
||||
.tooltip-arrow {
|
||||
border-width: 5px 5px 0 5px;
|
||||
border-left-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
bottom: -5px;
|
||||
left: calc(50% - 5px);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&[x-placement^="bottom"] {
|
||||
margin-top: 5px;
|
||||
|
||||
.tooltip-arrow {
|
||||
border-width: 0 5px 5px 5px;
|
||||
border-left-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
border-top-color: transparent !important;
|
||||
top: -5px;
|
||||
left: calc(50% - 5px);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&[x-placement^="right"] {
|
||||
margin-left: 5px;
|
||||
|
||||
.tooltip-arrow {
|
||||
border-width: 5px 5px 5px 0;
|
||||
border-left-color: transparent !important;
|
||||
border-top-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
left: -5px;
|
||||
top: calc(50% - 5px);
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&[x-placement^="left"] {
|
||||
margin-right: 5px;
|
||||
|
||||
.tooltip-arrow {
|
||||
border-width: 5px 0 5px 5px;
|
||||
border-top-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
right: -5px;
|
||||
top: calc(50% - 5px);
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.popover {
|
||||
$color: #f9f9f9;
|
||||
|
||||
.popover-inner {
|
||||
background: $color;
|
||||
color: black;
|
||||
padding: 24px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 5px 30px rgba(black, .1);
|
||||
}
|
||||
|
||||
.popover-arrow {
|
||||
border-color: $color;
|
||||
}
|
||||
}
|
||||
|
||||
&[aria-hidden='true'] {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity .15s, visibility .15s;
|
||||
}
|
||||
|
||||
&[aria-hidden='false'] {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: opacity .15s;
|
||||
}
|
||||
}
|
||||
5
resources/assets/sass/crater.scss
vendored
5
resources/assets/sass/crater.scss
vendored
@@ -49,6 +49,7 @@
|
||||
@import "components/base/base-switch";
|
||||
@import 'components/base/base-loader/index';
|
||||
@import 'components/base/base-prefix-input';
|
||||
@import 'components/v-tooltips.scss';
|
||||
|
||||
|
||||
// Components
|
||||
@@ -72,6 +73,9 @@
|
||||
@import "components/item-select";
|
||||
@import "components/tax-select";
|
||||
@import "components/avatar-cropper";
|
||||
@import "components/payment-modes-modal";
|
||||
@import "components/item-unit-modal.scss";
|
||||
@import "components/mail-test-modal.scss";
|
||||
|
||||
|
||||
// Modals
|
||||
@@ -107,5 +111,6 @@
|
||||
@import 'pages/reports.scss';
|
||||
@import 'pages/customers';
|
||||
@import 'pages/payments.scss';
|
||||
@import 'pages/payment-view.scss';
|
||||
@import 'pages/items.scss';
|
||||
@import 'pages/statuses.scss';
|
||||
|
||||
20
resources/assets/sass/pages/estimates/view.scss
vendored
20
resources/assets/sass/pages/estimates/view.scss
vendored
@@ -32,6 +32,11 @@
|
||||
margin-bottom: 98px;
|
||||
}
|
||||
|
||||
&.router-link-exact-active {
|
||||
border-left: 3px solid $ls-color-primary;
|
||||
background-color: $ls-color-gray--very-light;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $ls-color-gray--very-light;
|
||||
}
|
||||
@@ -158,6 +163,7 @@
|
||||
border: 1px solid #eaf1fb;
|
||||
box-sizing: border-box;
|
||||
color: $ls-color-gray--dark;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,8 +196,17 @@
|
||||
|
||||
.filter-container {
|
||||
margin-left: 12px;
|
||||
|
||||
.filter-title {
|
||||
padding: 5px 10px;
|
||||
border-bottom: 1px solid rgba(185, 193, 209, 0.41);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.filter-items {
|
||||
display: flex;
|
||||
padding: 4px 9px;
|
||||
cursor: pointer;
|
||||
|
||||
&:first-child {
|
||||
margin-top: auto;
|
||||
@@ -202,11 +217,12 @@
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
line-height: 12px;
|
||||
text-transform: capitalize;
|
||||
color: $ls-color-black;
|
||||
margin-bottom: 6px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.base-input {
|
||||
@@ -214,7 +230,7 @@
|
||||
}
|
||||
|
||||
.dropdown-container {
|
||||
padding: 11px;
|
||||
padding: 0px !important;
|
||||
left: auto;
|
||||
right: 0px;
|
||||
width: 166px;
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: $ls-color-primary;
|
||||
margin: 0 0 0 0;
|
||||
margin: 0 9px 0 0;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
20
resources/assets/sass/pages/invoices/view.scss
vendored
20
resources/assets/sass/pages/invoices/view.scss
vendored
@@ -32,6 +32,11 @@
|
||||
margin-bottom: 98px;
|
||||
}
|
||||
|
||||
&.router-link-exact-active {
|
||||
border-left: 3px solid $ls-color-primary;
|
||||
background-color: $ls-color-gray--very-light;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $ls-color-gray--very-light;
|
||||
}
|
||||
@@ -113,6 +118,7 @@
|
||||
border: 1px solid $ls-color-gray--light;
|
||||
box-sizing: border-box;
|
||||
color: $ls-color-gray;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -148,9 +154,18 @@
|
||||
|
||||
.filter-container {
|
||||
margin-left: 12px;
|
||||
|
||||
.filter-title {
|
||||
padding: 5px 10px;
|
||||
border-bottom: 1px solid rgba(185, 193, 209, 0.41);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.filter-items {
|
||||
// margin-top: 10px;
|
||||
display: flex;
|
||||
padding: 4px 9px;
|
||||
cursor: pointer;
|
||||
|
||||
&:first-child {
|
||||
margin-top: auto;
|
||||
@@ -162,11 +177,12 @@
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
line-height: 12px;
|
||||
text-transform: capitalize;
|
||||
color: $ls-color-black;
|
||||
margin-bottom: 6px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.base-input {
|
||||
@@ -174,7 +190,7 @@
|
||||
}
|
||||
|
||||
.dropdown-container {
|
||||
padding: 11px;
|
||||
padding: 0px !important;
|
||||
left: auto;
|
||||
right: 0px;
|
||||
width: 155px;
|
||||
|
||||
238
resources/assets/sass/pages/payment-view.scss
vendored
Normal file
238
resources/assets/sass/pages/payment-view.scss
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
// Payments - View
|
||||
// -------------------------
|
||||
|
||||
.payment-view-page {
|
||||
padding-left: 570px !important;
|
||||
|
||||
.payment-sidebar {
|
||||
width: 300px;
|
||||
height: 100vh;
|
||||
height: 100%;
|
||||
left: 240px;
|
||||
padding: 60px 0 10px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 300px;
|
||||
z-index: 25;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.inv-search {
|
||||
background: $ls-color-gray--very-light !important;
|
||||
}
|
||||
|
||||
.side-payment {
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid rgba(185, 193, 209, 0.41);
|
||||
cursor: pointer;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 98px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $ls-color-gray--very-light;
|
||||
}
|
||||
|
||||
.left {
|
||||
|
||||
.inv-name {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-transform: capitalize;
|
||||
color: $ls-color-black;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.inv-number {
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
color: $ls-color-gray--dark;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.inv-status {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 10px;
|
||||
line-height: 15px;
|
||||
padding: 2px 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.right {
|
||||
|
||||
.inv-amount {
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 30px;
|
||||
text-align: right;
|
||||
color: $ls-color-black--light;
|
||||
}
|
||||
|
||||
.inv-date {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-align: right;
|
||||
color: $ls-color-gray--dark;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.no-result {
|
||||
color: $ls-color-gray;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.side-header {
|
||||
|
||||
height: 100px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30px 15px;
|
||||
border-bottom: 1px solid rgba(185, 193, 209, 0.41);
|
||||
|
||||
.inv-button {
|
||||
background: $ls-color-gray--very-light;
|
||||
border: 1px solid $ls-color-gray--light;
|
||||
box-sizing: border-box;
|
||||
color: $ls-color-gray;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.side-content {
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.payment-view-page-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 75vh;
|
||||
min-height: 0;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.frame-style {
|
||||
flex: 1 1 auto;
|
||||
border: 1px solid $ls-color-gray;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.inv-filter-fields-btn, .inv-filter-sorting-btn {
|
||||
|
||||
&:focus {
|
||||
border-color: inherit;
|
||||
box-shadow: none;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.filter-container {
|
||||
margin-left: 12px;
|
||||
|
||||
.filter-title {
|
||||
padding: 5px 10px;
|
||||
border-bottom: 1px solid rgba(185, 193, 209, 0.41);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.filter-items {
|
||||
// margin-top: 10px;
|
||||
display: flex;
|
||||
padding: 4px 9px;
|
||||
cursor: pointer;
|
||||
|
||||
&:first-child {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.inv-label {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 12px;
|
||||
text-transform: capitalize;
|
||||
color: $ls-color-black;
|
||||
margin-bottom: 6px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.base-input {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.dropdown-container {
|
||||
padding: 0px !important;
|
||||
left: auto;
|
||||
right: 0px;
|
||||
width: 167px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.filter-payment-date {
|
||||
|
||||
.vdp-datepicker {
|
||||
|
||||
div {
|
||||
|
||||
.vdp-datepicker__clear-button {
|
||||
margin-left: -21px;
|
||||
margin-top: 2px;
|
||||
font-size: 20px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.date-group {
|
||||
display: flex
|
||||
}
|
||||
|
||||
.to-text {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: $small-breakpoint) {
|
||||
|
||||
.payment-view-page {
|
||||
padding-left: 310px !important;
|
||||
}
|
||||
|
||||
.payment-sidebar {
|
||||
transition: .2s all;
|
||||
left: 0px !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
19
resources/assets/sass/pages/settings.scss
vendored
19
resources/assets/sass/pages/settings.scss
vendored
@@ -104,9 +104,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
.payment-tab {
|
||||
|
||||
.dropdown-container {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.item-tab {
|
||||
|
||||
.dropdown-container {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.add-new-tax {
|
||||
height: 45px;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.flex-box {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Estimate</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">
|
||||
@@ -19,13 +18,18 @@
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
hr {
|
||||
.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);
|
||||
border: 0.5px solid #EAF1FB;
|
||||
}
|
||||
|
||||
.header-center {
|
||||
@@ -250,8 +254,7 @@
|
||||
|
||||
.table2 {
|
||||
margin-top: 35px;
|
||||
border-bottom: 1px solid #EAF1FB;
|
||||
padding: 0px 30px 0 30px;
|
||||
padding: 0px 30px 10px 30px;
|
||||
page-break-before: avoid;
|
||||
page-break-after: auto;
|
||||
}
|
||||
@@ -265,6 +268,7 @@
|
||||
text-align: center;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
padding: 5px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
tr.main-table-header th {
|
||||
@@ -275,6 +279,10 @@
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.main-table-header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
tr.item-details td {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
@@ -287,6 +295,7 @@
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
text-align: center;
|
||||
padding: 5px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.padd8 {
|
||||
@@ -379,7 +388,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr class="header-line" style="border: 0.620315px solid #E8E8E8;" />
|
||||
<hr class="header-line" />
|
||||
</div>
|
||||
<div class="wrapper">
|
||||
<div class="address">
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Estimate</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">
|
||||
body {
|
||||
font-family: "DejaVu Sans";
|
||||
@@ -25,7 +23,6 @@
|
||||
display:inline-block;
|
||||
width:30%;
|
||||
}
|
||||
|
||||
@page {
|
||||
margin-top: 60px !important;
|
||||
}
|
||||
@@ -80,7 +77,8 @@
|
||||
}
|
||||
|
||||
.address {
|
||||
display: inline-block;
|
||||
display: block;
|
||||
padding-top: 20px;
|
||||
}
|
||||
.company {
|
||||
padding: 0 0 0 30px;
|
||||
@@ -110,8 +108,8 @@
|
||||
/* -------------------------- */
|
||||
/* billing style */
|
||||
.bill-address-container {
|
||||
display: inline;
|
||||
position: absolute;
|
||||
display: block;
|
||||
/* position: absolute; */
|
||||
float:right;
|
||||
padding: 0 40px 0 0;
|
||||
}
|
||||
@@ -159,8 +157,7 @@
|
||||
/* -------------------------- */
|
||||
/* shipping style */
|
||||
.ship-address-container {
|
||||
display: inline;
|
||||
position: absolute;
|
||||
display: block;
|
||||
float:right;
|
||||
padding: 0 30px 0 0;
|
||||
}
|
||||
@@ -247,13 +244,18 @@
|
||||
}
|
||||
|
||||
.table2 {
|
||||
margin-top: 200px;
|
||||
border-bottom: 1px solid #EAF1FB;
|
||||
padding: 0px 30px 0 30px;
|
||||
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;
|
||||
}
|
||||
@@ -285,6 +287,7 @@
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
text-align: center;
|
||||
padding: 5px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.note-header {
|
||||
@@ -317,6 +320,16 @@
|
||||
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;
|
||||
@@ -402,6 +415,7 @@
|
||||
<h1 class="header-logo"> {{$estimate->user->company->name}} </h1>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
<td width="40%" class="header-right company-details">
|
||||
<h1>Estimate</h1>
|
||||
<h4>{{$estimate->estimate_number}}</h4>
|
||||
@@ -426,6 +440,7 @@
|
||||
@endif
|
||||
@include('app.pdf.estimate.partials.billing-address')
|
||||
</div>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
@include('app.pdf.estimate.partials.table')
|
||||
@include('app.pdf.estimate.partials.notes')
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Estimate</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">
|
||||
@@ -18,7 +17,7 @@
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
hr {
|
||||
.header-line {
|
||||
color:rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
@@ -27,6 +26,15 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
hr {
|
||||
color:rgba(0, 0, 0, 0.2);
|
||||
border: 0.5px solid #EAF1FB;
|
||||
}
|
||||
|
||||
.items-table-hr{
|
||||
margin: 0 30px 0 30px;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
padding-top: 45px;
|
||||
padding-bottom: 45px;
|
||||
@@ -34,6 +42,7 @@
|
||||
display:inline-block;
|
||||
width:30%;
|
||||
}
|
||||
|
||||
.header-table {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
@@ -87,7 +96,7 @@
|
||||
|
||||
.address {
|
||||
display: inline-block;
|
||||
padding-top: 20px
|
||||
padding-top: 100px
|
||||
}
|
||||
|
||||
.bill-add {
|
||||
@@ -201,8 +210,7 @@
|
||||
|
||||
|
||||
.job-add {
|
||||
display: inline;
|
||||
position: absolute;
|
||||
display: block;
|
||||
float: right;
|
||||
padding: 20px 30px 0 0;
|
||||
}
|
||||
@@ -251,9 +259,7 @@
|
||||
line-height: 18px;
|
||||
}
|
||||
.table2 {
|
||||
margin-top: 188px;
|
||||
border-bottom: 1px solid #EAF1FB;
|
||||
padding: 0px 30px 0 30px;
|
||||
padding: 0px 30px 10px 30px;
|
||||
page-break-before: avoid;
|
||||
page-break-after: auto;
|
||||
}
|
||||
@@ -417,7 +423,9 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<hr style="border: 0.620315px solid #E8E8E8;">
|
||||
|
||||
<hr class="header-line">
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="address">
|
||||
<div class="bill-add">
|
||||
@@ -450,6 +458,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
@include('app.pdf.estimate.partials.table')
|
||||
@include('app.pdf.estimate.partials.notes')
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user