Compare commits
	
		
			27 Commits
		
	
	
		
			csfixer-te
			...
			4.2.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f5c23b33da | |||
| a0898a1fa0 | |||
| 236db087ba | |||
| 4772079d13 | |||
| 0e0ef1d99e | |||
| 3d9a73f9ec | |||
| b452c3f173 | |||
| 87667be90c | |||
| 31481739f1 | |||
| da43797d9c | |||
| e1fcf0695c | |||
| a52d5bc582 | |||
| e7bf86f9c0 | |||
| fca7d164a6 | |||
| 4b603f8823 | |||
| 4552138787 | |||
| d1dd704cdf | |||
| 00961bcae1 | |||
| 98ba17e56a | |||
| 8eb47b553e | |||
| 2fb46a4ab3 | |||
| 6fcddd6feb | |||
| 43c871f374 | |||
| 4ec9b2e817 | |||
| f2c6e06c54 | |||
| f95b292717 | |||
| 6ecd9728d4 | 
| @ -20,3 +20,6 @@ indent_size = 2 | ||||
|  | ||||
| [*.js] | ||||
| indent_size = 2 | ||||
|  | ||||
| [*.json] | ||||
| indent_size = 2 | ||||
|  | ||||
| @ -14,7 +14,8 @@ RUN apt-get update && apt-get install -y \ | ||||
|     zip \ | ||||
|     unzip \ | ||||
|     libzip-dev \ | ||||
|     libmagickwand-dev | ||||
|     libmagickwand-dev \ | ||||
|     mariadb-client | ||||
|  | ||||
| # Clear cache | ||||
| RUN apt-get clean && rm -rf /var/lib/apt/lists/* | ||||
|  | ||||
							
								
								
									
										63
									
								
								app/Console/Commands/CreateTemplateCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,63 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Console\Commands; | ||||
|  | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Facades\Storage; | ||||
|  | ||||
| class CreateTemplateCommand extends Command | ||||
| { | ||||
|     /** | ||||
|      * The name and signature of the console command. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $signature = 'make:template {name} {--type=}'; | ||||
|  | ||||
|     /** | ||||
|      * The console command description. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $description = 'Create estimate or invoice pdf template.                               '; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function handle() | ||||
|     { | ||||
|         $templateName = $this->argument('name'); | ||||
|         $type = $this->option('type'); | ||||
|  | ||||
|         if (! $type) { | ||||
|             $type = $this->choice('Create a template for?', ['invoice', 'estimate']); | ||||
|         } | ||||
|  | ||||
|         if (Storage::disk('views')->exists("/app/pdf/{$type}/{$templateName}.blade.php")) { | ||||
|             $this->info("Template with given name already exists."); | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         Storage::disk('views')->copy("/app/pdf/{$type}/{$type}1.blade.php", "/app/pdf/{$type}/{$templateName}.blade.php"); | ||||
|         copy(public_path("/assets/img/PDF/{$type}1.png"), public_path("/assets/img/PDF/{$templateName}.png")); | ||||
|  | ||||
|         $path = resource_path("app/pdf/{$type}/{$templateName}.blade.php"); | ||||
|         $type = ucfirst($type); | ||||
|         $this->info("{$type} Template created successfully at ".$path); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| @ -15,6 +15,7 @@ class Kernel extends ConsoleKernel | ||||
|     protected $commands = [ | ||||
|         Commands\ResetApp::class, | ||||
|         Commands\UpdateCommand::class, | ||||
|         Commands\CreateTemplateCommand::class | ||||
|     ]; | ||||
|  | ||||
|     /** | ||||
|  | ||||
| @ -21,7 +21,7 @@ class ConvertEstimateController extends Controller | ||||
|     */ | ||||
|     public function __invoke(Request $request, Estimate $estimate) | ||||
|     { | ||||
|         $estimate->load(['items', 'items.taxes', 'user', 'estimateTemplate', 'taxes']); | ||||
|         $estimate->load(['items', 'items.taxes', 'user', 'taxes']); | ||||
|  | ||||
|         $invoice_date = Carbon::now(); | ||||
|         $due_date = Carbon::now()->addDays(7); | ||||
| @ -39,7 +39,7 @@ class ConvertEstimateController extends Controller | ||||
|             'reference_number' => $estimate->reference_number, | ||||
|             'user_id' => $estimate->user_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'invoice_template_id' => 1, | ||||
|             'template_name' => 'invoice1', | ||||
|             'status' => Invoice::STATUS_DRAFT, | ||||
|             'paid_status' => Invoice::STATUS_UNPAID, | ||||
|             'sub_total' => $estimate->sub_total, | ||||
| @ -84,8 +84,7 @@ class ConvertEstimateController extends Controller | ||||
|         $invoice = Invoice::with([ | ||||
|             'items', | ||||
|             'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes', | ||||
|             'taxes' | ||||
|         ])->find($invoice->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|  | ||||
| @ -3,8 +3,9 @@ | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\EstimateTemplate; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Storage; | ||||
| use Illuminate\Support\Str; | ||||
|  | ||||
| class EstimateTemplatesController extends Controller | ||||
| { | ||||
| @ -16,8 +17,17 @@ class EstimateTemplatesController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $templates = Storage::disk('views')->files('/app/pdf/estimate'); | ||||
|         $estimateTemplates = []; | ||||
|  | ||||
|         foreach ($templates as $key => $template) { | ||||
|             $templateName = Str::before(basename($template), '.blade.php'); | ||||
|             $estimateTemplates[$key]['name'] = $templateName; | ||||
|             $estimateTemplates[$key]['path'] = asset('assets/img/PDF/'.$templateName.'.png'); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'templates' => EstimateTemplate::all(), | ||||
|             'templates' => $estimateTemplates | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -18,7 +18,6 @@ class EstimatesController extends Controller | ||||
|         $estimates = Estimate::with([ | ||||
|                 'items', | ||||
|                 'user', | ||||
|                 'estimateTemplate', | ||||
|                 'taxes', | ||||
|                 'creator', | ||||
|             ]) | ||||
| @ -68,7 +67,6 @@ class EstimatesController extends Controller | ||||
|             'items', | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'estimateTemplate', | ||||
|             'creator', | ||||
|             'taxes', | ||||
|             'taxes.taxType', | ||||
|  | ||||
| @ -21,7 +21,9 @@ class BootstrapController extends Controller | ||||
|     { | ||||
|         $user = Auth::user(); | ||||
|  | ||||
|         $default_language = $user->getSettings(['language'])['language']; | ||||
|         $default_language = $user->getSettings(['language']); | ||||
|  | ||||
|         $default_language = array_key_exists('language', $default_language) ? $default_language['language'] : 'en'; | ||||
|  | ||||
|         $settings = [ | ||||
|             'moment_date_format', | ||||
|  | ||||
| @ -32,7 +32,7 @@ class CloneInvoiceController extends Controller | ||||
|             'reference_number' => $invoice->reference_number, | ||||
|             'user_id' => $invoice->user_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'invoice_template_id' => $invoice->invoice_template_id, | ||||
|             'template_name' => 'invoice1', | ||||
|             'status' => Invoice::STATUS_DRAFT, | ||||
|             'paid_status' => Invoice::STATUS_UNPAID, | ||||
|             'sub_total' => $invoice->sub_total, | ||||
| @ -78,8 +78,7 @@ class CloneInvoiceController extends Controller | ||||
|         $newInvoice = Invoice::with([ | ||||
|                 'items', | ||||
|                 'user', | ||||
|                 'invoiceTemplate', | ||||
|                 'taxes', | ||||
|                 'taxes' | ||||
|             ]) | ||||
|             ->find($newInvoice->id); | ||||
|  | ||||
|  | ||||
| @ -3,8 +3,9 @@ | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\InvoiceTemplate; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Storage; | ||||
| use Illuminate\Support\Str; | ||||
|  | ||||
| class InvoiceTemplatesController extends Controller | ||||
| { | ||||
| @ -16,7 +17,14 @@ class InvoiceTemplatesController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $invoiceTemplates = InvoiceTemplate::all(); | ||||
|         $templates = Storage::disk('views')->files('/app/pdf/invoice'); | ||||
|         $invoiceTemplates = []; | ||||
|  | ||||
|         foreach ($templates as $key => $template) { | ||||
|             $templateName = Str::before(basename($template), '.blade.php'); | ||||
|             $invoiceTemplates[$key]['name'] = $templateName; | ||||
|             $invoiceTemplates[$key]['path'] = asset('assets/img/PDF/'.$templateName.'.png'); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoiceTemplates' => $invoiceTemplates, | ||||
|  | ||||
| @ -20,7 +20,7 @@ class InvoicesController extends Controller | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $invoices = Invoice::with(['items', 'user', 'creator', 'invoiceTemplate', 'taxes']) | ||||
|         $invoices = Invoice::with(['items', 'user', 'creator', 'taxes']) | ||||
|             ->join('users', 'users.id', '=', 'invoices.user_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'status', | ||||
| @ -78,7 +78,6 @@ class InvoicesController extends Controller | ||||
|             'items', | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes.taxType', | ||||
|             'fields.customField', | ||||
|         ]); | ||||
|  | ||||
| @ -5,6 +5,7 @@ namespace Crater\Http\Controllers\V1\Mobile; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
| use Illuminate\Support\Facades\Hash; | ||||
| use Illuminate\Validation\ValidationException; | ||||
|  | ||||
| @ -40,4 +41,9 @@ class AuthController extends Controller | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function check() | ||||
|     { | ||||
|         return Auth::check(); | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										32
									
								
								app/Http/Controllers/V1/Onboarding/AppDomainController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Onboarding; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DomainEnvironmentRequest; | ||||
| use Crater\Space\EnvironmentManager; | ||||
| use Illuminate\Support\Facades\Artisan; | ||||
|  | ||||
| class AppDomainController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * | ||||
|      * @param DomainEnvironmentRequest $request | ||||
|      */ | ||||
|     public function __invoke(DomainEnvironmentRequest $request) | ||||
|     { | ||||
|         Artisan::call('optimize:clear'); | ||||
|  | ||||
|         $environmentManager = new EnvironmentManager(); | ||||
|  | ||||
|         $results = $environmentManager->saveDomainVariables($request); | ||||
|  | ||||
|         if (in_array('error', $results)) { | ||||
|             return response()->json($results); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => false, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -36,6 +36,7 @@ class DatabaseConfigurationController extends Controller | ||||
|  | ||||
|         if (array_key_exists("success", $results)) { | ||||
|             Artisan::call('key:generate --force'); | ||||
|             Artisan::call('optimize:clear'); | ||||
|             Artisan::call('config:clear'); | ||||
|             Artisan::call('cache:clear'); | ||||
|             Artisan::call('storage:link'); | ||||
| @ -76,14 +77,6 @@ class DatabaseConfigurationController extends Controller | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|             case 'sqlsrv': | ||||
|                 $databaseData = [ | ||||
|                     'driver' => 'sqlsrv', | ||||
|                     'host' => '127.0.0.1', | ||||
|                     'port' => 1433, | ||||
|                 ]; | ||||
|  | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -3,9 +3,7 @@ | ||||
| namespace Crater\Http\Controllers\V1\Onboarding; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
|  | ||||
| class FinishController extends Controller | ||||
| { | ||||
| @ -19,7 +17,6 @@ class FinishController extends Controller | ||||
|     { | ||||
|         \Storage::disk('local')->put('database_created', 'database_created'); | ||||
|  | ||||
|         $user = User::where('role', 'super admin')->first(); | ||||
|         Auth::login($user); | ||||
|         return response()->json(['success' => true]); | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										25
									
								
								app/Http/Controllers/V1/Onboarding/LoginController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Onboarding; | ||||
|  | ||||
| use Auth; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class LoginController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $user = User::where('role', 'super admin')->first(); | ||||
|         Auth::login($user); | ||||
|  | ||||
|         return response()->json(['success' => true]); | ||||
|     } | ||||
| } | ||||
| @ -28,9 +28,10 @@ class RequirementsController extends Controller | ||||
|      */ | ||||
|     public function requirements() | ||||
|     { | ||||
|         $phpSupportInfo = $this->requirements->checkPHPversion( | ||||
|         $phpSupportInfo = $this->requirements->checkPHPVersion( | ||||
|             config('installer.core.minPhpVersion') | ||||
|         ); | ||||
|  | ||||
|         $requirements = $this->requirements->check( | ||||
|             config('installer.requirements') | ||||
|         ); | ||||
|  | ||||
| @ -30,9 +30,6 @@ class DatabaseEnvironmentRequest extends FormRequest | ||||
|                         'required', | ||||
|                         'url', | ||||
|                     ], | ||||
|                     'app_domain' => [ | ||||
|                         'required', | ||||
|                     ], | ||||
|                     'database_connection' => [ | ||||
|                         'required', | ||||
|                         'string', | ||||
| @ -50,9 +47,6 @@ class DatabaseEnvironmentRequest extends FormRequest | ||||
|                         'required', | ||||
|                         'url', | ||||
|                     ], | ||||
|                     'app_domain' => [ | ||||
|                         'required', | ||||
|                     ], | ||||
|                     'database_connection' => [ | ||||
|                         'required', | ||||
|                         'string', | ||||
|  | ||||
							
								
								
									
										32
									
								
								app/Http/Requests/DomainEnvironmentRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Requests; | ||||
|  | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| class DomainEnvironmentRequest extends FormRequest | ||||
| { | ||||
|     /** | ||||
|      * Determine if the user is authorized to make this request. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the validation rules that apply to the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|         return [ | ||||
|             'app_domain' => [ | ||||
|                 'required', | ||||
|             ], | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @ -54,8 +54,8 @@ class EstimatesRequest extends FormRequest | ||||
|             'tax' => [ | ||||
|                 'required', | ||||
|             ], | ||||
|             'estimate_template_id' => [ | ||||
|                 'required', | ||||
|             'template_name' => [ | ||||
|                 'required' | ||||
|             ], | ||||
|             'items' => [ | ||||
|                 'required', | ||||
|  | ||||
| @ -54,8 +54,8 @@ class InvoicesRequest extends FormRequest | ||||
|             'tax' => [ | ||||
|                 'required', | ||||
|             ], | ||||
|             'invoice_template_id' => [ | ||||
|                 'required', | ||||
|             'template_name' => [ | ||||
|                 'required' | ||||
|             ], | ||||
|             'items' => [ | ||||
|                 'required', | ||||
|  | ||||
| @ -130,11 +130,6 @@ class Estimate extends Model implements HasMedia | ||||
|         return $this->hasMany(Tax::class); | ||||
|     } | ||||
|  | ||||
|     public function estimateTemplate() | ||||
|     { | ||||
|         return $this->belongsTo('Crater\Models\EstimateTemplate'); | ||||
|     } | ||||
|  | ||||
|     public function getEstimateNumAttribute() | ||||
|     { | ||||
|         $position = $this->strposX($this->estimate_number, "-", 1) + 1; | ||||
| @ -315,8 +310,7 @@ class Estimate extends Model implements HasMedia | ||||
|         return Estimate::with([ | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'estimateTemplate', | ||||
|             'taxes', | ||||
|             'taxes' | ||||
|         ]) | ||||
|             ->find($estimate->id); | ||||
|     } | ||||
| @ -343,8 +337,7 @@ class Estimate extends Model implements HasMedia | ||||
|         return Estimate::with([ | ||||
|                 'items.taxes', | ||||
|                 'user', | ||||
|             'estimateTemplate', | ||||
|             'taxes', | ||||
|                 'taxes' | ||||
|             ]) | ||||
|             ->find($this->id); | ||||
|     } | ||||
| @ -431,7 +424,7 @@ class Estimate extends Model implements HasMedia | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $estimateTemplate = EstimateTemplate::find($this->estimate_template_id); | ||||
|         $estimateTemplate = self::find($this->id)->template_name; | ||||
|  | ||||
|         $company = Company::find($this->company_id); | ||||
|         $locale = CompanySetting::getSetting('language', $company->id); | ||||
| @ -451,7 +444,7 @@ class Estimate extends Model implements HasMedia | ||||
|             'taxes' => $taxes, | ||||
|         ]); | ||||
|  | ||||
|         return PDF::loadView('app.pdf.estimate.'.$estimateTemplate->view); | ||||
|         return PDF::loadView('app.pdf.estimate.'.$estimateTemplate); | ||||
|     } | ||||
|  | ||||
|     public function getCompanyAddress() | ||||
|  | ||||
| @ -1,23 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Factories\HasFactory; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| class EstimateTemplate extends Model | ||||
| { | ||||
|     use HasFactory; | ||||
|  | ||||
|     protected $fillable = ['path', 'view', 'name']; | ||||
|  | ||||
|     public function estimates() | ||||
|     { | ||||
|         return $this->hasMany(Estimate::class); | ||||
|     } | ||||
|  | ||||
|     public function getPathAttribute($value) | ||||
|     { | ||||
|         return url($value); | ||||
|     } | ||||
| } | ||||
| @ -141,11 +141,6 @@ class Invoice extends Model implements HasMedia | ||||
|         return $this->belongsTo('Crater\Models\User', 'creator_id'); | ||||
|     } | ||||
|  | ||||
|     public function invoiceTemplate() | ||||
|     { | ||||
|         return $this->belongsTo(InvoiceTemplate::class); | ||||
|     } | ||||
|  | ||||
|     public function getInvoicePdfUrlAttribute() | ||||
|     { | ||||
|         return url('/invoices/pdf/'.$this->unique_hash); | ||||
| @ -368,8 +363,7 @@ class Invoice extends Model implements HasMedia | ||||
|         $invoice = Invoice::with([ | ||||
|                 'items', | ||||
|                 'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes', | ||||
|                 'taxes' | ||||
|             ]) | ||||
|             ->find($invoice->id); | ||||
|  | ||||
| @ -420,8 +414,7 @@ class Invoice extends Model implements HasMedia | ||||
|         $invoice = Invoice::with([ | ||||
|                 'items', | ||||
|                 'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes', | ||||
|                 'taxes' | ||||
|             ]) | ||||
|             ->find($this->id); | ||||
|  | ||||
| @ -512,7 +505,7 @@ class Invoice extends Model implements HasMedia | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $invoiceTemplate = InvoiceTemplate::find($this->invoice_template_id); | ||||
|         $invoiceTemplate = self::find($this->id)->template_name; | ||||
|  | ||||
|         $company = Company::find($this->company_id); | ||||
|         $locale = CompanySetting::getSetting('language', $company->id); | ||||
| @ -532,7 +525,7 @@ class Invoice extends Model implements HasMedia | ||||
|             'taxes' => $taxes, | ||||
|         ]); | ||||
|  | ||||
|         return PDF::loadView('app.pdf.invoice.'.$invoiceTemplate->view); | ||||
|         return PDF::loadView('app.pdf.invoice.'.$invoiceTemplate); | ||||
|     } | ||||
|  | ||||
|     public function getEmailAttachmentSetting() | ||||
|  | ||||
| @ -1,23 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Factories\HasFactory; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| class InvoiceTemplate extends Model | ||||
| { | ||||
|     use HasFactory; | ||||
|  | ||||
|     protected $fillable = ['path', 'view', 'name']; | ||||
|  | ||||
|     public function invoices() | ||||
|     { | ||||
|         return $this->hasMany(Invoice::class); | ||||
|     } | ||||
|  | ||||
|     public function getPathAttribute($value) | ||||
|     { | ||||
|         return url($value); | ||||
|     } | ||||
| } | ||||
| @ -262,6 +262,11 @@ class User extends Authenticatable implements HasMedia | ||||
|         $query->orWhere('users.id', $customer_id); | ||||
|     } | ||||
|  | ||||
|     public function scopeWhereSuperAdmin($query) | ||||
|     { | ||||
|         $query->orWhere('role', 'super admin'); | ||||
|     } | ||||
|  | ||||
|     public function scopeApplyInvoiceFilters($query, array $filters) | ||||
|     { | ||||
|         $filters = collect($filters); | ||||
|  | ||||
| @ -10,6 +10,8 @@ class UniqueNumber implements Rule | ||||
|  | ||||
|     public $class; | ||||
|  | ||||
|     public $type; | ||||
|  | ||||
|     /** | ||||
|      * Create a new rule instance. | ||||
|      * @param  string  $class | ||||
| @ -38,6 +40,8 @@ class UniqueNumber implements Rule | ||||
|             $uniqueNumber = $value; | ||||
|         } | ||||
|  | ||||
|         $this->type = $attribute; | ||||
|  | ||||
|         if ($this->id && $this->class::where('id', $this->id)->where($attribute, $uniqueNumber)->first()) { | ||||
|             return true; | ||||
|         } | ||||
| @ -56,6 +60,8 @@ class UniqueNumber implements Rule | ||||
|      */ | ||||
|     public function message() | ||||
|     { | ||||
|         return 'Invalid number passed.'; | ||||
|         $type = str_replace('_', ' ', $this->type); | ||||
|  | ||||
|         return "{$type} is already used."; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -4,6 +4,7 @@ namespace Crater\Space; | ||||
|  | ||||
| use Crater\Http\Requests\DatabaseEnvironmentRequest; | ||||
| use Crater\Http\Requests\DiskEnvironmentRequest; | ||||
| use Crater\Http\Requests\DomainEnvironmentRequest; | ||||
| use Crater\Http\Requests\MailEnvironmentRequest; | ||||
| use Exception; | ||||
| use Illuminate\Http\Request; | ||||
| @ -77,6 +78,15 @@ class EnvironmentManager | ||||
|         try { | ||||
|             $this->checkDatabaseConnection($request); | ||||
|  | ||||
|             $requirement = $this->checkVersionRequirements($request); | ||||
|  | ||||
|             if ($requirement) { | ||||
|                 return [ | ||||
|                     'error' => 'minimum_version_requirement', | ||||
|                     'requirement' => $requirement, | ||||
|                 ]; | ||||
|             } | ||||
|  | ||||
|             if (\Schema::hasTable('users')) { | ||||
|                 return [ | ||||
|                     'error' => 'database_should_be_empty', | ||||
| @ -133,6 +143,7 @@ class EnvironmentManager | ||||
|     { | ||||
|         $connection = $request->database_connection; | ||||
|  | ||||
|         $settings = config("database.connections.$connection"); | ||||
|         $settings = config("database.connections.$connection"); | ||||
|  | ||||
|         $connectionArray = array_merge($settings, [ | ||||
| @ -160,6 +171,60 @@ class EnvironmentManager | ||||
|         return DB::connection()->getPdo(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param DatabaseEnvironmentRequest $request | ||||
|      * @return bool | ||||
|      */ | ||||
|     private function checkVersionRequirements(DatabaseEnvironmentRequest $request) | ||||
|     { | ||||
|         $connection = $request->database_connection; | ||||
|  | ||||
|         $checker = new RequirementsChecker(); | ||||
|  | ||||
|         $phpSupportInfo = $checker->checkPHPVersion( | ||||
|             config('crater.min_php_version') | ||||
|         ); | ||||
|  | ||||
|         if (! $phpSupportInfo['supported']) { | ||||
|             return $phpSupportInfo; | ||||
|         } | ||||
|  | ||||
|         $dbSupportInfo = []; | ||||
|  | ||||
|         switch ($connection) { | ||||
|             case 'mysql': | ||||
|                 $dbSupportInfo = $checker->checkMysqlVersion( | ||||
|                     config('crater.min_mysql_version') | ||||
|                 ); | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|             case 'pgsql': | ||||
|                 $conn = pg_connect("host={$request->database_hostname} port={$request->database_port} dbname={$request->database_name} user={$request->database_username} password={$request->database_password}"); | ||||
|                 $dbSupportInfo = $checker->checkPgsqlVersion( | ||||
|                     $conn, | ||||
|                     config('crater.min_pgsql_version') | ||||
|                 ); | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|             case 'sqlite': | ||||
|                 $dbSupportInfo = $checker->checkSqliteVersion( | ||||
|                     config('crater.min_sqlite_version') | ||||
|                 ); | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         if (! $dbSupportInfo['supported']) { | ||||
|             return $dbSupportInfo; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|     * Save the mail content to the .env file. | ||||
|     * | ||||
| @ -486,4 +551,35 @@ class EnvironmentManager | ||||
|             'old_default_driver' => $oldDefaultDriver, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Save sanctum statful domain to the .env file. | ||||
|      * | ||||
|      * @param DomainEnvironmentRequest $request | ||||
|      * @return array | ||||
|      */ | ||||
|     public function saveDomainVariables(DomainEnvironmentRequest $request) | ||||
|     { | ||||
|         try { | ||||
|             file_put_contents($this->envPath, str_replace( | ||||
|                 'SANCTUM_STATEFUL_DOMAINS='.env('SANCTUM_STATEFUL_DOMAINS'), | ||||
|                 'SANCTUM_STATEFUL_DOMAINS='.$request->app_domain, | ||||
|                 file_get_contents($this->envPath) | ||||
|             )); | ||||
|  | ||||
|             file_put_contents($this->envPath, str_replace( | ||||
|                 'SESSION_DOMAIN='.config('session.domain'), | ||||
|                 'SESSION_DOMAIN='.explode(':', $request->app_domain)[0], | ||||
|                 file_get_contents($this->envPath) | ||||
|             )); | ||||
|         } catch (Exception $e) { | ||||
|             return [ | ||||
|                 'error' => 'domain_verification_failed' | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'success' => 'domain_variable_save_successfully' | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -2,6 +2,8 @@ | ||||
|  | ||||
| namespace Crater\Space; | ||||
|  | ||||
| use SQLite3; | ||||
|  | ||||
| class RequirementsChecker | ||||
| { | ||||
|     /** | ||||
| @ -63,7 +65,7 @@ class RequirementsChecker | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function checkPHPversion(string $minPhpVersion = null) | ||||
|     public function checkPHPVersion(string $minPhpVersion = null) | ||||
|     { | ||||
|         $minVersionPhp = $minPhpVersion; | ||||
|         $currentPhpVersion = $this->getPhpVersionInfo(); | ||||
| @ -113,4 +115,112 @@ class RequirementsChecker | ||||
|     { | ||||
|         return $this->_minPhpVersion; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check PHP version requirement. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function checkMysqlVersion(string $minMysqlVersion = null) | ||||
|     { | ||||
|         $minVersionMysql = $minMysqlVersion; | ||||
|         $currentMysqlVersion = $this->getMysqlVersionInfo(); | ||||
|         $supported = false; | ||||
|  | ||||
|         if (version_compare($currentMysqlVersion, $minVersionMysql) >= 0) { | ||||
|             $supported = true; | ||||
|         } | ||||
|  | ||||
|         $phpStatus = [ | ||||
|             'current' => $currentMysqlVersion, | ||||
|             'minimum' => $minVersionMysql, | ||||
|             'supported' => $supported, | ||||
|         ]; | ||||
|  | ||||
|         return $phpStatus; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get current Mysql version information. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     private static function getMysqlVersionInfo() | ||||
|     { | ||||
|         $currentVersion = explode(' ', mysqli_get_client_info()); | ||||
|  | ||||
|         return $currentVersion[1]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check Sqlite version requirement. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function checkSqliteVersion(string $minSqliteVersion = null) | ||||
|     { | ||||
|         $minVersionSqlite = $minSqliteVersion; | ||||
|         $currentSqliteVersion = $this->getSqliteVersionInfo(); | ||||
|         $supported = false; | ||||
|  | ||||
|         if (version_compare($currentSqliteVersion, $minVersionSqlite) >= 0) { | ||||
|             $supported = true; | ||||
|         } | ||||
|  | ||||
|         $phpStatus = [ | ||||
|             'current' => $currentSqliteVersion, | ||||
|             'minimum' => $minVersionSqlite, | ||||
|             'supported' => $supported, | ||||
|         ]; | ||||
|  | ||||
|         return $phpStatus; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get current Sqlite version information. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     private static function getSqliteVersionInfo() | ||||
|     { | ||||
|         $currentVersion = SQLite3::version(); | ||||
|  | ||||
|         return $currentVersion['versionString']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check Pgsql version requirement. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function checkPgsqlVersion($conn, string $minPgsqlVersion = null) | ||||
|     { | ||||
|         $minVersionPgsql = $minPgsqlVersion; | ||||
|         $currentPgsqlVersion = $this->getPgsqlVersionInfo($conn); | ||||
|         $supported = false; | ||||
|  | ||||
|         if (version_compare($currentPgsqlVersion, $minVersionPgsql) >= 0) { | ||||
|             $supported = true; | ||||
|         } | ||||
|  | ||||
|         $phpStatus = [ | ||||
|             'current' => $currentPgsqlVersion, | ||||
|             'minimum' => $minVersionPgsql, | ||||
|             'supported' => $supported, | ||||
|         ]; | ||||
|  | ||||
|         return $phpStatus; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get current Pgsql version information. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     private static function getPgsqlVersionInfo($conn) | ||||
|     { | ||||
|         $currentVersion = pg_version($conn); | ||||
|  | ||||
|         return $currentVersion['server']; | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										1410
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						| @ -3,9 +3,27 @@ | ||||
| return [ | ||||
|  | ||||
|     /* | ||||
|     * Current version of the application. | ||||
|     * Minimum php version of the application. | ||||
|     */ | ||||
|     'version' => '4.0.0', | ||||
|     'min_php_version' => '7.4.0', | ||||
|  | ||||
|     /* | ||||
|     * Minimum mysql version of the application. | ||||
|     */ | ||||
|  | ||||
|     'min_mysql_version' => '5.7.7', | ||||
|  | ||||
|     /* | ||||
|     * Minimum pgsql version of the application. | ||||
|     */ | ||||
|  | ||||
|     'min_pgsql_version' => '9.2.0', | ||||
|  | ||||
|     /* | ||||
|     * Minimum sqlite version of the application. | ||||
|     */ | ||||
|  | ||||
|     'min_sqlite_version' => '3.24.0', | ||||
|  | ||||
|     /* | ||||
|     * List of languages supported by Crater. | ||||
|  | ||||
| @ -90,6 +90,12 @@ return [ | ||||
|             'app' => env('DROPBOX_APP'), | ||||
|             'root' => env('DROPBOX_ROOT'), | ||||
|         ], | ||||
|  | ||||
|         'views' => [ | ||||
|             'driver' => 'local', | ||||
|             'root' => resource_path('views'), | ||||
|         ], | ||||
|  | ||||
|     ], | ||||
|  | ||||
|     /* | ||||
|  | ||||
| @ -13,7 +13,7 @@ return [ | ||||
|     | | ||||
|     */ | ||||
|     'core' => [ | ||||
|         'minPhpVersion' => '7.2.0', | ||||
|         'minPhpVersion' => '7.4.0', | ||||
|     ], | ||||
|     'final' => [ | ||||
|         'key' => true, | ||||
|  | ||||
| @ -3,7 +3,6 @@ | ||||
| namespace Database\Factories; | ||||
|  | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\EstimateTemplate; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Database\Eloquent\Factories\Factory; | ||||
|  | ||||
| @ -76,7 +75,7 @@ class EstimateFactory extends Factory | ||||
|             'company_id' => User::where('role', 'super admin')->first()->company_id, | ||||
|             'user_id' => User::factory()->create(['role' => 'customer'])->id, | ||||
|             'status' => Estimate::STATUS_DRAFT, | ||||
|             'estimate_template_id' => EstimateTemplate::find(1) ?? EstimateTemplate::factory(), | ||||
|             'template_name' => 'estimate1', | ||||
|             'sub_total' => $this->faker->randomDigitNotNull, | ||||
|             'total' => $this->faker->randomDigitNotNull, | ||||
|             'discount_type' => $this->faker->randomElement(['percentage', 'fixed']), | ||||
|  | ||||
| @ -1,30 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Database\Factories; | ||||
|  | ||||
| use Crater\Models\EstimateTemplate; | ||||
| use Illuminate\Database\Eloquent\Factories\Factory; | ||||
|  | ||||
| class EstimateTemplateFactory extends Factory | ||||
| { | ||||
|     /** | ||||
|      * The name of the factory's corresponding model. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $model = EstimateTemplate::class; | ||||
|  | ||||
|     /** | ||||
|      * Define the model's default state. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function definition() | ||||
|     { | ||||
|         return [ | ||||
|             'path' => $this->faker->word, | ||||
|             'view' => $this->faker->word, | ||||
|             'name' => $this->faker->word, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @ -3,7 +3,6 @@ | ||||
| namespace Database\Factories; | ||||
|  | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\InvoiceTemplate; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Database\Eloquent\Factories\Factory; | ||||
|  | ||||
| @ -101,7 +100,7 @@ class InvoiceFactory extends Factory | ||||
|             'invoice_number' => 'INV-'.Invoice::getNextInvoiceNumber('INV'), | ||||
|             'reference_number' => Invoice::getNextInvoiceNumber('INV'), | ||||
|             'user_id' => User::factory()->create(['role' => 'customer'])->id, | ||||
|             'invoice_template_id' => InvoiceTemplate::find(1) ?? InvoiceTemplate::factory(), | ||||
|             'template_name' => 'invoice1', | ||||
|             'status' => Invoice::STATUS_DRAFT, | ||||
|             'tax_per_item' => 'NO', | ||||
|             'discount_per_item' => 'NO', | ||||
|  | ||||
| @ -1,30 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Database\Factories; | ||||
|  | ||||
| use Crater\Models\InvoiceTemplate; | ||||
| use Illuminate\Database\Eloquent\Factories\Factory; | ||||
|  | ||||
| class InvoiceTemplateFactory extends Factory | ||||
| { | ||||
|     /** | ||||
|      * The name of the factory's corresponding model. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $model = InvoiceTemplate::class; | ||||
|  | ||||
|     /** | ||||
|      * Define the model's default state. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function definition() | ||||
|     { | ||||
|         return [ | ||||
|             'path' => $this->faker->word, | ||||
|             'view' => $this->faker->word, | ||||
|             'name' => $this->faker->word, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @ -34,8 +34,6 @@ class CreateInvoicesTable extends Migration | ||||
|             $table->boolean('sent')->default(false); | ||||
|             $table->boolean('viewed')->default(false); | ||||
|             $table->string('unique_hash')->nullable(); | ||||
|             $table->integer('invoice_template_id')->unsigned()->nullable(); | ||||
|             $table->foreign('invoice_template_id')->references('id')->on('invoice_templates'); | ||||
|             $table->integer('user_id')->unsigned()->nullable(); | ||||
|             $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|             $table->integer('company_id')->unsigned()->nullable(); | ||||
|  | ||||
| @ -32,8 +32,6 @@ class CreateEstimatesTable extends Migration | ||||
|             $table->string('unique_hash')->nullable(); | ||||
|             $table->integer('user_id')->unsigned()->nullable(); | ||||
|             $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|             $table->integer('estimate_template_id')->unsigned()->nullable(); | ||||
|             $table->foreign('estimate_template_id')->references('id')->on('estimate_templates'); | ||||
|             $table->integer('company_id')->unsigned()->nullable(); | ||||
|             $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); | ||||
|             $table->timestamps(); | ||||
|  | ||||
| @ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| use Illuminate\Support\Facades\Schema; | ||||
| 
 | ||||
| class CreateInvoiceTemplatesTable extends Migration | ||||
| class AddTemplateNameToInvoicesTable extends Migration | ||||
| { | ||||
|     /** | ||||
|      * Run the migrations. | ||||
| @ -13,12 +13,8 @@ class CreateInvoiceTemplatesTable extends Migration | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create('invoice_templates', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->string('name')->nullable(); | ||||
|             $table->string('view'); | ||||
|             $table->string('path'); | ||||
|             $table->timestamps(); | ||||
|         Schema::table('invoices', function (Blueprint $table) { | ||||
|             $table->string('template_name')->nullable(); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| @ -29,6 +25,8 @@ class CreateInvoiceTemplatesTable extends Migration | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::dropIfExists('invoice_templates'); | ||||
|         Schema::table('invoices', function (Blueprint $table) { | ||||
|             $table->dropColumn('template_name'); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| use Illuminate\Support\Facades\Schema; | ||||
| 
 | ||||
| class CreateEstimateTemplatesTable extends Migration | ||||
| class AddTemplateNameToEstimatesTable extends Migration | ||||
| { | ||||
|     /** | ||||
|      * Run the migrations. | ||||
| @ -13,12 +13,8 @@ class CreateEstimateTemplatesTable extends Migration | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create('estimate_templates', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->string('name')->nullable(); | ||||
|             $table->string('view'); | ||||
|             $table->string('path'); | ||||
|             $table->timestamps(); | ||||
|         Schema::table('estimates', function (Blueprint $table) { | ||||
|             $table->string('template_name')->nullable(); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| @ -29,6 +25,8 @@ class CreateEstimateTemplatesTable extends Migration | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::dropIfExists('estimate_templates'); | ||||
|         Schema::table('estimates', function (Blueprint $table) { | ||||
|             $table->dropColumn('template_name'); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,63 @@ | ||||
| <?php | ||||
|  | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| use Illuminate\Support\Facades\Schema; | ||||
|  | ||||
| class RemoveTemplateIdFromInvoicesAndEstimatesTable extends Migration | ||||
| { | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         if (Schema::hasColumn('invoices', 'invoice_template_id')) { | ||||
|             $invoices = Invoice::all(); | ||||
|  | ||||
|             $invoices->map(function ($invoice) { | ||||
|                 $invoice->template_name = 'invoice'.$invoice->invoice_template_id; | ||||
|                 $invoice->save(); | ||||
|             }); | ||||
|  | ||||
|             Schema::table('invoices', function (Blueprint $table) { | ||||
|                 if (config('database.default') !== 'sqlite') { | ||||
|                     $table->dropForeign(['invoice_template_id']); | ||||
|                 } | ||||
|                 $table->dropColumn('invoice_template_id'); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         if (Schema::hasColumn('estimates', 'estimate_template_id')) { | ||||
|             $estimates = Estimate::all(); | ||||
|  | ||||
|             $estimates->map(function ($estimate) { | ||||
|                 $estimate->template_name = 'estimate'.$estimate->estimate_template_id; | ||||
|                 $estimate->save(); | ||||
|             }); | ||||
|  | ||||
|             Schema::table('estimates', function (Blueprint $table) { | ||||
|                 if (config('database.default') !== 'sqlite') { | ||||
|                     $table->dropForeign(['estimate_template_id']); | ||||
|                 } | ||||
|                 $table->dropColumn('estimate_template_id'); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         Schema::dropIfExists('invoice_templates'); | ||||
|         Schema::dropIfExists('estimate_templates'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,27 @@ | ||||
| <?php | ||||
|  | ||||
| use Crater\Models\Setting; | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
|  | ||||
| class UpdateCraterVersion420 extends Migration | ||||
| { | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Setting::setSetting('version', '4.2.0'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
| } | ||||
| @ -17,8 +17,6 @@ class DatabaseSeeder extends Seeder | ||||
|         $this->call(CurrenciesTableSeeder::class); | ||||
|         $this->call(DefaultSettingsSeeder::class); | ||||
|         $this->call(CountriesTableSeeder::class); | ||||
|         $this->call(EstimateTemplateSeeder::class); | ||||
|         $this->call(InvoiceTemplateSeeder::class); | ||||
|         $this->call(PaymentMethodSeeder::class); | ||||
|         $this->call(UnitSeeder::class); | ||||
|     } | ||||
|  | ||||
| @ -1,35 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Database\Seeders; | ||||
|  | ||||
| use Crater\Models\EstimateTemplate; | ||||
| use Illuminate\Database\Seeder; | ||||
|  | ||||
| class EstimateTemplateSeeder extends Seeder | ||||
| { | ||||
|     /** | ||||
|      * Run the database seeds. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function run() | ||||
|     { | ||||
|         EstimateTemplate::create([ | ||||
|             'name' => 'Template 1', | ||||
|             'view' => 'estimate1', | ||||
|             'path' => '/assets/img/PDF/Template1.png', | ||||
|         ]); | ||||
|  | ||||
|         EstimateTemplate::create([ | ||||
|             'name' => 'Template 2', | ||||
|             'view' => 'estimate2', | ||||
|             'path' => '/assets/img/PDF/Template2.png', | ||||
|         ]); | ||||
|  | ||||
|         EstimateTemplate::create([ | ||||
|             'name' => 'Template 3', | ||||
|             'view' => 'estimate3', | ||||
|             'path' => '/assets/img/PDF/Template3.png', | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,35 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Database\Seeders; | ||||
|  | ||||
| use Crater\Models\InvoiceTemplate; | ||||
| use Illuminate\Database\Seeder; | ||||
|  | ||||
| class InvoiceTemplateSeeder extends Seeder | ||||
| { | ||||
|     /** | ||||
|      * Run the database seeds. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function run() | ||||
|     { | ||||
|         InvoiceTemplate::create([ | ||||
|             'name' => 'Template 1', | ||||
|             'view' => 'invoice1', | ||||
|             'path' => '/assets/img/PDF/Template1.png', | ||||
|         ]); | ||||
|  | ||||
|         InvoiceTemplate::create([ | ||||
|             'name' => ' Template 2', | ||||
|             'view' => 'invoice2', | ||||
|             'path' => '/assets/img/PDF/Template2.png', | ||||
|         ]); | ||||
|  | ||||
|         InvoiceTemplate::create([ | ||||
|             'name' => 'Template 3', | ||||
|             'view' => 'invoice3', | ||||
|             'path' => '/assets/img/PDF/Template3.png', | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										2
									
								
								public/assets/css/crater.css
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB | 
| Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB | 
| Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/img/PDF/invoice1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 94 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/img/PDF/invoice2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 84 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/img/PDF/invoice3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 104 KiB | 
| @ -1,4 +1,4 @@ | ||||
| { | ||||
|     "/assets/js/app.js": "/assets/js/app.js?id=ccf2d83d1f924a997810", | ||||
|     "/assets/css/crater.css": "/assets/css/crater.css?id=6ba60df7635dc2f5fbc5" | ||||
|     "/assets/js/app.js": "/assets/js/app.js?id=d81a97bae3dfe124894b", | ||||
|     "/assets/css/crater.css": "/assets/css/crater.css?id=16fbf5d814f29e408426" | ||||
| } | ||||
|  | ||||
							
								
								
									
										2
									
								
								resources/assets/js/bootstrap.js
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -126,9 +126,11 @@ global.axios.interceptors.response.use(undefined, function (err) { | ||||
|   } else { | ||||
|     if ( | ||||
|       err.response.data && | ||||
|       err.config.url !== '/api/v1/auth/check' && | ||||
|       (err.response.statusText === 'Unauthorized' || | ||||
|         err.response.data === ' Unauthorized.') | ||||
|     ) { | ||||
|       console.log(err.response) | ||||
|       // Unauthorized and log out | ||||
|       store.dispatch('notification/showNotification', { | ||||
|         type: 'error', | ||||
|  | ||||
| @ -71,7 +71,7 @@ | ||||
|                       ? notificationMessage | ||||
|                       : success | ||||
|                       ? 'Successful' | ||||
|                       : 'Somthing went wrong' | ||||
|                       : 'Something went wrong' | ||||
|                   }} | ||||
|                 </p> | ||||
|               </div> | ||||
|  | ||||
| @ -7,14 +7,19 @@ | ||||
|           :key="index" | ||||
|           :class="{ | ||||
|             'border border-solid border-primary-500': | ||||
|               selectedTemplate === template.id, | ||||
|               selectedTemplate === template.name, | ||||
|           }" | ||||
|           class="relative flex flex-col m-2 border border-gray-200 border-solid cursor-pointer  hover:border-primary-300" | ||||
|           @click="selectedTemplate = template.id" | ||||
|         > | ||||
|           <img :src="template.path" alt="template-image" /> | ||||
|           <img | ||||
|             v-if="selectedTemplate === template.id" | ||||
|             :src="template.path" | ||||
|             :alt="template.name" | ||||
|             class="w-full" | ||||
|             @click="selectedTemplate = template.name" | ||||
|           /> | ||||
|           <img | ||||
|             v-if="selectedTemplate === template.name" | ||||
|             :alt="template.name" | ||||
|             class="absolute z-10 w-5 h-5 text-primary-500" | ||||
|             style="top: -6px; right: -5px" | ||||
|             src="/assets/img/tick.png" | ||||
| @ -24,8 +29,8 @@ | ||||
|               'w-full p-1 bg-gray-200 text-sm text-center absolute bottom-0 left-0', | ||||
|               { | ||||
|                 'text-primary-500 bg-primary-100': | ||||
|                   selectedTemplate === template.id, | ||||
|                 'text-gray-600': selectedTemplate != template.id, | ||||
|                   selectedTemplate === template.name, | ||||
|                 'text-gray-600': selectedTemplate != template.name, | ||||
|               }, | ||||
|             ]" | ||||
|           > | ||||
| @ -53,16 +58,16 @@ import { mapActions, mapGetters } from 'vuex' | ||||
| export default { | ||||
|   data() { | ||||
|     return { | ||||
|       selectedTemplate: 1, | ||||
|       selectedTemplate: null, | ||||
|       isLoading: false, | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapGetters('modal', ['modalData']), | ||||
|     ...mapGetters('estimate', ['getTemplateId']), | ||||
|     ...mapGetters('estimate', ['getTemplateName']), | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.selectedTemplate = this.getTemplateId | ||||
|     this.selectedTemplate = this.getTemplateName | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('estimate', ['setTemplate']), | ||||
| @ -77,7 +82,7 @@ export default { | ||||
|       } | ||||
|     }, | ||||
|     closeEstimateModal() { | ||||
|       this.selectedTemplate = this.getTemplateId | ||||
|       this.selectedTemplate = this.getTemplateName | ||||
|       this.closeModal() | ||||
|       this.resetModalData() | ||||
|     }, | ||||
|  | ||||
| @ -7,14 +7,19 @@ | ||||
|           :key="index" | ||||
|           :class="{ | ||||
|             'border border-solid border-primary-500': | ||||
|               selectedTemplate === template.id, | ||||
|               selectedTemplate === template.name, | ||||
|           }" | ||||
|           class="relative flex flex-col m-2 border border-gray-200 border-solid cursor-pointer  hover:border-primary-300" | ||||
|           @click="selectedTemplate = template.id" | ||||
|         > | ||||
|           <img :src="template.path" alt="template-image" /> | ||||
|           <img | ||||
|             v-if="selectedTemplate === template.id" | ||||
|             :src="template.path" | ||||
|             :alt="template.name" | ||||
|             class="w-full" | ||||
|             @click="selectedTemplate = template.name" | ||||
|           /> | ||||
|           <img | ||||
|             v-if="selectedTemplate === template.name" | ||||
|             :alt="template.name" | ||||
|             class="absolute z-10 w-5 h-5 text-primary-500" | ||||
|             style="top: -6px; right: -5px" | ||||
|             src="/assets/img/tick.png" | ||||
| @ -53,16 +58,16 @@ import { mapActions, mapGetters } from 'vuex' | ||||
| export default { | ||||
|   data() { | ||||
|     return { | ||||
|       selectedTemplate: 1, | ||||
|       selectedTemplate: null, | ||||
|       isLoading: false, | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapGetters('modal', ['modalData']), | ||||
|     ...mapGetters('invoice', ['getTemplateId']), | ||||
|     ...mapGetters('invoice', ['getTemplateName']), | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.selectedTemplate = this.getTemplateId | ||||
|     this.selectedTemplate = this.getTemplateName | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('invoice', ['setTemplate']), | ||||
| @ -77,7 +82,7 @@ export default { | ||||
|       } | ||||
|     }, | ||||
|     closeInvoiceModal() { | ||||
|       this.selectedTemplate = this.getTemplateId | ||||
|       this.selectedTemplate = this.getTemplateName | ||||
|       this.closeModal() | ||||
|       this.resetModalData() | ||||
|     }, | ||||
|  | ||||
| @ -19,7 +19,7 @@ export default { | ||||
|     stepHeadingContainer: 'heading-section', | ||||
|     stepTitle: 'text-2xl not-italic font-semibold leading-7 text-black', | ||||
|     stepDescription: | ||||
|       'w-full mt-2.5 mb-8 text-sm not-italic leading-snug text-gray-500 lg:w-7/12 md:w-7/12 sm:w-7/12', | ||||
|       'w-full mt-2.5 mb-8 text-sm not-italic text-gray-600 lg:w-7/12 md:w-7/12 sm:w-7/12', | ||||
|   }, | ||||
|   variants: {}, | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import i18n from '../plugins/i18n'; | ||||
| import i18n from '../plugins/i18n' | ||||
|  | ||||
| export default { | ||||
|   addClass(el, className) { | ||||
| @ -142,12 +142,20 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   checkValidDomainUrl(url) { | ||||
|     if (url.includes('localhost')) { | ||||
|     if (url.includes('localhost') || url.includes('127.0.0.1')) { | ||||
|       return true | ||||
|     } | ||||
|  | ||||
|     let pattern = new RegExp( | ||||
|       '^([0-9A-Za-z-\\.@:%_+~#=]+)+((\\.[a-zA-Z]{2,3})+)(/(.)*)?(\\?(.)*)?' | ||||
|     ) | ||||
|       '^(https?:\\/\\/)?' + // protocol | ||||
|       '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name | ||||
|       '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address | ||||
|       '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path | ||||
|       '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string | ||||
|       '(\\#[-a-z\\d_]*)?$', | ||||
|       'i' | ||||
|     ) // fragment locator | ||||
|  | ||||
|     return !!pattern.test(url) | ||||
|   }, | ||||
|  | ||||
|  | ||||
| @ -87,7 +87,7 @@ | ||||
|     "choose_note": "اختر ملاحظة", | ||||
|     "no_note_found": "لم يتم العثور على الملاحظة", | ||||
|     "insert_note": "أدخل ملاحظة", | ||||
|     "copied_pdf_url_clipboard": "Copied PDF url to clipboard!" | ||||
|     "copied_pdf_url_clipboard": "تم نسخ رابط PDF إلى الحافظة!" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "select_year": "اختر السنة", | ||||
| @ -178,8 +178,8 @@ | ||||
|     "copy_billing_address": "نسخ من عنوان الفوترة", | ||||
|     "no_customers": "لا يوجد عملاء حتى الآن!", | ||||
|     "no_customers_found": "لم يتم الحصول على عملاء!", | ||||
|     "no_contact": "No contact", | ||||
|     "no_contact_name": "No contact name", | ||||
|     "no_contact": "ليست هناك جهات اتصال", | ||||
|     "no_contact_name": "اسم جهة الاتصال غير موجود", | ||||
|     "list_of_customers": "سوف يحتوي هذا القسم على قائمة العملاء.", | ||||
|     "primary_display_name": "اسم العرض الرئيسي", | ||||
|     "select_currency": "اختر العملة", | ||||
| @ -203,7 +203,7 @@ | ||||
|     "added_on": "أضيف في", | ||||
|     "price": "السعر", | ||||
|     "date_of_creation": "تاريخ الإنشاء", | ||||
|     "not_selected": "No item selected", | ||||
|     "not_selected": "لم يتم إختيار أي عنصر", | ||||
|     "action": "إجراء", | ||||
|     "add_item": "إضافة صنف", | ||||
|     "save_item": "حفظ الصنف", | ||||
| @ -274,7 +274,7 @@ | ||||
|       "required": "حقل مطلوب" | ||||
|     }, | ||||
|     "accepted": "مقبول", | ||||
|     "rejected": "Rejected", | ||||
|     "rejected": "مرفوض", | ||||
|     "sent": "مرسل", | ||||
|     "draft": "مسودة", | ||||
|     "declined": "مرفوض", | ||||
| @ -321,9 +321,9 @@ | ||||
|     "all": "الكل", | ||||
|     "paid": "مدفوع", | ||||
|     "unpaid": "غير مدفوع", | ||||
|     "viewed": "Viewed", | ||||
|     "viewed": "شوهد", | ||||
|     "overdue": "Overdue", | ||||
|     "completed": "Completed", | ||||
|     "completed": "اكتمل", | ||||
|     "customer": "العميل", | ||||
|     "paid_status": "حالة الدفع", | ||||
|     "ref_no": "رقم المرجع.", | ||||
| @ -442,8 +442,8 @@ | ||||
|     "update_payment": "تحديث الدفعة", | ||||
|     "payment": "دفعة | مدفوعات", | ||||
|     "no_payments": "لا يوجد مدفوعات حتى الآن!", | ||||
|     "not_selected": "Not selected", | ||||
|     "no_invoice": "No invoice", | ||||
|     "not_selected": "لم يتم تحديد", | ||||
|     "no_invoice": "لا توجد فاتورة", | ||||
|     "no_matching_payments": "لا توجد مدفوعات مطابقة!", | ||||
|     "list_of_payments": "سوف تحتوي هذه القائمة على مدفوعات الفواتير.", | ||||
|     "select_payment_mode": "اختر طريقة الدفع", | ||||
| @ -473,7 +473,7 @@ | ||||
|     "receipt": "سند القبض", | ||||
|     "amount": "المبلغ المطلوب", | ||||
|     "action": "إجراء", | ||||
|     "not_selected": "Not selected", | ||||
|     "not_selected": "لم يتم تحديد", | ||||
|     "note": "ملاحظة", | ||||
|     "category_id": "رمز الفئة", | ||||
|     "date": "تاريخ النفقات", | ||||
| @ -751,13 +751,13 @@ | ||||
|         "title": "الفواتير", | ||||
|         "notes": "ملاحظات", | ||||
|         "invoice_prefix": "بادئة رقم الفاتورة", | ||||
|         "invoice_number_length": "Invoice number length", | ||||
|         "invoice_number_length": "طول رقم الفاتورة", | ||||
|         "default_invoice_email_body": "نص الفاتورة الافتراضي للبريد الإلكتروني", | ||||
|         "invoice_settings": "إعدادات الفاتورة", | ||||
|         "autogenerate_invoice_number": "ترقيم آلي للفاتورة", | ||||
|         "invoice_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام الفاتورة تلقائيًا في كل مرة تقوم فيها بإنشاء فاتورة جديدة.", | ||||
|         "invoice_email_attachment": "Send invoices as attachments", | ||||
|         "invoice_email_attachment_setting_description": "Enable this if you want to send invoices as email attachment. Please note that 'View Invoice' button in emails will not be displayed anymore when enabled.", | ||||
|         "invoice_email_attachment": "إرسال الفواتير كمرفقات", | ||||
|         "invoice_email_attachment_setting_description": "تفعيل هذا إذا كنت ترغب في إرسال الفواتير كمرفق بريد إلكتروني. يرجى ملاحظة أن زر \"عرض الفواتير\" في رسائل البريد الإلكتروني لن يتم عرضه بعد الآن عند التفعيل.", | ||||
|         "enter_invoice_prefix": "أدخل بادئة رقم الفاتورة", | ||||
|         "terms_and_conditions": "الأحكام والشروط", | ||||
|         "company_address_format": "تنسيق عنوان الشركة", | ||||
| @ -768,13 +768,13 @@ | ||||
|       "estimates": { | ||||
|         "title": "التقديرات", | ||||
|         "estimate_prefix": "بادئة رقم التقدير", | ||||
|         "estimate_number_length": "Estimate number length", | ||||
|         "estimate_number_length": "تقدير طول العدد", | ||||
|         "default_estimate_email_body": "تقدير نص البريد الإلكتروني الافتراضي", | ||||
|         "estimate_settings": "إعدادت التقدير", | ||||
|         "autogenerate_estimate_number": "ترقيم آلي للتقدير", | ||||
|         "estimate_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام التقديرات تلقائيًا في كل مرة تقوم فيها بإنشاء تقدير جديد.", | ||||
|         "estimate_email_attachment": "Send estimates as attachments", | ||||
|         "estimate_email_attachment_setting_description": "Enable this if you want to send the estimates as an email attachment. Please note that 'View Estimate' button in emails will not be displayed anymore when enabled.", | ||||
|         "estimate_email_attachment": "إرسال التقديرات كمرفقات", | ||||
|         "estimate_email_attachment_setting_description": "تفعيل هذا إذا كنت ترغب في إرسال الفواتير كمرفق بريد إلكتروني. يرجى ملاحظة أن زر \"عرض التقديرات\" في رسائل البريد الإلكتروني لن يتم عرضه بعد الآن عند التفعيل.", | ||||
|         "enter_estimate_prefix": "أدخل بادئة رقم التقدير", | ||||
|         "estimate_setting_updated": "تم تحديث إعدادات التقدير بنجاح", | ||||
|         "company_address_format": "تنسيق عنوان الشركة", | ||||
| @ -785,13 +785,13 @@ | ||||
|         "title": "المدفوعات", | ||||
|         "description": "أساليب المعاملات المتعلقة بالمدفوعات", | ||||
|         "payment_prefix": "بادئة رقم الدفعة", | ||||
|         "payment_number_length": "Payment number lenght", | ||||
|         "payment_number_length": "طول رقم الدفع", | ||||
|         "default_payment_email_body": "نص البريد الإلكتروني للدفع الافتراضي", | ||||
|         "payment_settings": "إعدادات الدفعة", | ||||
|         "autogenerate_payment_number": "ترقيم آلي للمدفوعات", | ||||
|         "payment_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام الدفعة تلقائيًا في كل مرة تقوم فيها بإنشاء دفعة جديدة.", | ||||
|         "payment_email_attachment": "Send payments as attachments", | ||||
|         "payment_email_attachment_setting_description": "Enable this if you want to send the payment receipts as an email attachment. Please note that 'View Payment' button in emails will not be displayed anymore when enabled.", | ||||
|         "payment_email_attachment": "إرسال المدفوعات كمرفقات", | ||||
|         "payment_email_attachment_setting_description": "تفعيل هذا إذا كنت ترغب في إرسال الفواتير كمرفق بريد إلكتروني. يرجى ملاحظة أن زر \"عرض المدفوعات\" في رسائل البريد الإلكتروني لن يتم عرضه بعد الآن عند التفعيل.", | ||||
|         "enter_payment_prefix": "أدخل بادئة رقم الدفعة", | ||||
|         "payment_setting_updated": "تم تحديث إعدادات الدفعة بنجاح", | ||||
|         "payment_modes": "طرق الدفع", | ||||
| @ -931,7 +931,7 @@ | ||||
|       "download_zip_file": "تنزيل ملف ZIP", | ||||
|       "unzipping_package": "حزمة فك الضغط", | ||||
|       "copying_files": "نسخ الملفات", | ||||
|       "deleting_files": "Deleting Unused files", | ||||
|       "deleting_files": "حذف الملفات الغير مستخدمة", | ||||
|       "running_migrations": "إدارة عمليات الترحيل", | ||||
|       "finishing_update": "تحديث التشطيب", | ||||
|       "update_failed": "فشل التحديث", | ||||
| @ -1001,19 +1001,19 @@ | ||||
|       "default_driver": "برنامج التشغيل الافتراضي", | ||||
|       "is_default": "أمر افتراضي", | ||||
|       "set_default_disk": "تعيين القرص الافتراضي", | ||||
|       "set_default_disk_confirm": "This disk will be set as default and all the new PDFs will be saved on this disk", | ||||
|       "success_set_default_disk": "Disk set as default successfully", | ||||
|       "set_default_disk_confirm": "سيتم تعيين هذا القرص كالافتراضي وسيتم حفظ جميع ملفات PDF الجديدة على هذا القرص", | ||||
|       "success_set_default_disk": "تم تعيين القرص كالافتراضي بنجاح", | ||||
|       "save_pdf_to_disk": "حفظ ملفات PDF على القرص", | ||||
|       "disk_setting_description": "قم بتمكين هذا ، إذا كنت ترغب في حفظ نسخة من كل فاتورة ، تقدير وإيصال دفع PDF على القرص الافتراضي الخاص بك تلقائيًا. سيؤدي تشغيل هذا الخيار إلى تقليل وقت التحميل عند عرض ملفات PDF.", | ||||
|       "select_disk": "حدد القرص", | ||||
|       "disk_settings": "إعدادات القرص", | ||||
|       "confirm_delete": "Your existing files & folders in the specified disk will not be affected but your disk configuration will be deleted from Crater", | ||||
|       "confirm_delete": "لن تتأثر الملفات والمجلدات الموجودة في القرص المحدد ولكن سيتم حذف اعدادات القرص الخاص بك من Crater", | ||||
|       "action": "عمل", | ||||
|       "edit_file_disk": "Edit File Disk", | ||||
|       "edit_file_disk": "تعديل قرص الملف", | ||||
|       "success_create": "تمت إضافة القرص بنجاح", | ||||
|       "success_update": "Disk updated successfully", | ||||
|       "success_update": "تم تحديث القرص بنجاح", | ||||
|       "error": "فشل إضافة القرص", | ||||
|       "deleted_message": "File Disk deleted successfully", | ||||
|       "deleted_message": "تم حذف ملف القرص بنجاح", | ||||
|       "disk_variables_save_successfully": "تم تكوين القرص بنجاح", | ||||
|       "disk_variables_save_error": "فشل تكوين القرص.", | ||||
|       "invalid_disk_credentials": "بيانات اعتماد غير صالحة للقرص المحدد" | ||||
| @ -1152,7 +1152,7 @@ | ||||
|     "ref_number_maxlength": "يجب ألا يزيد الرقم المرجعي عن 255 حرفاً.", | ||||
|     "prefix_maxlength": "يجب ألا تزيد البادئة عن 5 أحرف.", | ||||
|     "something_went_wrong": "خطأ غير معروف!", | ||||
|     "number_length_minvalue": "Number lenght should be greater than 0" | ||||
|     "number_length_minvalue": "يجب أن تكون قيمة الرقم أكبر من الصفر" | ||||
|   }, | ||||
|   "pdf_estimate_label": "تقدير", | ||||
|   "pdf_estimate_number": "رقم تقدير", | ||||
| @ -1170,7 +1170,7 @@ | ||||
|   "pdf_amount_label": "المبلغ المطلوب", | ||||
|   "pdf_subtotal": "المجموع الفرعي", | ||||
|   "pdf_total": "الإجمالي", | ||||
|   "pdf_payment_label": "Payment", | ||||
|   "pdf_payment_label": "الدفع", | ||||
|   "pdf_payment_receipt_label": "ايصال الدفع", | ||||
|   "pdf_payment_date": "تاريخ الدفع", | ||||
|   "pdf_payment_number": "رقم الدفعة", | ||||
| @ -1179,9 +1179,9 @@ | ||||
|   "pdf_expense_report_label": "تقرير المصاريف", | ||||
|   "pdf_total_expenses_label": "مجموع المصاريف", | ||||
|   "pdf_profit_loss_label": "تقرير الارباح و الخسائر", | ||||
|   "pdf_sales_customers_label": "Sales Customer Report", | ||||
|   "pdf_sales_items_label": "Sales Item Report", | ||||
|   "pdf_tax_summery_label": "Tax Summary Report", | ||||
|   "pdf_sales_customers_label": "تقرير عملاء المبيعات", | ||||
|   "pdf_sales_items_label": "تقرير عناصر المبيعات", | ||||
|   "pdf_tax_summery_label": "تقرير ملخص الضرائب", | ||||
|   "pdf_income_label": "الايرادات", | ||||
|   "pdf_net_profit_label": "صافي الأرباح", | ||||
|   "pdf_customer_sales_report": "تقرير المبيعات: حسب العميل", | ||||
|  | ||||
| @ -1071,6 +1071,14 @@ | ||||
|       "permission_confirm_desc": "Folder permission check failed", | ||||
|       "permission_desc": "Below is the list of folder permissions which are required in order for the app to work. If the permission check fails, make sure to update your folder permissions." | ||||
|     }, | ||||
|     "verify_domain": { | ||||
|       "title": "Domain Verification", | ||||
|       "desc": "Crater uses Session based authentication which requires domain verification for security purposes. Please enter the domain on which you will be accessing your web application.", | ||||
|       "app_domain": "App Domain", | ||||
|       "verify_now": "Verify Now", | ||||
|       "success": "Domain Verify Successfully.", | ||||
|       "verify_and_continue": "Verify And Continue" | ||||
|     }, | ||||
|     "mail": { | ||||
|       "host": "Mail Host", | ||||
|       "port": "Mail Port", | ||||
| @ -1091,19 +1099,22 @@ | ||||
|     }, | ||||
|     "req": { | ||||
|       "system_req": "System Requirements", | ||||
|       "php_req_version": "Php (version {version} required)", | ||||
|       "php_req_version": "Minimum Php (version {version} required)", | ||||
|       "check_req": "Check Requirements", | ||||
|       "system_req_desc": "Crater has a few server requirements. Make sure that your server has the required php version and all the extensions mentioned below." | ||||
|     }, | ||||
|     "errors": { | ||||
|       "migrate_failed": "Migrate Failed", | ||||
|       "domain_verification_failed": "Domain verification failed", | ||||
|       "database_variables_save_error": "Cannot write configuration to .env file. Please check its file permissions", | ||||
|       "mail_variables_save_error": "Email configuration failed.", | ||||
|       "connection_failed": "Database connection failed", | ||||
|       "database_should_be_empty": "Database should be empty" | ||||
|       "database_should_be_empty": "Database should be empty", | ||||
|       "minimum_version_requirement": "Minimum {name} version {version} required." | ||||
|     }, | ||||
|     "success": { | ||||
|       "mail_variables_save_successfully": "Email configured successfully", | ||||
|       "domain_variable_save_successfully": "Domain configured successfully", | ||||
|       "database_variables_save_successfully": "Database configured successfully." | ||||
|     } | ||||
|   }, | ||||
|  | ||||
| @ -87,7 +87,7 @@ | ||||
|     "choose_note": "Elegir nota", | ||||
|     "no_note_found": "No se encontró ninguna nota", | ||||
|     "insert_note": "Insertar una nota", | ||||
|     "copied_pdf_url_clipboard": "Copied PDF url to clipboard!" | ||||
|     "copied_pdf_url_clipboard": "Copiar Url al portapapeles" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "select_year": "Seleccionar año", | ||||
|  | ||||
							
								
								
									
										1197
									
								
								resources/assets/js/plugins/fa.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -43,7 +43,7 @@ | ||||
|     "view": "Afficher", | ||||
|     "add_new_item": "Nouvel article", | ||||
|     "clear_all": "Tout supprimer", | ||||
|     "showing": "Montant", | ||||
|     "showing": "Affichage", | ||||
|     "of": "sur", | ||||
|     "actions": "Actions", | ||||
|     "subtotal": "SOUS-TOTAL", | ||||
| @ -54,9 +54,9 @@ | ||||
|     "total_amount": "TOTAL TTC", | ||||
|     "bill_to": "Facturer à", | ||||
|     "ship_to": "Expédier à", | ||||
|     "due": "Dû", | ||||
|     "due": "En cours", | ||||
|     "draft": "Brouillon", | ||||
|     "sent": "Envoyée", | ||||
|     "sent": "Envoyé", | ||||
|     "all": "Tout", | ||||
|     "select_all": "Tout sélectionner", | ||||
|     "choose_file": "Cliquez ici pour choisir un fichier", | ||||
| @ -87,7 +87,7 @@ | ||||
|     "choose_note": "Choisissez une note", | ||||
|     "no_note_found": "Aucune note trouvée", | ||||
|     "insert_note": "Insérer une note", | ||||
|     "copied_pdf_url_clipboard": "Copied PDF url to clipboard!" | ||||
|     "copied_pdf_url_clipboard": "L'adresse du PDF a été copiée." | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "select_year": "Sélectionnez l'année", | ||||
| @ -178,8 +178,8 @@ | ||||
|     "copy_billing_address": "Copier depuis l'adresse de facturation", | ||||
|     "no_customers": "Vous n’avez pas encore de clients !", | ||||
|     "no_customers_found": "Aucun client !", | ||||
|     "no_contact": "No contact", | ||||
|     "no_contact_name": "No contact name", | ||||
|     "no_contact": "-", | ||||
|     "no_contact_name": "-", | ||||
|     "list_of_customers": "Ajoutez des clients et retrouvez-les ici.", | ||||
|     "primary_display_name": "Nom d'affichage principal", | ||||
|     "select_currency": "Sélectionnez la devise", | ||||
| @ -203,7 +203,7 @@ | ||||
|     "added_on": "Ajouté le", | ||||
|     "price": "Prix", | ||||
|     "date_of_creation": "Date de création", | ||||
|     "not_selected": "No item selected", | ||||
|     "not_selected": "Aucun article sélectionné", | ||||
|     "action": "action", | ||||
|     "add_item": "Nouvel article", | ||||
|     "save_item": "Enregistrer", | ||||
| @ -249,7 +249,7 @@ | ||||
|     "expiry_date": "Date d'expiration", | ||||
|     "status": "Statut", | ||||
|     "add_tax": "Ajouter une taxe", | ||||
|     "amount": " ", | ||||
|     "amount": "Montant", | ||||
|     "action": "action", | ||||
|     "notes": "Notes de bas de page", | ||||
|     "tax": "Taxe", | ||||
| @ -274,7 +274,7 @@ | ||||
|       "required": "Champ requis" | ||||
|     }, | ||||
|     "accepted": "Accepté", | ||||
|     "rejected": "Rejected", | ||||
|     "rejected": "Refusé", | ||||
|     "sent": "Envoyé", | ||||
|     "draft": "Brouillon", | ||||
|     "declined": "Refusé", | ||||
| @ -321,9 +321,9 @@ | ||||
|     "all": "Toutes", | ||||
|     "paid": "Payé", | ||||
|     "unpaid": "Non payé", | ||||
|     "viewed": "Viewed", | ||||
|     "overdue": "Overdue", | ||||
|     "completed": "Completed", | ||||
|     "viewed": "Consultée", | ||||
|     "overdue": "En retard", | ||||
|     "completed": "Payée", | ||||
|     "customer": "CLIENT", | ||||
|     "paid_status": "État du paiement", | ||||
|     "ref_no": "Réf.", | ||||
| @ -342,7 +342,7 @@ | ||||
|     "due_date": "Date d'échéance", | ||||
|     "status": "Statut", | ||||
|     "add_tax": "Ajouter une taxe", | ||||
|     "amount": " ", | ||||
|     "amount": "Montant", | ||||
|     "action": "action", | ||||
|     "notes": "Notes de bas de page", | ||||
|     "view": "Afficher", | ||||
| @ -442,8 +442,8 @@ | ||||
|     "update_payment": "Enregistrer", | ||||
|     "payment": "Paiement | Paiements", | ||||
|     "no_payments": "Aucun paiement", | ||||
|     "not_selected": "Not selected", | ||||
|     "no_invoice": "No invoice", | ||||
|     "not_selected": "-", | ||||
|     "no_invoice": "Aucune facture", | ||||
|     "no_matching_payments": "Il n'y a aucun paiement correspondant !", | ||||
|     "list_of_payments": "Ajoutez des paiements et retrouvez-les ici.", | ||||
|     "select_payment_mode": "Sélectionnez le moyen de paiement", | ||||
| @ -473,7 +473,7 @@ | ||||
|     "receipt": "Reçu", | ||||
|     "amount": "Montant", | ||||
|     "action": "action", | ||||
|     "not_selected": "Not selected", | ||||
|     "not_selected": "-", | ||||
|     "note": "Description", | ||||
|     "category_id": "Identifiant de catégorie", | ||||
|     "date": "Date", | ||||
| @ -751,13 +751,13 @@ | ||||
|         "title": "Factures", | ||||
|         "notes": "Remarques", | ||||
|         "invoice_prefix": "Préfixe", | ||||
|         "invoice_number_length": "Invoice number length", | ||||
|         "invoice_number_length": "Longueur du numéro de facture", | ||||
|         "default_invoice_email_body": "Message", | ||||
|         "invoice_settings": "Paramètres", | ||||
|         "autogenerate_invoice_number": "Générer automatiquement le numéro de facture", | ||||
|         "invoice_setting_description": "Désactivez cette option si vous ne souhaitez pas générer automatiquement les numéros de facture à chaque fois que vous en créez une nouvelle.", | ||||
|         "invoice_email_attachment": "Send invoices as attachments", | ||||
|         "invoice_email_attachment_setting_description": "Enable this if you want to send invoices as email attachment. Please note that 'View Invoice' button in emails will not be displayed anymore when enabled.", | ||||
|         "invoice_email_attachment": "Envoyer les factures en pièces jointes", | ||||
|         "invoice_email_attachment_setting_description": "Activez cette option si vous souhaitez envoyer les factures en pièces jointes. Le bouton \"Afficher la facture\" n'apparaîtra plus dans l'email.", | ||||
|         "enter_invoice_prefix": "Ajouter le préfixe de facture", | ||||
|         "terms_and_conditions": "Termes et conditions", | ||||
|         "company_address_format": "Format d'adresse de l'entreprise", | ||||
| @ -768,13 +768,13 @@ | ||||
|       "estimates": { | ||||
|         "title": "Devis", | ||||
|         "estimate_prefix": "Préfixe des devis", | ||||
|         "estimate_number_length": "Estimate number length", | ||||
|         "estimate_number_length": "Longueur du numéro de devis", | ||||
|         "default_estimate_email_body": "Message", | ||||
|         "estimate_settings": "Paramètre", | ||||
|         "autogenerate_estimate_number": "Générer automatiquement le numéro de devis", | ||||
|         "estimate_setting_description": "Désactivez cette option si vous ne souhaitez pas générer automatiquement les numéros de devis à chaque fois que vous en créez un nouveau.", | ||||
|         "estimate_email_attachment": "Send estimates as attachments", | ||||
|         "estimate_email_attachment_setting_description": "Enable this if you want to send the estimates as an email attachment. Please note that 'View Estimate' button in emails will not be displayed anymore when enabled.", | ||||
|         "estimate_email_attachment": "Envoyer les devis en pièces jointes", | ||||
|         "estimate_email_attachment_setting_description": "Activez cette option si vous souhaitez envoyer les devis en pièces jointes. Le bouton \"Afficher le devis\" n'apparaîtra plus dans l'email.", | ||||
|         "enter_estimate_prefix": "Entrez le préfixe d'estimation", | ||||
|         "estimate_setting_updated": "Paramètres de devis mis à jour", | ||||
|         "company_address_format": "Format d'adresse de l'entreprise", | ||||
| @ -785,13 +785,13 @@ | ||||
|         "title": "Paiements", | ||||
|         "description": "Saisissez ici les différents moyens de paiement que vous utiliserez.", | ||||
|         "payment_prefix": "Préfixe", | ||||
|         "payment_number_length": "Payment number lenght", | ||||
|         "payment_number_length": "Longueur de numéro de reçu de paiement", | ||||
|         "default_payment_email_body": "Message", | ||||
|         "payment_settings": "Paramètres", | ||||
|         "autogenerate_payment_number": "Générer automatiquement le numéro de paiement", | ||||
|         "payment_setting_description": "Désactivez cette option si vous ne souhaitez pas générer automatiquement les numéros de paiement à chaque fois que vous en créez un nouveau.", | ||||
|         "payment_email_attachment": "Send payments as attachments", | ||||
|         "payment_email_attachment_setting_description": "Enable this if you want to send the payment receipts as an email attachment. Please note that 'View Payment' button in emails will not be displayed anymore when enabled.", | ||||
|         "payment_email_attachment": "Envoyer les reçus de paiement en pièces jointes", | ||||
|         "payment_email_attachment_setting_description": "Activez cette option si vous souhaitez envoyer les devis en pièces jointes. Le bouton \"Afficher le reçu de paiement\" n'apparaîtra plus dans l'email.", | ||||
|         "enter_payment_prefix": "Entrez le préfixe de paiement", | ||||
|         "payment_setting_updated": "Les paramètres de paiement ont bien été mis à jour", | ||||
|         "payment_modes": "Moyens de paiement", | ||||
| @ -931,7 +931,7 @@ | ||||
|       "download_zip_file": "Télécharger le fichier ZIP", | ||||
|       "unzipping_package": "Dézipper le package", | ||||
|       "copying_files": "Copie de fichiers en cours", | ||||
|       "deleting_files": "Deleting Unused files", | ||||
|       "deleting_files": "Supprimer les fichiers inutilisés", | ||||
|       "running_migrations": "Migrations en cours", | ||||
|       "finishing_update": "Finalisation de la mise à jour", | ||||
|       "update_failed": "Échec de la mise à jour", | ||||
| @ -1001,7 +1001,7 @@ | ||||
|       "default_driver": "Fournisseur par défaut", | ||||
|       "is_default": "Par défaut", | ||||
|       "set_default_disk": "Définir l'espace par défaut", | ||||
|       "set_default_disk_confirm": "This disk will be set as default and all the new PDFs will be saved on this disk", | ||||
|       "set_default_disk_confirm": "Cet espace sera utilisé par défaut pour l'enregistrement des PDF", | ||||
|       "success_set_default_disk": "Stockage par défaut mis à jour", | ||||
|       "save_pdf_to_disk": "Enregistrer les PDF sur le disque", | ||||
|       "disk_setting_description": "Activez cette option si vous souhaitez enregistrer automatiquement une copie de chaque facture, devis et reçu de paiement PDF sur votre disque par défaut. L'activation de cette option réduira le temps de chargement lors de l'affichage des PDF.", | ||||
| @ -1152,7 +1152,7 @@ | ||||
|     "ref_number_maxlength": "Le numéro de référence ne doit pas dépasser 255 caractères.", | ||||
|     "prefix_maxlength": "Le préfixe ne doit pas dépasser 5 caractères.", | ||||
|     "something_went_wrong": "quelque chose a mal tourné", | ||||
|     "number_length_minvalue": "Number lenght should be greater than 0" | ||||
|     "number_length_minvalue": "Ce nombre doit être supérieur à 0" | ||||
|   }, | ||||
|   "pdf_estimate_label": "Devis", | ||||
|   "pdf_estimate_number": "N°", | ||||
| @ -1170,7 +1170,7 @@ | ||||
|   "pdf_amount_label": "Montant", | ||||
|   "pdf_subtotal": "Total HT", | ||||
|   "pdf_total": "Total TTC", | ||||
|   "pdf_payment_label": "Payment", | ||||
|   "pdf_payment_label": "Paiement", | ||||
|   "pdf_payment_receipt_label": "Reçu de paiement", | ||||
|   "pdf_payment_date": "Date de paiement", | ||||
|   "pdf_payment_number": "Numéro", | ||||
| @ -1179,9 +1179,9 @@ | ||||
|   "pdf_expense_report_label": "RAPPORT DE DÉPENSES", | ||||
|   "pdf_total_expenses_label": "TOTAL DES DÉPENSES", | ||||
|   "pdf_profit_loss_label": "RECETTES ET DÉPENSES", | ||||
|   "pdf_sales_customers_label": "Sales Customer Report", | ||||
|   "pdf_sales_items_label": "Sales Item Report", | ||||
|   "pdf_tax_summery_label": "Tax Summary Report", | ||||
|   "pdf_sales_customers_label": "Rapport de vente client", | ||||
|   "pdf_sales_items_label": "Rapport de vente par articles", | ||||
|   "pdf_tax_summery_label": "Rapport de résumé fiscal", | ||||
|   "pdf_income_label": "REVENU", | ||||
|   "pdf_net_profit_label": "RÉSULTAT", | ||||
|   "pdf_customer_sales_report": "Rapport de ventes : par client", | ||||
|  | ||||
| @ -52,7 +52,7 @@ | ||||
|     "percentage": "Percentage", | ||||
|     "tax": "BELASTING", | ||||
|     "total_amount": "TOTAALBEDRAG", | ||||
|     "bill_to": "Rekening naar", | ||||
|     "bill_to": "Factuur aan", | ||||
|     "ship_to": "Verzend naar", | ||||
|     "due": "Openstaand", | ||||
|     "draft": "Concept", | ||||
| @ -87,7 +87,7 @@ | ||||
|     "choose_note": "Kies notitie", | ||||
|     "no_note_found": "Geen notitie gevonden", | ||||
|     "insert_note": "Notitie invoegen", | ||||
|     "copied_pdf_url_clipboard": "Copied PDF url to clipboard!" | ||||
|     "copied_pdf_url_clipboard": "PDF link naar klembord gekopieerd!" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "select_year": "Selecteer jaar", | ||||
| @ -178,8 +178,8 @@ | ||||
|     "copy_billing_address": "Kopiëren van facturering", | ||||
|     "no_customers": "Nog geen klanten!", | ||||
|     "no_customers_found": "Geen klanten gevonden!", | ||||
|     "no_contact": "No contact", | ||||
|     "no_contact_name": "No contact name", | ||||
|     "no_contact": "Geen contact", | ||||
|     "no_contact_name": "Geen contactnaam", | ||||
|     "list_of_customers": "Hier vind je jouw klanten terug.", | ||||
|     "primary_display_name": "Primaire weergavenaam", | ||||
|     "select_currency": "Selecteer valuta", | ||||
| @ -203,7 +203,7 @@ | ||||
|     "added_on": "Toegevoegd", | ||||
|     "price": "Prijs", | ||||
|     "date_of_creation": "Datum van creatie", | ||||
|     "not_selected": "No item selected", | ||||
|     "not_selected": "Geen item geselecteerd", | ||||
|     "action": "Actie", | ||||
|     "add_item": "Voeg item toe", | ||||
|     "save_item": "Item opslaan", | ||||
| @ -245,7 +245,7 @@ | ||||
|     "contact": "Contact", | ||||
|     "add_item": "Voeg een item toe", | ||||
|     "date": "Datum", | ||||
|     "due_date": "Opleveringsdatum", | ||||
|     "due_date": "Vervaldatum", | ||||
|     "expiry_date": "Vervaldatum", | ||||
|     "status": "Status", | ||||
|     "add_tax": "Belasting toevoegen", | ||||
| @ -274,7 +274,7 @@ | ||||
|       "required": "Veld is vereist" | ||||
|     }, | ||||
|     "accepted": "Geaccepteerd", | ||||
|     "rejected": "Rejected", | ||||
|     "rejected": "Afgewezen", | ||||
|     "sent": "Verzonden", | ||||
|     "draft": "Concept", | ||||
|     "declined": "Geweigerd", | ||||
| @ -321,9 +321,9 @@ | ||||
|     "all": "Allemaal", | ||||
|     "paid": "Betaald", | ||||
|     "unpaid": "Onbetaald", | ||||
|     "viewed": "Viewed", | ||||
|     "overdue": "Overdue", | ||||
|     "completed": "Completed", | ||||
|     "viewed": "Bekeken", | ||||
|     "overdue": "Over tijd", | ||||
|     "completed": "Voltooid", | ||||
|     "customer": "Klant", | ||||
|     "paid_status": "Betaling", | ||||
|     "ref_no": "REF NR.", | ||||
| @ -339,7 +339,7 @@ | ||||
|     "contact": "Contact", | ||||
|     "add_item": "Voeg een item toe", | ||||
|     "date": "Datum", | ||||
|     "due_date": "Opleveringsdatum", | ||||
|     "due_date": "Vervaldatum", | ||||
|     "status": "Status", | ||||
|     "add_tax": "Belasting toevoegen", | ||||
|     "amount": "Bedrag", | ||||
| @ -442,8 +442,8 @@ | ||||
|     "update_payment": "Betaling bijwerken", | ||||
|     "payment": "Betaling | Betalingen", | ||||
|     "no_payments": "Nog geen betalingen!", | ||||
|     "not_selected": "Not selected", | ||||
|     "no_invoice": "No invoice", | ||||
|     "not_selected": "Niet geselecteerd", | ||||
|     "no_invoice": "Geen factuur", | ||||
|     "no_matching_payments": "Er zijn geen overeenkomende betalingen!", | ||||
|     "list_of_payments": "Hier vind je jouw betalingen terug.", | ||||
|     "select_payment_mode": "Selecteer betalingswijze", | ||||
| @ -473,7 +473,7 @@ | ||||
|     "receipt": "Bon", | ||||
|     "amount": "Bedrag", | ||||
|     "action": "Actie", | ||||
|     "not_selected": "Not selected", | ||||
|     "not_selected": "Niet geselecteerd", | ||||
|     "note": "Notitie", | ||||
|     "category_id": "Categorie ID", | ||||
|     "date": "Uitgavendatum", | ||||
| @ -580,7 +580,7 @@ | ||||
|     "invoices": { | ||||
|       "invoice": "Factuur", | ||||
|       "invoice_date": "Factuur datum", | ||||
|       "due_date": "Opleveringsdatum", | ||||
|       "due_date": "Vervaldatum", | ||||
|       "amount": "Bedrag", | ||||
|       "contact_name": "Contactnaam", | ||||
|       "status": "Status" | ||||
| @ -588,7 +588,7 @@ | ||||
|     "estimates": { | ||||
|       "estimate": "Offerte", | ||||
|       "estimate_date": "Offerte Datum", | ||||
|       "due_date": "Opleveringsdatum", | ||||
|       "due_date": "Vervaldatum", | ||||
|       "estimate_number": "Offerte nummer", | ||||
|       "ref_number": "Referentie nummer", | ||||
|       "amount": "Bedrag", | ||||
| @ -697,7 +697,7 @@ | ||||
|       "help_text": "Hulp Text", | ||||
|       "default_value": "Standaard waarde", | ||||
|       "prefix": "Voorvoegsel", | ||||
|       "starting_number": "Starting Number", | ||||
|       "starting_number": "Startnummer", | ||||
|       "model": "Model", | ||||
|       "help_text_description": "Voer tekst in om gebruikers te helpen het doel van dit aangepaste veld te begrijpen.", | ||||
|       "suffix": "Achtervoegsel", | ||||
| @ -751,13 +751,13 @@ | ||||
|         "title": "Facturen", | ||||
|         "notes": "Opmerkingen", | ||||
|         "invoice_prefix": "Factuurvoorvoegsel", | ||||
|         "invoice_number_length": "Invoice number length", | ||||
|         "invoice_number_length": "Lengte factuurnummer", | ||||
|         "default_invoice_email_body": "Standaard factuur email text", | ||||
|         "invoice_settings": "Factuurinstellingen", | ||||
|         "autogenerate_invoice_number": "Factuurnummer automatisch genereren", | ||||
|         "invoice_setting_description": "Schakel dit uit als u niet automatisch factuurnummers wilt genereren telkens wanneer u een nieuwe factuur maakt.", | ||||
|         "invoice_email_attachment": "Send invoices as attachments", | ||||
|         "invoice_email_attachment_setting_description": "Enable this if you want to send invoices as email attachment. Please note that 'View Invoice' button in emails will not be displayed anymore when enabled.", | ||||
|         "invoice_email_attachment": "Stuur factuur als bijlage", | ||||
|         "invoice_email_attachment_setting_description": "Schakel dit in als u facturen als e-mailbijlage wilt verzenden. Houd er rekening mee dat de knop 'Factuur bekijken' in e-mails niet meer wordt weergegeven wanneer deze is ingeschakeld.", | ||||
|         "enter_invoice_prefix": "Voer het factuurvoorvoegsel in", | ||||
|         "terms_and_conditions": "Voorwaarden", | ||||
|         "company_address_format": "Bedrijfsadres format", | ||||
| @ -768,13 +768,13 @@ | ||||
|       "estimates": { | ||||
|         "title": "Offertes", | ||||
|         "estimate_prefix": "Voorvoegsel schatten", | ||||
|         "estimate_number_length": "Estimate number length", | ||||
|         "estimate_number_length": "Lengte offerte nummer", | ||||
|         "default_estimate_email_body": "Standaard offerte email text", | ||||
|         "estimate_settings": "Instellingen schatten", | ||||
|         "autogenerate_estimate_number": "Automatisch geschat nummer genereren", | ||||
|         "estimate_setting_description": "Schakel dit uit als u niet automatisch offertesaantallen wilt genereren telkens wanneer u een nieuwe offerte maakt.", | ||||
|         "estimate_email_attachment": "Send estimates as attachments", | ||||
|         "estimate_email_attachment_setting_description": "Enable this if you want to send the estimates as an email attachment. Please note that 'View Estimate' button in emails will not be displayed anymore when enabled.", | ||||
|         "estimate_email_attachment": "Stuur offerte als bijlage", | ||||
|         "estimate_email_attachment_setting_description": "Schakel dit in als u de offertes als e-mailbijlage wilt verzenden. Houd er rekening mee dat de knop 'Bekijk offerte' in e-mails niet meer wordt weergegeven wanneer deze is ingeschakeld.", | ||||
|         "enter_estimate_prefix": "Voer het prefixnummer in", | ||||
|         "estimate_setting_updated": "Instelling Offerte succesvol bijgewerkt", | ||||
|         "company_address_format": "Bedrijfsadres format", | ||||
| @ -785,13 +785,13 @@ | ||||
|         "title": "Betalingen", | ||||
|         "description": "Manieren om te betalen", | ||||
|         "payment_prefix": "Betalingsvoorvoegsel", | ||||
|         "payment_number_length": "Payment number lenght", | ||||
|         "payment_number_length": "Lengte van betalingsnummer", | ||||
|         "default_payment_email_body": "Standaard format betalingsmail", | ||||
|         "payment_settings": "Betalingsinstellingen", | ||||
|         "autogenerate_payment_number": "Betalingsnummer automatisch genereren", | ||||
|         "payment_setting_description": "Schakel dit uit als u niet elke keer dat u een nieuwe betaling aanmaakt, automatisch betalingsnummers wilt genereren.", | ||||
|         "payment_email_attachment": "Send payments as attachments", | ||||
|         "payment_email_attachment_setting_description": "Enable this if you want to send the payment receipts as an email attachment. Please note that 'View Payment' button in emails will not be displayed anymore when enabled.", | ||||
|         "payment_email_attachment": "Stuur betaalbewijs als bijlage", | ||||
|         "payment_email_attachment_setting_description": "Schakel dit in als u de betalingsbewijzen als e-mailbijlage wilt verzenden. Houd er rekening mee dat de knop 'Betaling bekijken' in e-mails niet meer wordt weergegeven wanneer deze is ingeschakeld.", | ||||
|         "enter_payment_prefix": "Voer het betalingsvoorvoegsel in", | ||||
|         "payment_setting_updated": "Betalingsinstelling geüpdatet", | ||||
|         "payment_modes": "Betaalmethodes", | ||||
| @ -931,7 +931,7 @@ | ||||
|       "download_zip_file": "Download ZIP-bestand", | ||||
|       "unzipping_package": "Pakket uitpakken", | ||||
|       "copying_files": "Bestanden kopiëren", | ||||
|       "deleting_files": "Deleting Unused files", | ||||
|       "deleting_files": "Ongebruikte bestanden verwijderen", | ||||
|       "running_migrations": "Migraties uitvoeren", | ||||
|       "finishing_update": "Afwerking Update", | ||||
|       "update_failed": "Update mislukt", | ||||
| @ -972,13 +972,13 @@ | ||||
|       "new_disk": "Nieuwe schijf toevoegen", | ||||
|       "filesystem_driver": "Bestandssysteem locatie", | ||||
|       "local_driver": "lokaal besturingsprogramma", | ||||
|       "local_root": "local Root", | ||||
|       "local_root": "locale schijf", | ||||
|       "public_driver": "Publiek besturingsprogramma", | ||||
|       "public_root": "Public Root", | ||||
|       "public_root": "Openbare schijf", | ||||
|       "public_url": "Publieke URL", | ||||
|       "public_visibility": "Publieke zichtbaarheid", | ||||
|       "media_driver": "Media stuurprogramma", | ||||
|       "media_root": "Media Root", | ||||
|       "media_root": "Media schijf", | ||||
|       "aws_driver": "AWS Stuurprogramma", | ||||
|       "aws_key": "AWS Sleutel", | ||||
|       "aws_secret": "AWS Secret", | ||||
| @ -1001,7 +1001,7 @@ | ||||
|       "default_driver": "Standaard stuurprogramma", | ||||
|       "is_default": "IS STANDAARD", | ||||
|       "set_default_disk": "Standaardschijf instellen", | ||||
|       "set_default_disk_confirm": "This disk will be set as default and all the new PDFs will be saved on this disk", | ||||
|       "set_default_disk_confirm": "Deze schijf zal als standaard worden ingesteld en alle nieuwe PDF's worden opgeslagen op deze schijf", | ||||
|       "success_set_default_disk": "Standaardschijf ingesteld", | ||||
|       "save_pdf_to_disk": "PDF's opslaan op schijf", | ||||
|       "disk_setting_description": " Schakel dit in als je een kopie van elke factuur, raming en betalingsbewijs automatisch op je standaard schijf wilt opslaan. Het inschakelen van deze optie zal de laadtijd verminderen wanneer de PDF's worden bekeken.", | ||||
| @ -1152,7 +1152,7 @@ | ||||
|     "ref_number_maxlength": "Ref-nummer mag niet groter zijn dan 255 tekens.", | ||||
|     "prefix_maxlength": "Het voorvoegsel mag niet meer dan 5 tekens bevatten.", | ||||
|     "something_went_wrong": "Er is iets fout gegaan", | ||||
|     "number_length_minvalue": "Number lenght should be greater than 0" | ||||
|     "number_length_minvalue": "Het getal moet groter zijn dan 0" | ||||
|   }, | ||||
|   "pdf_estimate_label": "Offerte", | ||||
|   "pdf_estimate_number": "Offerte nummer", | ||||
| @ -1161,7 +1161,7 @@ | ||||
|   "pdf_invoice_label": "Factuur", | ||||
|   "pdf_invoice_number": "Factuurnummer", | ||||
|   "pdf_invoice_date": "Factuur datum", | ||||
|   "pdf_invoice_due_date": "Opleveringsdatum", | ||||
|   "pdf_invoice_due_date": "Vervaldatum", | ||||
|   "pdf_notes": "Opmerkingen", | ||||
|   "pdf_items_label": "Artikelen", | ||||
|   "pdf_quantity_label": "Aantal stuks", | ||||
| @ -1170,7 +1170,7 @@ | ||||
|   "pdf_amount_label": "Bedrag", | ||||
|   "pdf_subtotal": "Subtotaal", | ||||
|   "pdf_total": "Totaal", | ||||
|   "pdf_payment_label": "Payment", | ||||
|   "pdf_payment_label": "Betaling", | ||||
|   "pdf_payment_receipt_label": "Betalingsafschrift", | ||||
|   "pdf_payment_date": "Betalingsdatum", | ||||
|   "pdf_payment_number": "Betalingsnummer", | ||||
| @ -1179,9 +1179,9 @@ | ||||
|   "pdf_expense_report_label": "UITGAVEN RAPPORT", | ||||
|   "pdf_total_expenses_label": "TOTALE UITGAVEN", | ||||
|   "pdf_profit_loss_label": "WINST & VERLIES RAPPORT", | ||||
|   "pdf_sales_customers_label": "Sales Customer Report", | ||||
|   "pdf_sales_items_label": "Sales Item Report", | ||||
|   "pdf_tax_summery_label": "Tax Summary Report", | ||||
|   "pdf_sales_customers_label": "Klant verkoop rapport", | ||||
|   "pdf_sales_items_label": "Artikel verkooprapport", | ||||
|   "pdf_tax_summery_label": "Belastingoverzicht", | ||||
|   "pdf_income_label": "INKOMEN", | ||||
|   "pdf_net_profit_label": "NETTO WINST", | ||||
|   "pdf_customer_sales_report": "Verkooprapport: per klant", | ||||
|  | ||||
							
								
								
									
										1197
									
								
								resources/assets/js/plugins/pl.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -87,7 +87,7 @@ | ||||
|     "choose_note": "Escolher Nota", | ||||
|     "no_note_found": "Nenhuma Nota Encontrada", | ||||
|     "insert_note": "Inserir Nota", | ||||
|     "copied_pdf_url_clipboard": "Copied PDF url to clipboard!" | ||||
|     "copied_pdf_url_clipboard": "URL do PDF copiado para área de transferência!" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "select_year": "Selecione Ano", | ||||
| @ -178,8 +178,8 @@ | ||||
|     "copy_billing_address": "Copiar Endereço de Faturamento", | ||||
|     "no_customers": "Ainda não há clientes!", | ||||
|     "no_customers_found": "Clientes não encontrados!", | ||||
|     "no_contact": "No contact", | ||||
|     "no_contact_name": "No contact name", | ||||
|     "no_contact": "Nenhum contato", | ||||
|     "no_contact_name": "Sem nome de contato", | ||||
|     "list_of_customers": "Esta seção conterá a lista de clientes.", | ||||
|     "primary_display_name": "Nome de exibição principal", | ||||
|     "select_currency": "Selecione o tipo de moeda", | ||||
| @ -203,7 +203,7 @@ | ||||
|     "added_on": "Adicionado", | ||||
|     "price": "Preço", | ||||
|     "date_of_creation": "Data de criação", | ||||
|     "not_selected": "No item selected", | ||||
|     "not_selected": "Nenhum item selecionado", | ||||
|     "action": "Ação", | ||||
|     "add_item": "Adicionar item", | ||||
|     "save_item": "Salvar item", | ||||
| @ -274,7 +274,7 @@ | ||||
|       "required": "Campo obrigatório" | ||||
|     }, | ||||
|     "accepted": "Aceito", | ||||
|     "rejected": "Rejected", | ||||
|     "rejected": "Rejeitado", | ||||
|     "sent": "Enviado", | ||||
|     "draft": "Rascunho", | ||||
|     "declined": "Rejeitado", | ||||
| @ -321,9 +321,9 @@ | ||||
|     "all": "Todas", | ||||
|     "paid": "Paga", | ||||
|     "unpaid": "Não Paga", | ||||
|     "viewed": "Viewed", | ||||
|     "overdue": "Overdue", | ||||
|     "completed": "Completed", | ||||
|     "viewed": "Visualizado", | ||||
|     "overdue": "Atrasado", | ||||
|     "completed": "Concluído", | ||||
|     "customer": "CLIENTE", | ||||
|     "paid_status": "STATUS PAGAMENTO", | ||||
|     "ref_no": "REF NO.", | ||||
| @ -442,8 +442,8 @@ | ||||
|     "update_payment": "Atualizar Pagamento", | ||||
|     "payment": "Pagamento | Pagamentos", | ||||
|     "no_payments": "Não há pagamentos ainda!", | ||||
|     "not_selected": "Not selected", | ||||
|     "no_invoice": "No invoice", | ||||
|     "not_selected": "Não selecionado", | ||||
|     "no_invoice": "Nenhuma fatura", | ||||
|     "no_matching_payments": "Não há pagamentos correspondentes!", | ||||
|     "list_of_payments": "Esta seção conterá a lista de pagamentos.", | ||||
|     "select_payment_mode": "Selecione a forma de pagamento", | ||||
| @ -473,7 +473,7 @@ | ||||
|     "receipt": "Recibo", | ||||
|     "amount": "Valor", | ||||
|     "action": "Ação", | ||||
|     "not_selected": "Not selected", | ||||
|     "not_selected": "Não selecionado", | ||||
|     "note": "Observação", | ||||
|     "category_id": "Categoria", | ||||
|     "date": "Data da Despesa", | ||||
| @ -751,13 +751,13 @@ | ||||
|         "title": "Faturas", | ||||
|         "notes": "Notas", | ||||
|         "invoice_prefix": "Fatura Prefixo", | ||||
|         "invoice_number_length": "Invoice number length", | ||||
|         "invoice_number_length": "Comprimento do número da fatura", | ||||
|         "default_invoice_email_body": "Corpo Padrão de Email de Fatura", | ||||
|         "invoice_settings": "Configurações de Fatura", | ||||
|         "autogenerate_invoice_number": "Gerar automaticamente o número da Fatura", | ||||
|         "invoice_setting_description": "Desative isso, se você não deseja gerar automaticamente números da Fatura sempre que criar uma nova.", | ||||
|         "invoice_email_attachment": "Send invoices as attachments", | ||||
|         "invoice_email_attachment_setting_description": "Enable this if you want to send invoices as email attachment. Please note that 'View Invoice' button in emails will not be displayed anymore when enabled.", | ||||
|         "invoice_email_attachment": "Enviar faturas como anexos", | ||||
|         "invoice_email_attachment_setting_description": "Ative esta opção se quiser anexar faturas no e-mail. Lembrando que quando habilitado, o botão 'Ver fatura' nos e-mails não será mais exibido.", | ||||
|         "enter_invoice_prefix": "Digite o prefixo da Fatura", | ||||
|         "terms_and_conditions": "Termos e Condições", | ||||
|         "company_address_format": "Formato de Endereço de Empresa", | ||||
| @ -768,13 +768,13 @@ | ||||
|       "estimates": { | ||||
|         "title": "Orçamentos", | ||||
|         "estimate_prefix": "Orçamento Prefixo", | ||||
|         "estimate_number_length": "Estimate number length", | ||||
|         "estimate_number_length": "Comprimento do número do orçamento", | ||||
|         "default_estimate_email_body": "Corpo Padrão de Email de Orçamento", | ||||
|         "estimate_settings": "Configurações do Orçamento", | ||||
|         "autogenerate_estimate_number": "Gerar automaticamente o número do Orçamento", | ||||
|         "estimate_setting_description": "Desative isso, se você não deseja gerar automaticamente números do Orçamento sempre que criar um novo.", | ||||
|         "estimate_email_attachment": "Send estimates as attachments", | ||||
|         "estimate_email_attachment_setting_description": "Enable this if you want to send the estimates as an email attachment. Please note that 'View Estimate' button in emails will not be displayed anymore when enabled.", | ||||
|         "estimate_email_attachment": "Enviar orçamentos como anexos", | ||||
|         "estimate_email_attachment_setting_description": "Ative esta opção se quiser anexar orçamentos no e-mail. Lembrando que quando habilitado, o botão 'Ver orçamento' nos e-mails não será mais exibido.", | ||||
|         "enter_estimate_prefix": "Digite o prefixo do Orçamento", | ||||
|         "estimate_setting_updated": "Configuração de Orçamento atualizada com sucesso", | ||||
|         "company_address_format": "Formato de Endereço de Empresa", | ||||
| @ -785,13 +785,13 @@ | ||||
|         "title": "Pagamentos", | ||||
|         "description": "Modos de transação para pagamentos", | ||||
|         "payment_prefix": "Pagamento Prefixo", | ||||
|         "payment_number_length": "Payment number lenght", | ||||
|         "payment_number_length": "Comprimento do número do pagamento", | ||||
|         "default_payment_email_body": "Corpo Padrão de Email de Pagamento", | ||||
|         "payment_settings": "Configurações de Pagamento", | ||||
|         "autogenerate_payment_number": "Gerar automaticamente número do Pagamento", | ||||
|         "payment_setting_description": "Desative isso, se você não deseja gerar automaticamente números do Pagamento sempre que criar um novo.", | ||||
|         "payment_email_attachment": "Send payments as attachments", | ||||
|         "payment_email_attachment_setting_description": "Enable this if you want to send the payment receipts as an email attachment. Please note that 'View Payment' button in emails will not be displayed anymore when enabled.", | ||||
|         "payment_email_attachment": "Enviar pagamentos como anexos", | ||||
|         "payment_email_attachment_setting_description": "Ative esta opção se quiser anexar pagamentos no e-mail. Lembrando que quando habilitado, o botão 'Ver pagamento' nos e-mails não será mais exibido.", | ||||
|         "enter_payment_prefix": "Digite o Prefixo do Pagamento", | ||||
|         "payment_setting_updated": "Configurações de Pagamento atualizada com sucesso", | ||||
|         "payment_modes": "Meios de Pagamento", | ||||
| @ -931,7 +931,7 @@ | ||||
|       "download_zip_file": "Baixar arquivo ZIP", | ||||
|       "unzipping_package": "Descompactando o pacote", | ||||
|       "copying_files": "Copiando arquivos", | ||||
|       "deleting_files": "Deleting Unused files", | ||||
|       "deleting_files": "Excluindo arquivos não utilizados", | ||||
|       "running_migrations": "Executando migrações", | ||||
|       "finishing_update": "Acabando a Atualização", | ||||
|       "update_failed": "Atualização falhou", | ||||
| @ -1001,7 +1001,7 @@ | ||||
|       "default_driver": "Driver Padrão", | ||||
|       "is_default": "ESTÁ PADRÃO", | ||||
|       "set_default_disk": "Definir Disco Padrão", | ||||
|       "set_default_disk_confirm": "This disk will be set as default and all the new PDFs will be saved on this disk", | ||||
|       "set_default_disk_confirm": "Este disco será definido como padrão e todos os novos PDFs serão salvos neste disco", | ||||
|       "success_set_default_disk": "Disco definido como padrão com sucesso", | ||||
|       "save_pdf_to_disk": "Salvar PDFs no Disco", | ||||
|       "disk_setting_description": " Ative isso, se você deseja salvar uma cópia de cada fatura, Orçamento e Pagamento PDF em seu disco padrão automaticamente. Virar esta opção irá diminuir o tempo de carregamento ao visualizar os PDFs.", | ||||
| @ -1152,7 +1152,7 @@ | ||||
|     "ref_number_maxlength": "O número de referência não deve ter mais que 255 caracteres.", | ||||
|     "prefix_maxlength": "O prefixo não deve ter mais que 5 caracteres.", | ||||
|     "something_went_wrong": "algo deu errado", | ||||
|     "number_length_minvalue": "Number lenght should be greater than 0" | ||||
|     "number_length_minvalue": "O valor deve ser maior que 0" | ||||
|   }, | ||||
|   "pdf_estimate_label": "Orçamento", | ||||
|   "pdf_estimate_number": "Numero do Orçamento", | ||||
| @ -1170,7 +1170,7 @@ | ||||
|   "pdf_amount_label": "Valor", | ||||
|   "pdf_subtotal": "Subtotal", | ||||
|   "pdf_total": "Total", | ||||
|   "pdf_payment_label": "Payment", | ||||
|   "pdf_payment_label": "Pagamento", | ||||
|   "pdf_payment_receipt_label": "RECIBO DE PAGAMENTO", | ||||
|   "pdf_payment_date": "Data de Pagamento", | ||||
|   "pdf_payment_number": "Número do Pagamento", | ||||
| @ -1179,9 +1179,9 @@ | ||||
|   "pdf_expense_report_label": "RELATÓRIO DE DESPESAS", | ||||
|   "pdf_total_expenses_label": "TOTAL DESPESAS", | ||||
|   "pdf_profit_loss_label": "RELATÓRIO LUCRO & PERDA", | ||||
|   "pdf_sales_customers_label": "Sales Customer Report", | ||||
|   "pdf_sales_items_label": "Sales Item Report", | ||||
|   "pdf_tax_summery_label": "Tax Summary Report", | ||||
|   "pdf_sales_customers_label": "Relatório de vendas cliente", | ||||
|   "pdf_sales_items_label": "Relatório de venda de itens", | ||||
|   "pdf_tax_summery_label": "Relatório resumido de imposto", | ||||
|   "pdf_income_label": "RENDA", | ||||
|   "pdf_net_profit_label": "LUCRO LÍQUIDO", | ||||
|   "pdf_customer_sales_report": "Relatório de Vendas: Por Cliente", | ||||
|  | ||||
							
								
								
									
										1197
									
								
								resources/assets/js/plugins/ro.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1197
									
								
								resources/assets/js/plugins/ru.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -18,13 +18,13 @@ | ||||
|     "copy_pdf_url": "Sao chép Url PDF", | ||||
|     "download_pdf": "tải PDF", | ||||
|     "save": "Tiết kiệm", | ||||
|         "create": "Tạo mới", | ||||
|     "create": "Tạo nên", | ||||
|     "cancel": "Huỷ bỏ", | ||||
|     "update": "Cập nhật", | ||||
|     "deselect": "Bỏ chọn", | ||||
|     "download": "Tải xuống", | ||||
|     "from_date": "Từ ngày", | ||||
|         "to_date": "Đến ngày", | ||||
|     "to_date": "Đến nay", | ||||
|     "from": "Từ", | ||||
|     "to": "Đến", | ||||
|     "sort_by": "Sắp xếp theo", | ||||
| @ -39,7 +39,7 @@ | ||||
|     "home": "Trang Chủ", | ||||
|     "filter": "Bộ lọc", | ||||
|     "delete": "Xóa bỏ", | ||||
|         "edit": "Chỉnh sửa", | ||||
|     "edit": "Biên tập", | ||||
|     "view": "Lượt xem", | ||||
|     "add_new_item": "Thêm mục mới", | ||||
|     "clear_all": "Làm sạch tất cả", | ||||
| @ -52,17 +52,17 @@ | ||||
|     "percentage": "Phần trăm", | ||||
|     "tax": "THUẾ", | ||||
|     "total_amount": "TỔNG CỘNG", | ||||
|         "bill_to": "Giao từ", | ||||
|         "ship_to": "Giao tới", | ||||
|     "bill_to": "Hoa đơn để", | ||||
|     "ship_to": "Tàu", | ||||
|     "due": "Đến hạn", | ||||
|     "draft": "Bản nháp", | ||||
|         "sent": "Gửi", | ||||
|     "sent": "Gởi", | ||||
|     "all": "Tất cả", | ||||
|     "select_all": "Chọn tất cả", | ||||
|     "choose_file": "Bấm vào đây để chọn một tập tin", | ||||
|     "choose_template": "Chọn một mẫu", | ||||
|     "choose": "Chọn", | ||||
|         "remove": "Gỡ", | ||||
|     "remove": "Tẩy", | ||||
|     "powered_by": "Được cung cấp bởi", | ||||
|     "bytefury": "Bytefury", | ||||
|     "select_a_status": "Chọn một trạng thái", | ||||
| @ -82,7 +82,7 @@ | ||||
|     "select_city": "Lựa chọn thành phố", | ||||
|     "street_1": "đường số 1", | ||||
|     "street_2": "Đường 2", | ||||
|         "action_failed": "Đã thất bại", | ||||
|     "action_failed": "Diễn: Đã thất bại", | ||||
|     "retry": "Thử lại", | ||||
|     "choose_note": "Chọn Ghi chú", | ||||
|     "no_note_found": "Không tìm thấy ghi chú", | ||||
| @ -129,7 +129,7 @@ | ||||
|   }, | ||||
|   "tax_types": { | ||||
|     "name": "Tên", | ||||
|         "description": "Miêu tả", | ||||
|     "description": "Sự miêu tả", | ||||
|     "percent": "Phần trăm", | ||||
|     "compound_tax": "Thuế tổng hợp" | ||||
|   }, | ||||
| @ -153,8 +153,8 @@ | ||||
|     "email": "E-mail", | ||||
|     "address": "Địa chỉ", | ||||
|     "phone": "Điện thoại", | ||||
|         "website": "Website", | ||||
|         "overview": "Tổng quan", | ||||
|     "website": "Trang mạng", | ||||
|     "overview": "Tổng quat", | ||||
|     "enable_portal": "Bật Cổng thông tin", | ||||
|     "country": "Quốc gia", | ||||
|     "state": "Tiểu bang", | ||||
| @ -165,7 +165,7 @@ | ||||
|     "password": "Mật khẩu", | ||||
|     "street_number": "Số đường", | ||||
|     "primary_currency": "Tiền tệ chính", | ||||
|         "description": "Miêu tả", | ||||
|     "description": "Sự miêu tả", | ||||
|     "add_new_customer": "Thêm khách hàng mới", | ||||
|     "save_customer": "Lưu khách hàng", | ||||
|     "update_customer": "Cập nhật khách hàng", | ||||
| @ -199,7 +199,7 @@ | ||||
|     "items_list": "Danh sách mặt hàng", | ||||
|     "name": "Tên", | ||||
|     "unit": "Đơn vị", | ||||
|         "description": "Miêu tả", | ||||
|     "description": "Sự miêu tả", | ||||
|     "added_on": "Đã thêm vào", | ||||
|     "price": "Giá bán", | ||||
|     "date_of_creation": "Ngày tạo", | ||||
| @ -210,7 +210,7 @@ | ||||
|     "update_item": "Cập nhật mặt hàng", | ||||
|     "item": "Mặt hàng | Mặt hàng", | ||||
|     "add_new_item": "Thêm mục mới", | ||||
|         "new_item": "Sản phẩm mới", | ||||
|     "new_item": "Vật phẩm mới", | ||||
|     "edit_item": "Chỉnh sửa mục", | ||||
|     "no_items": "Chưa có mặt hàng nào!", | ||||
|     "list_of_items": "Phần này sẽ chứa danh sách các mục.", | ||||
| @ -227,22 +227,22 @@ | ||||
|     "estimate": "Ước tính | Ước tính", | ||||
|     "estimates_list": "Danh sách ước tính", | ||||
|     "days": "{days} Ngày", | ||||
|         "months": "{months} tháng", | ||||
|         "years": "{years} Năm", | ||||
|     "months": "{tháng} tháng", | ||||
|     "years": "{năm} Năm", | ||||
|     "all": "Tất cả", | ||||
|     "paid": "Đã thanh toán", | ||||
|     "unpaid": "Chưa thanh toán", | ||||
|     "customer": "KHÁCH HÀNG", | ||||
|         "ref_no": "SỐ THAM CHIẾU.", | ||||
|     "ref_no": "REF KHÔNG.", | ||||
|     "number": "CON SỐ", | ||||
|         "amount_due": "SỐ TIỀN THANH TOÁN", | ||||
|     "amount_due": "SỐ TIỀN ĐÚNG", | ||||
|     "partially_paid": "Thanh toán một phần", | ||||
|     "total": "Toàn bộ", | ||||
|     "discount": "Giảm giá", | ||||
|     "sub_total": "Tổng phụ", | ||||
|     "estimate_number": "Số ước tính", | ||||
|     "ref_number": "Số REF", | ||||
|         "contact": "Liên hệ", | ||||
|     "contact": "Tiếp xúc", | ||||
|     "add_item": "Thêm một mặt hàng", | ||||
|     "date": "Ngày", | ||||
|     "due_date": "Ngày đáo hạn", | ||||
| @ -271,11 +271,11 @@ | ||||
|     "mark_as_sent_successfully": "Ước tính được đánh dấu là đã gửi thành công", | ||||
|     "send_estimate_successfully": "Ước tính đã được gửi thành công", | ||||
|     "errors": { | ||||
|             "required": "Trường không được bỏ trống." | ||||
|       "required": "Lĩnh vực được yêu cầu" | ||||
|     }, | ||||
|     "accepted": "Đã được chấp nhận", | ||||
|     "rejected": "Từ chối", | ||||
|         "sent": "Gửi", | ||||
|     "sent": "Gởi", | ||||
|     "draft": "Bản nháp", | ||||
|     "declined": "Suy giảm", | ||||
|     "new_estimate": "Ước tính mới", | ||||
| @ -296,10 +296,10 @@ | ||||
|     "updated_message": "Đã cập nhật ước tính thành công", | ||||
|     "deleted_message": "Đã xóa ước tính thành công | Đã xóa ước tính thành công", | ||||
|     "user_email_does_not_exist": "Email người dùng không tồn tại", | ||||
|         "something_went_wrong": "Có gì đó không ổn", | ||||
|     "something_went_wrong": "có gì đó không ổn", | ||||
|     "item": { | ||||
|       "title": "Danh mục", | ||||
|             "description": "Miêu tả", | ||||
|       "description": "Sự miêu tả", | ||||
|       "quantity": "Định lượng", | ||||
|       "price": "Giá bán", | ||||
|       "discount": "Giảm giá", | ||||
| @ -316,8 +316,8 @@ | ||||
|     "title": "Hóa đơn", | ||||
|     "invoices_list": "Danh sách hóa đơn", | ||||
|     "days": "{days} Ngày", | ||||
|         "months": "{months} tháng", | ||||
|         "years": "{years} Năm", | ||||
|     "months": "{tháng} tháng", | ||||
|     "years": "{năm} Năm", | ||||
|     "all": "Tất cả", | ||||
|     "paid": "Đã thanh toán", | ||||
|     "unpaid": "Chưa thanh toán", | ||||
| @ -326,9 +326,9 @@ | ||||
|     "completed": "Đã hoàn thành", | ||||
|     "customer": "KHÁCH HÀNG", | ||||
|     "paid_status": "TRẠNG THÁI ĐÃ TRẢ TIỀN", | ||||
|         "ref_no": "SỐ THAM CHIẾU.", | ||||
|         "number": "SỐ", | ||||
|         "amount_due": "SỐ TIỀN THANH TOÁN", | ||||
|     "ref_no": "REF KHÔNG.", | ||||
|     "number": "CON SỐ", | ||||
|     "amount_due": "SỐ TIỀN ĐÚNG", | ||||
|     "partially_paid": "Thanh toán một phần", | ||||
|     "total": "Toàn bộ", | ||||
|     "discount": "Giảm giá", | ||||
| @ -336,7 +336,7 @@ | ||||
|     "invoice": "Hóa đơn | Hóa đơn", | ||||
|     "invoice_number": "Số hóa đơn", | ||||
|     "ref_number": "Số REF", | ||||
|         "contact": "Liên hệ", | ||||
|     "contact": "Tiếp xúc", | ||||
|     "add_item": "Thêm một mặt hàng", | ||||
|     "date": "Ngày", | ||||
|     "due_date": "Ngày đáo hạn", | ||||
| @ -374,7 +374,7 @@ | ||||
|     "confirm_clone": "Hóa đơn này sẽ được sao chép vào một Hóa đơn mới", | ||||
|     "item": { | ||||
|       "title": "Danh mục", | ||||
|             "description": "Miêu tả", | ||||
|       "description": "Sự miêu tả", | ||||
|       "quantity": "Định lượng", | ||||
|       "price": "Giá bán", | ||||
|       "discount": "Giảm giá", | ||||
| @ -400,7 +400,7 @@ | ||||
|     "title": "Giấy báo có", | ||||
|     "credit_notes_list": "Danh sách ghi chú tín dụng", | ||||
|     "credit_notes": "Giấy báo có", | ||||
|         "contact": "Liên hệ", | ||||
|     "contact": "Tiếp xúc", | ||||
|     "date": "Ngày", | ||||
|     "amount": "Số tiền", | ||||
|     "action": "Hoạt động", | ||||
| @ -409,7 +409,7 @@ | ||||
|     "confirm_delete": "Bạn có muốn xóa thư tín dụng này không?", | ||||
|     "item": { | ||||
|       "title": "Danh mục", | ||||
|             "description": "Miêu tả", | ||||
|       "description": "Sự miêu tả", | ||||
|       "quantity": "Định lượng", | ||||
|       "price": "Giá bán", | ||||
|       "discount": "Giảm giá", | ||||
| @ -427,7 +427,7 @@ | ||||
|     "date": "Ngày", | ||||
|     "amount": "Số tiền", | ||||
|     "action": "Hoạt động", | ||||
|         "payment_number": "Mã Số Thanh Toán", | ||||
|     "payment_number": "Số tiền phải trả", | ||||
|     "payment_mode": "Phương thức thanh toán", | ||||
|     "invoice": "Hóa đơn", | ||||
|     "note": "Ghi chú", | ||||
| @ -451,7 +451,7 @@ | ||||
|     "confirm_send_payment": "Khoản thanh toán này sẽ được gửi qua email cho khách hàng", | ||||
|     "send_payment_successfully": "Thanh toán đã được gửi thành công", | ||||
|     "user_email_does_not_exist": "Email người dùng không tồn tại", | ||||
|         "something_went_wrong": "Có gì đó không ổn", | ||||
|     "something_went_wrong": "có gì đó không ổn", | ||||
|     "confirm_delete": "Bạn sẽ không thể khôi phục Thanh toán này | Bạn sẽ không thể khôi phục các Khoản thanh toán này", | ||||
|     "created_message": "Thanh toán được tạo thành công", | ||||
|     "updated_message": "Đã cập nhật thanh toán thành công", | ||||
| @ -464,12 +464,12 @@ | ||||
|     "select_a_customer": "Chọn một khách hàng", | ||||
|     "expense_title": "Tiêu đề", | ||||
|     "customer": "khách hàng", | ||||
|         "contact": "Liên hệ", | ||||
|     "contact": "Tiếp xúc", | ||||
|     "category": "thể loại", | ||||
|     "from_date": "Từ ngày", | ||||
|         "to_date": "Đến ngày", | ||||
|     "to_date": "Đến nay", | ||||
|     "expense_date": "Ngày", | ||||
|         "description": "Miêu tả", | ||||
|     "description": "Sự miêu tả", | ||||
|     "receipt": "Biên lai", | ||||
|     "amount": "Số tiền", | ||||
|     "action": "Hoạt động", | ||||
| @ -495,7 +495,7 @@ | ||||
|       "categories_list": "Danh sách hạng mục", | ||||
|       "title": "Tiêu đề", | ||||
|       "name": "Tên", | ||||
|             "description": "Miêu tả", | ||||
|       "description": "Sự miêu tả", | ||||
|       "amount": "Số tiền", | ||||
|       "actions": "Hành động", | ||||
|       "add_category": "thêm thể loại", | ||||
| @ -522,7 +522,7 @@ | ||||
|     "title": "Người dùng", | ||||
|     "users_list": "Danh sách người dùng", | ||||
|     "name": "Tên", | ||||
|         "description": "Miêu tả", | ||||
|     "description": "Sự miêu tả", | ||||
|     "added_on": "Đã thêm vào", | ||||
|     "date_of_creation": "Ngày tạo", | ||||
|     "action": "Hoạt động", | ||||
| @ -532,7 +532,7 @@ | ||||
|     "user": "Người dùng | Người dùng", | ||||
|     "add_new_user": "Thêm người dùng mới", | ||||
|     "new_user": "Người dùng mới", | ||||
|         "edit_user": "Chỉnh sửa gười dùng", | ||||
|     "edit_user": "Người dùng biên tập", | ||||
|     "no_users": "Chưa có người dùng nào!", | ||||
|     "list_of_users": "Phần này sẽ chứa danh sách người dùng.", | ||||
|     "email": "E-mail", | ||||
| @ -547,30 +547,30 @@ | ||||
|   "reports": { | ||||
|     "title": "Báo cáo", | ||||
|     "from_date": "Từ ngày", | ||||
|         "to_date": "Đến ngày", | ||||
|     "to_date": "Đến nay", | ||||
|     "status": "Trạng thái", | ||||
|     "paid": "Đã thanh toán", | ||||
|     "unpaid": "Chưa thanh toán", | ||||
|         "download_pdf": "Tải PDF", | ||||
|     "download_pdf": "tải PDF", | ||||
|     "view_pdf": "Xem PDF", | ||||
|     "update_report": "Cập nhật báo cáo", | ||||
|     "report": "Báo cáo | Báo cáo", | ||||
|     "profit_loss": { | ||||
|       "profit_loss": "Lợi nhuận", | ||||
|             "to_date": "Đến ngày", | ||||
|       "to_date": "Đến nay", | ||||
|       "from_date": "Từ ngày", | ||||
|       "date_range": "Chọn phạm vi ngày" | ||||
|     }, | ||||
|     "sales": { | ||||
|       "sales": "Bán hàng", | ||||
|       "date_range": "Chọn phạm vi ngày", | ||||
|             "to_date": "Đến ngày", | ||||
|       "to_date": "Đến nay", | ||||
|       "from_date": "Từ ngày", | ||||
|       "report_type": "Loại báo cáo" | ||||
|     }, | ||||
|     "taxes": { | ||||
|       "taxes": "Thuế", | ||||
|             "to_date": "Đến ngày", | ||||
|       "to_date": "Đến nay", | ||||
|       "from_date": "Từ ngày", | ||||
|       "date_range": "Chọn phạm vi ngày" | ||||
|     }, | ||||
| @ -600,7 +600,7 @@ | ||||
|       "category": "thể loại", | ||||
|       "date": "Ngày", | ||||
|       "amount": "Số tiền", | ||||
|             "to_date": "Đến ngày", | ||||
|       "to_date": "Đến nay", | ||||
|       "from_date": "Từ ngày", | ||||
|       "date_range": "Chọn phạm vi ngày" | ||||
|     } | ||||
| @ -650,11 +650,11 @@ | ||||
|       "host": "Máy chủ Thư", | ||||
|       "port": "Cổng thư", | ||||
|       "driver": "Trình điều khiển Thư", | ||||
|             "secret": "Khóa", | ||||
|             "mailgun_secret": "Khóa Mailgun", | ||||
|       "secret": "Bí mật", | ||||
|       "mailgun_secret": "Bí mật Mailgun", | ||||
|       "mailgun_domain": "Miền", | ||||
|       "mailgun_endpoint": "Điểm cuối của Mailgun", | ||||
|             "ses_secret": "Khóa SES", | ||||
|       "ses_secret": "Bí mật SES", | ||||
|       "ses_key": "Khóa SES", | ||||
|       "password": "Mật khẩu thư", | ||||
|       "username": "Tên người dùng thư", | ||||
| @ -680,7 +680,7 @@ | ||||
|       "city": "Tp.", | ||||
|       "address": "Địa chỉ", | ||||
|       "zip": "Zip", | ||||
|             "save": "Lưu", | ||||
|       "save": "Tiết kiệm", | ||||
|       "updated_message": "Thông tin công ty được cập nhật thành công" | ||||
|     }, | ||||
|     "custom_fields": { | ||||
| @ -729,12 +729,12 @@ | ||||
|         "customer_shipping_address": "Địa chỉ giao hàng của khách hàng", | ||||
|         "company_address": "địa chỉ công ty", | ||||
|         "insert_fields": "Chèn trường", | ||||
|                 "contact": "Liên hệ", | ||||
|         "contact": "Tiếp xúc", | ||||
|         "address": "Địa chỉ", | ||||
|         "display_name": "Tên hiển thị", | ||||
|         "primary_contact_name": "Tên liên hệ chính", | ||||
|         "email": "E-mail", | ||||
|                 "website": "Website", | ||||
|         "website": "Trang mạng", | ||||
|         "name": "Tên", | ||||
|         "country": "Quốc gia", | ||||
|         "state": "Tiểu bang", | ||||
| @ -751,6 +751,7 @@ | ||||
|         "title": "Hóa đơn", | ||||
|         "notes": "Ghi chú", | ||||
|         "invoice_prefix": "Tiền tố hóa đơn", | ||||
|         "invoice_number_length": "Invoice number length", | ||||
|         "default_invoice_email_body": "Nội dung email hóa đơn mặc định", | ||||
|         "invoice_settings": "Cài đặt hóa đơn", | ||||
|         "autogenerate_invoice_number": "Tự động tạo số hóa đơn", | ||||
| @ -767,6 +768,7 @@ | ||||
|       "estimates": { | ||||
|         "title": "Ước tính", | ||||
|         "estimate_prefix": "Tiền tố ước tính", | ||||
|         "estimate_number_length": "Estimate number length", | ||||
|         "default_estimate_email_body": "Nội dung Email Ước tính Mặc định", | ||||
|         "estimate_settings": "Cài đặt ước tính", | ||||
|         "autogenerate_estimate_number": "Tự động tạo số ước tính", | ||||
| @ -783,6 +785,7 @@ | ||||
|         "title": "Thanh toán", | ||||
|         "description": "Các phương thức giao dịch thanh toán", | ||||
|         "payment_prefix": "Tiền tố thanh toán", | ||||
|         "payment_number_length": "Payment number lenght", | ||||
|         "default_payment_email_body": "Nội dung Email Thanh toán Mặc định", | ||||
|         "payment_settings": "Cài đặt thanh toán", | ||||
|         "autogenerate_payment_number": "Tự động tạo số thanh toán", | ||||
| @ -838,7 +841,7 @@ | ||||
|       "password": "Mật khẩu", | ||||
|       "confirm_password": "Xác nhận mật khẩu", | ||||
|       "account_settings": "Cài đặt tài khoản", | ||||
|             "save": "Lưu", | ||||
|       "save": "Tiết kiệm", | ||||
|       "section_description": "Bạn có thể cập nhật tên, email của mình", | ||||
|       "updated_message": "Đã cập nhật cài đặt tài khoản thành công" | ||||
|     }, | ||||
| @ -856,7 +859,7 @@ | ||||
|       "invoice_viewed_desc": "Khi khách hàng của bạn xem hóa đơn được gửi qua bảng điều khiển miệng núi lửa.", | ||||
|       "estimate_viewed": "Ước tính đã xem", | ||||
|       "estimate_viewed_desc": "Khi khách hàng của bạn xem ước tính được gửi qua bảng điều khiển miệng núi lửa.", | ||||
|             "save": "Lưu", | ||||
|       "save": "Tiết kiệm", | ||||
|       "email_save_message": "Email đã được lưu thành công", | ||||
|       "please_enter_email": "Vui lòng nhập Email" | ||||
|     }, | ||||
| @ -887,7 +890,7 @@ | ||||
|       "add_category": "thêm thể loại", | ||||
|       "edit_category": "Chỉnh sửa danh mục", | ||||
|       "category_name": "tên danh mục", | ||||
|             "category_description": "Miêu tả", | ||||
|       "category_description": "Sự miêu tả", | ||||
|       "created_message": "Danh mục Chi phí đã được tạo thành công", | ||||
|       "deleted_message": "Đã xóa thành công danh mục chi phí", | ||||
|       "updated_message": "Đã cập nhật danh mục chi phí thành công", | ||||
| @ -903,7 +906,7 @@ | ||||
|       "discount_setting": "Cài đặt chiết khấu", | ||||
|       "discount_per_item": "Giảm giá cho mỗi mặt hàng", | ||||
|       "discount_setting_description": "Bật tính năng này nếu bạn muốn thêm Giảm giá vào các mặt hàng hóa đơn riêng lẻ. Theo mặc định, Giảm giá được thêm trực tiếp vào hóa đơn.", | ||||
|             "save": "Lưu", | ||||
|       "save": "Tiết kiệm", | ||||
|       "preference": "Sở thích | Sở thích", | ||||
|       "general_settings": "Tùy chọn mặc định cho hệ thống.", | ||||
|       "updated_message": "Đã cập nhật thành công các tùy chọn", | ||||
| @ -978,7 +981,7 @@ | ||||
|       "media_root": "Gốc phương tiện", | ||||
|       "aws_driver": "Trình điều khiển AWS", | ||||
|       "aws_key": "Khóa AWS", | ||||
|             "aws_secret": "Khóa AWS", | ||||
|       "aws_secret": "Bí mật AWS", | ||||
|       "aws_region": "Khu vực AWS", | ||||
|       "aws_bucket": "Nhóm AWS", | ||||
|       "aws_root": "Gốc AWS", | ||||
| @ -992,7 +995,7 @@ | ||||
|       "dropbox_type": "Loại hộp chứa", | ||||
|       "dropbox_token": "Mã thông báo Dropbox", | ||||
|       "dropbox_key": "Khóa Dropbox", | ||||
|             "dropbox_secret": "Khóa Dropbox", | ||||
|       "dropbox_secret": "Bí mật Dropbox", | ||||
|       "dropbox_app": "Ứng dụng Dropbox", | ||||
|       "dropbox_root": "Gốc Dropbox", | ||||
|       "default_driver": "Trình điều khiển mặc định", | ||||
| @ -1023,7 +1026,7 @@ | ||||
|     "email": "E-mail", | ||||
|     "password": "Mật khẩu", | ||||
|     "confirm_password": "Xác nhận mật khẩu", | ||||
|         "save_cont": "Lưu", | ||||
|     "save_cont": "Tiết kiệm", | ||||
|     "company_info": "Thông tin công ty", | ||||
|     "company_info_desc": "Thông tin này sẽ được hiển thị trên hóa đơn. Lưu ý rằng bạn có thể chỉnh sửa điều này sau trên trang cài đặt.", | ||||
|     "company_name": "Tên công ty", | ||||
| @ -1072,11 +1075,11 @@ | ||||
|       "host": "Máy chủ Thư", | ||||
|       "port": "Cổng thư", | ||||
|       "driver": "Trình điều khiển Thư", | ||||
|             "secret": "Khóa", | ||||
|             "mailgun_secret": "Khóa Mailgun", | ||||
|       "secret": "Bí mật", | ||||
|       "mailgun_secret": "Bí mật Mailgun", | ||||
|       "mailgun_domain": "Miền", | ||||
|       "mailgun_endpoint": "Điểm cuối của Mailgun", | ||||
|             "ses_secret": "Khóa SES", | ||||
|       "ses_secret": "Bí mật SES", | ||||
|       "ses_key": "Khóa SES", | ||||
|       "password": "Mật khẩu thư", | ||||
|       "username": "Tên người dùng thư", | ||||
| @ -1088,7 +1091,7 @@ | ||||
|     }, | ||||
|     "req": { | ||||
|       "system_req": "yêu cầu hệ thống", | ||||
|             "php_req_version": "Php (version {version} required)", | ||||
|       "php_req_version": "Php (bắt buộc phải có phiên bản {version})", | ||||
|       "check_req": "Kiểm tra yêu cầu", | ||||
|       "system_req_desc": "Crater có một số yêu cầu máy chủ. Đảm bảo rằng máy chủ của bạn có phiên bản php bắt buộc và tất cả các phần mở rộng được đề cập bên dưới." | ||||
|     }, | ||||
| @ -1110,7 +1113,7 @@ | ||||
|     "for_freelancer": "dành cho những người làm nghề tự do", | ||||
|     "small_businesses": "Tiểu thương", | ||||
|     "crater_help": "Crater giúp bạn theo dõi chi phí, ghi lại các khoản thanh toán", | ||||
|         "invoices_and_estimates": "hóa đơn và ước tính với khả năng chọn nhiều mẫu." | ||||
|     "invoices_and_estimates": "hóa đơn" | ||||
|   }, | ||||
|   "validation": { | ||||
|     "invalid_phone": "Số điện thoại không hợp lệ", | ||||
| @ -1148,7 +1151,8 @@ | ||||
|     "address_maxlength": "Địa chỉ không được lớn hơn 255 ký tự.", | ||||
|     "ref_number_maxlength": "Số tham chiếu không được lớn hơn 255 ký tự.", | ||||
|     "prefix_maxlength": "Tiền tố không được lớn hơn 5 ký tự.", | ||||
|         "something_went_wrong": "có gì đó không ổn" | ||||
|     "something_went_wrong": "có gì đó không ổn", | ||||
|     "number_length_minvalue": "Number lenght should be greater than 0" | ||||
|   }, | ||||
|   "pdf_estimate_label": "Ước tính", | ||||
|   "pdf_estimate_number": "Số ước tính", | ||||
| @ -1180,14 +1184,14 @@ | ||||
|   "pdf_tax_summery_label": "Báo cáo Tóm tắt Thuế", | ||||
|   "pdf_income_label": "THU NHẬP = EARNINGS", | ||||
|   "pdf_net_profit_label": "LỢI NHUẬN RÒNG", | ||||
|     "pdf_customer_sales_report": "Báo cáo bán hàng: Theo khách hàng", | ||||
|   "pdf_customer_sales_report": "Báo cáo bán hàng: Bởi khách hàng", | ||||
|   "pdf_total_sales_label": "TỔNG DOANH SỐ BÁN HÀNG", | ||||
|   "pdf_item_sales_label": "Báo cáo bán hàng: Theo mặt hàng", | ||||
|   "pdf_tax_report_label": "BÁO CÁO THUẾ", | ||||
|   "pdf_total_tax_label": "TỔNG THUẾ", | ||||
|   "pdf_tax_types_label": "Các loại thuế", | ||||
|   "pdf_expenses_label": "Chi phí", | ||||
|     "pdf_bill_to": "Xuất từ,", | ||||
|     "pdf_ship_to": "Chuyển tới,", | ||||
|     "pdf_received_from": "Nhận từ:" | ||||
|   "pdf_bill_to": "Hoa đơn để,", | ||||
|   "pdf_ship_to": "Tàu,", | ||||
|   "pdf_received_from": "Nhận được tư:" | ||||
| } | ||||
|  | ||||
| @ -1,9 +1,9 @@ | ||||
| { | ||||
|   "navigation": { | ||||
|     "dashboard": "Dashboard", | ||||
|     "customers": "Customers", | ||||
|     "dashboard": "管理面板", | ||||
|     "customers": "客户", | ||||
|     "items": "Items", | ||||
|     "invoices": "Invoices", | ||||
|     "invoices": "发票", | ||||
|     "expenses": "Expenses", | ||||
|     "estimates": "Estimates", | ||||
|     "payments": "Payments", | ||||
| @ -18,11 +18,11 @@ | ||||
|     "copy_pdf_url": "Copy PDF Url", | ||||
|     "download_pdf": "Download PDF", | ||||
|     "save": "Save", | ||||
|     "create": "Create", | ||||
|     "cancel": "Cancel", | ||||
|     "update": "Update", | ||||
|     "deselect": "Deselect", | ||||
|     "download": "Download", | ||||
|     "create": "创建", | ||||
|     "cancel": "取消", | ||||
|     "update": "更新", | ||||
|     "deselect": "取消选择", | ||||
|     "download": "下载", | ||||
|     "from_date": "From Date", | ||||
|     "to_date": "To Date", | ||||
|     "from": "From", | ||||
| @ -51,7 +51,7 @@ | ||||
|     "fixed": "Fixed", | ||||
|     "percentage": "Percentage", | ||||
|     "tax": "TAX", | ||||
|     "total_amount": "TOTAL AMOUNT", | ||||
|     "total_amount": "总计", | ||||
|     "bill_to": "Bill to", | ||||
|     "ship_to": "Ship to", | ||||
|     "due": "Due", | ||||
| @ -61,14 +61,14 @@ | ||||
|     "select_all": "Select All", | ||||
|     "choose_file": "Click here to choose a file", | ||||
|     "choose_template": "Choose a template", | ||||
|     "choose": "Choose", | ||||
|     "remove": "Remove", | ||||
|     "choose": "选择", | ||||
|     "remove": "删除", | ||||
|     "powered_by": "Powered by", | ||||
|     "bytefury": "Bytefury", | ||||
|     "select_a_status": "Select a status", | ||||
|     "select_a_status": "选择状态", | ||||
|     "select_a_tax": "Select a tax", | ||||
|     "search": "Search", | ||||
|     "are_you_sure": "Are you sure?", | ||||
|     "search": "搜索", | ||||
|     "are_you_sure": "您确定吗?", | ||||
|     "list_is_empty": "List is empty.", | ||||
|     "no_tax_found": "No tax found!", | ||||
|     "four_zero_four": "404", | ||||
|  | ||||
| @ -60,10 +60,7 @@ export const fetchEstimate = ({ commit, dispatch, state }, id) => { | ||||
|     window.axios | ||||
|       .get(`/api/v1/estimates/${id}`) | ||||
|       .then((response) => { | ||||
|         commit( | ||||
|           types.SET_TEMPLATE_ID, | ||||
|           response.data.estimate.estimate_template_id | ||||
|         ) | ||||
|         commit(types.SET_TEMPLATE_NAME, response.data.estimate.template_name) | ||||
|         resolve(response) | ||||
|       }) | ||||
|       .catch((err) => { | ||||
| @ -297,7 +294,7 @@ export const resetItem = ({ commit, dispatch, state }) => { | ||||
|  | ||||
| export const setTemplate = ({ commit, dispatch, state }, data) => { | ||||
|   return new Promise((resolve, reject) => { | ||||
|     commit(types.SET_TEMPLATE_ID, data) | ||||
|     commit(types.SET_TEMPLATE_NAME, data) | ||||
|     resolve({}) | ||||
|   }) | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| export const estimates = (state) => state.estimates | ||||
| export const selectAllField = (state) => state.selectAllField | ||||
| export const getTemplateId = (state) => state.estimateTemplateId | ||||
| export const getTemplateName = (state) => state.estimateTemplateName | ||||
| export const selectedEstimates = (state) => state.selectedEstimates | ||||
| export const totalEstimates = (state) => state.totalEstimates | ||||
| export const selectedCustomer = (state) => state.selectedCustomer | ||||
|  | ||||
| @ -4,7 +4,7 @@ import * as getters from './getters' | ||||
|  | ||||
| const initialState = { | ||||
|   estimates: [], | ||||
|   estimateTemplateId: 1, | ||||
|   estimateTemplateName: null, | ||||
|   selectAllField: false, | ||||
|   selectedEstimates: [], | ||||
|   totalEstimates: 0, | ||||
|  | ||||
| @ -9,7 +9,7 @@ export const RESET_CUSTOMER = 'RESET_CUSTOMER' | ||||
| export const RESET_ITEM = 'RESET_ITEM' | ||||
| export const SET_CUSTOMER = 'SET_CUSTOMER' | ||||
| export const SET_ITEM = 'SET_ITEM' | ||||
| export const SET_TEMPLATE_ID = 'SET_TEMPLATE_ID' | ||||
| export const SET_TEMPLATE_NAME = 'SET_TEMPLATE_NAME' | ||||
| export const SELECT_CUSTOMER = 'SELECT_CUSTOMER' | ||||
| export const RESET_SELECTED_CUSTOMER = 'RESET_SELECTED_CUSTOMER' | ||||
| export const SET_SELECT_ALL_STATE = 'SET_SELECT_ALL_STATE' | ||||
|  | ||||
| @ -52,8 +52,8 @@ export default { | ||||
|     state.selectAllField = false | ||||
|   }, | ||||
|  | ||||
|   [types.SET_TEMPLATE_ID](state, templateId) { | ||||
|     state.estimateTemplateId = templateId | ||||
|   [types.SET_TEMPLATE_NAME](state, templateName) { | ||||
|     state.estimateTemplateName = templateName | ||||
|   }, | ||||
|  | ||||
|   [types.SELECT_CUSTOMER](state, data) { | ||||
|  | ||||
| @ -21,7 +21,7 @@ export const fetchInvoice = ({ commit, dispatch, state }, id) => { | ||||
|     window.axios | ||||
|       .get(`/api/v1/invoices/${id}`) | ||||
|       .then((response) => { | ||||
|         commit(types.SET_TEMPLATE_ID, response.data.invoice.invoice_template_id) | ||||
|         commit(types.SET_TEMPLATE_NAME, response.data.invoice.template_name) | ||||
|         resolve(response) | ||||
|       }) | ||||
|       .catch((err) => { | ||||
| @ -219,7 +219,7 @@ export const resetCustomer = ({ commit, dispatch, state }) => { | ||||
|  | ||||
| export const setTemplate = ({ commit, dispatch, state }, data) => { | ||||
|   return new Promise((resolve, reject) => { | ||||
|     commit(types.SET_TEMPLATE_ID, data) | ||||
|     commit(types.SET_TEMPLATE_NAME, data) | ||||
|     resolve({}) | ||||
|   }) | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| export const invoices = (state) => state.invoices | ||||
| export const selectAllField = (state) => state.selectAllField | ||||
| export const getTemplateId = (state) => state.invoiceTemplateId | ||||
| export const getTemplateName = (state) => state.invoiceTemplateName | ||||
| export const selectedInvoices = (state) => state.selectedInvoices | ||||
| export const totalInvoices = (state) => state.totalInvoices | ||||
| export const selectedCustomer = (state) => state.selectedCustomer | ||||
|  | ||||
| @ -4,7 +4,7 @@ import * as getters from './getters' | ||||
|  | ||||
| const initialState = { | ||||
|   invoices: [], | ||||
|   invoiceTemplateId: 1, | ||||
|   invoiceTemplateName: null, | ||||
|   selectedInvoices: [], | ||||
|   selectAllField: false, | ||||
|   totalInvoices: 0, | ||||
|  | ||||
| @ -12,7 +12,7 @@ export const SET_CUSTOMER = 'SET_CUSTOMER' | ||||
| export const RESET_ITEM = 'RESET_ITEM' | ||||
| export const SET_ITEM = 'SET_ITEM' | ||||
|  | ||||
| export const SET_TEMPLATE_ID = 'SET_TEMPLATE_ID' | ||||
| export const SET_TEMPLATE_NAME = 'SET_TEMPLATE_NAME' | ||||
|  | ||||
| export const SELECT_CUSTOMER = 'SELECT_CUSTOMER' | ||||
| export const RESET_SELECTED_CUSTOMER = 'RESET_SELECTED_CUSTOMER' | ||||
|  | ||||
| @ -51,8 +51,8 @@ export default { | ||||
|     state.selectedInvoices = [] | ||||
|   }, | ||||
|  | ||||
|   [types.SET_TEMPLATE_ID](state, templateId) { | ||||
|     state.invoiceTemplateId = templateId | ||||
|   [types.SET_TEMPLATE_NAME](state, templateName) { | ||||
|     state.invoiceTemplateName = templateName | ||||
|   }, | ||||
|  | ||||
|   [types.SELECT_CUSTOMER](state, data) { | ||||
|  | ||||
| @ -80,7 +80,7 @@ export default { | ||||
|           if (res.data) { | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: 'Mail sent successfuly!', | ||||
|               message: 'Mail sent successfully!', | ||||
|             }) | ||||
|           } | ||||
|  | ||||
|  | ||||
| @ -266,8 +266,8 @@ | ||||
|               variant="gray" | ||||
|               @click="openTemplateModal" | ||||
|             > | ||||
|               <span class="flex text-black"> | ||||
|                 {{ $t('estimates.estimate_template') }} {{ getTemplateId }} | ||||
|               <span class="flex text-black capitalize"> | ||||
|                 {{ getTemplateName }} | ||||
|                 <pencil-icon class="h-5 ml-2 -mr-1" /> | ||||
|               </span> | ||||
|             </sw-button> | ||||
| @ -514,9 +514,9 @@ export default { | ||||
|     ...mapGetters('company', ['defaultCurrency']), | ||||
|  | ||||
|     ...mapGetters('estimate', [ | ||||
|       'getTemplateId', | ||||
|       'selectedCustomer', | ||||
|       'selectedNote', | ||||
|       'getTemplateName', | ||||
|     ]), | ||||
|  | ||||
|     ...mapGetters('estimateTemplate', ['getEstimateTemplates']), | ||||
| @ -708,6 +708,7 @@ export default { | ||||
|       'selectCustomer', | ||||
|       'updateEstimate', | ||||
|       'resetSelectedNote', | ||||
|       'setTemplate', | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('item', ['fetchItems']), | ||||
| @ -789,6 +790,7 @@ export default { | ||||
|               this.estimateNumAttribute = res4.data.nextNumber | ||||
|               this.estimatePrefix = res4.data.prefix | ||||
|             } | ||||
|             this.setTemplate(this.getEstimateTemplates[0].name) | ||||
|           } else { | ||||
|             this.estimatePrefix = res4.data.prefix | ||||
|           } | ||||
| @ -903,7 +905,7 @@ export default { | ||||
|         total: this.total, | ||||
|         tax: this.totalTax, | ||||
|         user_id: null, | ||||
|         estimate_template_id: this.getTemplateId, | ||||
|         template_name: this.getTemplateName, | ||||
|       } | ||||
|  | ||||
|       if (this.selectedCustomer != null) { | ||||
|  | ||||
| @ -183,7 +183,7 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapGetters('estimate', ['getTemplateId', 'selectedCustomer']), | ||||
|     ...mapGetters('estimate', ['getTemplateName', 'selectedCustomer']), | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|  | ||||
| @ -259,7 +259,7 @@ | ||||
|               @click="openTemplateModal" | ||||
|             > | ||||
|               <span class="flex text-black"> | ||||
|                 {{ $t('invoices.template') }} {{ getTemplateId }} | ||||
|                 {{ getTemplateName }} | ||||
|                 <pencil-icon class="h-5 ml-2 -mr-1" /> | ||||
|               </span> | ||||
|             </sw-button> | ||||
| @ -510,7 +510,7 @@ export default { | ||||
|     ...mapGetters('notes', ['notes']), | ||||
|  | ||||
|     ...mapGetters('invoice', [ | ||||
|       'getTemplateId', | ||||
|       'getTemplateName', | ||||
|       'selectedCustomer', | ||||
|       'selectedNote', | ||||
|     ]), | ||||
| @ -710,6 +710,7 @@ export default { | ||||
|       'selectCustomer', | ||||
|       'updateInvoice', | ||||
|       'resetSelectedNote', | ||||
|       'setTemplate', | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('invoiceTemplate', ['fetchInvoiceTemplates']), | ||||
| @ -784,6 +785,7 @@ export default { | ||||
|               this.invoiceNumAttribute = res4.data.nextNumber | ||||
|               this.invoicePrefix = res4.data.prefix | ||||
|             } | ||||
|             this.setTemplate(this.getInvoiceTemplates[0].name) | ||||
|           } else { | ||||
|             this.invoicePrefix = res4.data.prefix | ||||
|           } | ||||
| @ -899,7 +901,7 @@ export default { | ||||
|         total: this.total, | ||||
|         tax: this.totalTax, | ||||
|         user_id: null, | ||||
|         invoice_template_id: this.getTemplateId, | ||||
|         template_name: this.getTemplateName, | ||||
|       } | ||||
|  | ||||
|       if (this.selectedCustomer != null) { | ||||
|  | ||||
| @ -185,7 +185,7 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapGetters('invoice', ['getTemplateId', 'selectedCustomer']), | ||||
|     ...mapGetters('invoice', ['getTemplateName', 'selectedCustomer']), | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|  | ||||
| @ -21,7 +21,6 @@ import SiteSidebar from './partials/TheSiteSidebar.vue' | ||||
| import BaseModal from '../../components/base/modal/BaseModal' | ||||
| import { RefreshIcon } from '@vue-hero-icons/solid' | ||||
| import { mapActions, mapGetters } from 'vuex' | ||||
| import BaseNotification from '../../components/base/BaseNotification.vue' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
| @ -30,7 +29,6 @@ export default { | ||||
|     SiteFooter, | ||||
|     BaseModal, | ||||
|     RefreshIcon, | ||||
|     BaseNotification, | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| <template> | ||||
|   <div class="site-wrapper h-full text-base"> | ||||
|   <div class="h-full text-base site-wrapper"> | ||||
|     <base-notification /> | ||||
|     <div class="container mx-auto"> | ||||
|       <router-view></router-view> | ||||
|     </div> | ||||
|  | ||||
| @ -22,6 +22,7 @@ | ||||
| import SystemRequirement from './WizardSystemRequirementStep' | ||||
| import Permission from './WizardPermissionStep' | ||||
| import Database from './WizardDatabaseStep' | ||||
| import VerifyDomain from './WizardVerifyDomainStep' | ||||
| import EmailConfiguration from './WizardEmailConfigStep' | ||||
| import UserProfile from './WizardUserProfileStep' | ||||
| import CompanyInfo from './WizardCompanyInfoStep' | ||||
| @ -32,10 +33,11 @@ export default { | ||||
|     step_1: SystemRequirement, | ||||
|     step_2: Permission, | ||||
|     step_3: Database, | ||||
|     step_4: EmailConfiguration, | ||||
|     step_5: UserProfile, | ||||
|     step_6: CompanyInfo, | ||||
|     step_7: Settings, | ||||
|     step_4: VerifyDomain, | ||||
|     step_5: EmailConfiguration, | ||||
|     step_6: UserProfile, | ||||
|     step_7: CompanyInfo, | ||||
|     step_8: Settings, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
| @ -69,16 +71,27 @@ export default { | ||||
|       let status = { | ||||
|         profile_complete: data, | ||||
|       } | ||||
|  | ||||
|       let response = await axios.post('/api/v1/onboarding/wizard-step', status) | ||||
|       try { | ||||
|         let response = await axios.post( | ||||
|           '/api/v1/onboarding/wizard-step', | ||||
|           status | ||||
|         ) | ||||
|         return true | ||||
|       } catch (e) { | ||||
|         if (e?.response?.data?.message === 'The MAC is invalid.') { | ||||
|           window.location.reload() | ||||
|         } | ||||
|         return false | ||||
|       } | ||||
|     }, | ||||
|     async setTab(data) { | ||||
|       if (data) { | ||||
|         this.setProfileComplete(data) | ||||
|         let res = await this.setProfileComplete(data) | ||||
|         if (!res) return false | ||||
|       } | ||||
|       this.step++ | ||||
|  | ||||
|       if (this.step <= 7) { | ||||
|       if (this.step <= 8) { | ||||
|         this.tab = 'step_' + this.step | ||||
|       } else { | ||||
|         // window.location.reload() | ||||
|  | ||||
| @ -297,7 +297,7 @@ export default { | ||||
|           }) | ||||
|         } | ||||
|  | ||||
|         this.$emit('next', 6) | ||||
|         this.$emit('next', 7) | ||||
|         this.isLoading = false | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -16,18 +16,15 @@ | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { validationMixin } from 'vuelidate' | ||||
| import Mysql from './database/MysqlDatabase' | ||||
| import Pgsql from './database/PgsqlDatabase' | ||||
| import Sqlite from './database/SqliteDatabase' | ||||
| import Sqlsrv from './database/SqlsrvDatabase' | ||||
| import { mapActions } from 'vuex' | ||||
| export default { | ||||
|   components: { | ||||
|     Mysql, | ||||
|     Pgsql, | ||||
|     Sqlite, | ||||
|     Sqlsrv, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
| @ -37,7 +34,7 @@ export default { | ||||
|       isLoading: false, | ||||
|       isFetching: false, | ||||
|       database_connection: 'mysql', | ||||
|       connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'], | ||||
|       connections: ['sqlite', 'mysql', 'pgsql'], | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
| @ -67,15 +64,11 @@ export default { | ||||
|     async next(databaseData) { | ||||
|       this.isLoading = this.isFetching = true | ||||
|       try { | ||||
|         await window.axios.get('/sanctum/csrf-cookie') | ||||
|  | ||||
|         let response = await window.axios.post( | ||||
|           '/api/v1/onboarding/database/config', | ||||
|           databaseData | ||||
|         ) | ||||
|  | ||||
|         await window.axios.get('/sanctum/csrf-cookie') | ||||
|  | ||||
|         if (response.data.success) { | ||||
|           await window.axios.post('/api/v1/onboarding/finish') | ||||
|  | ||||
| @ -88,6 +81,16 @@ export default { | ||||
|  | ||||
|           return true | ||||
|         } else if (response.data.error) { | ||||
|           if (response.data.requirement) { | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: this.$t('wizard.errors.' + response.data.error, { | ||||
|                 version: response.data.requirement.minimum, | ||||
|                 name: this.database_connection, | ||||
|               }), | ||||
|             }) | ||||
|             return | ||||
|           } | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('wizard.errors.' + response.data.error), | ||||
|  | ||||
| @ -67,7 +67,7 @@ export default { | ||||
|           mailConfigData | ||||
|         ) | ||||
|         if (response.data.success) { | ||||
|           this.$emit('next', 4) | ||||
|           this.$emit('next', 5) | ||||
|           this.showNotification({ | ||||
|             type: 'success', | ||||
|             message: this.$t('wizard.success.' + response.data.success), | ||||
|  | ||||
| @ -246,7 +246,7 @@ export default { | ||||
|  | ||||
|           this.uploadAvatar(avatarData) | ||||
|         } | ||||
|         this.$emit('next', 5) | ||||
|         this.$emit('next', 6) | ||||
|         this.isLoading = false | ||||
|       } | ||||
|       return true | ||||
|  | ||||
							
								
								
									
										136
									
								
								resources/assets/js/views/wizard/WizardVerifyDomainStep.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,136 @@ | ||||
| <template> | ||||
|   <sw-wizard-step | ||||
|     :title="$t('wizard.verify_domain.title')" | ||||
|     :description="$t('wizard.verify_domain.desc')" | ||||
|   > | ||||
|     <div class="w-full md:w-2/3"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.verify_domain.app_domain')" | ||||
|         :error="domainError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.formData.app_domain.$error" | ||||
|           v-model.trim="formData.app_domain" | ||||
|           type="text" | ||||
|           name="name" | ||||
|           placeholder="crater.com" | ||||
|           @input="$v.formData.app_domain.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|  | ||||
|     <p class="mt-4 mb-0 text-sm text-gray-600">Notes:</p> | ||||
|     <ul class="w-full text-gray-600 list-disc list-inside"> | ||||
|       <li class="text-sm leading-8"> | ||||
|         App domain should not contain | ||||
|         <b class="inline-block px-1 bg-gray-100 rounded-sm">https://</b> or | ||||
|         <b class="inline-block px-1 bg-gray-100 rounded-sm">http</b> in front of | ||||
|         the domain. | ||||
|       </li> | ||||
|       <li class="text-sm leading-8"> | ||||
|         If you're accessing the website on a different port, please mention the | ||||
|         port. For example: | ||||
|         <b class="inline-block px-1 bg-gray-100">localhost:8080</b> | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <sw-button | ||||
|       :loading="isLoading" | ||||
|       :disabled="isLoading" | ||||
|       class="mt-8" | ||||
|       variant="primary" | ||||
|       @click="verifyDomain" | ||||
|     > | ||||
|       {{ $t('wizard.verify_domain.verify_now') }} | ||||
|     </sw-button> | ||||
|   </sw-wizard-step> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { ArrowRightIcon } from '@vue-hero-icons/solid' | ||||
| const { required } = require('vuelidate/lib/validators') | ||||
| import { mapActions } from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     ArrowRightIcon, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       formData: { | ||||
|         app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''), | ||||
|       }, | ||||
|       isLoading: false, | ||||
|       isShow: true, | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   validations: { | ||||
|     formData: { | ||||
|       app_domain: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidDomainUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     hasNext() { | ||||
|       return false | ||||
|     }, | ||||
|     domainError() { | ||||
|       if (!this.$v.formData.app_domain.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.formData.app_domain.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.formData.app_domain.isUrl) { | ||||
|         return this.$tc('validation.invalid_domain_url') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     listToggle() { | ||||
|       this.isShow = !this.isShow | ||||
|     }, | ||||
|  | ||||
|     async verifyDomain() { | ||||
|       this.$v.formData.$touch() | ||||
|  | ||||
|       if (this.$v.formData.$invalid) { | ||||
|         return true | ||||
|       } | ||||
|  | ||||
|       this.isLoading = true | ||||
|       try { | ||||
|         await window.axios.put('api/v1/onboarding/set-domain', this.formData) | ||||
|  | ||||
|         await window.axios.get('/sanctum/csrf-cookie') | ||||
|  | ||||
|         await window.axios.post('/api/v1/onboarding/login') | ||||
|  | ||||
|         let driverRes = await window.axios.get('/api/v1/auth/check') | ||||
|  | ||||
|         if (driverRes.data) { | ||||
|           await this.$emit('next', 4) | ||||
|         } | ||||
|         this.isLoading = false | ||||
|       } catch (e) { | ||||
|         this.showNotification({ | ||||
|           type: 'error', | ||||
|           message: this.$t('wizard.errors.domain_verification_failed'), | ||||
|         }) | ||||
|         this.isLoading = false | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
| @ -1,7 +1,7 @@ | ||||
| <template> | ||||
|   <form action="" @submit.prevent="next()"> | ||||
|     <div> | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|       <div class="grid grid-cols-1 gap-5 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_url')" | ||||
|           :error="urlError" | ||||
| @ -16,23 +16,6 @@ | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_domain')" | ||||
|           :error="domainError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_domain.$error" | ||||
|             v-model.trim="databaseData.app_domain" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             placeholder="crater.com" | ||||
|             @input="$v.databaseData.app_domain.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.connection')" | ||||
|           :error="connectionError" | ||||
| @ -62,9 +45,7 @@ | ||||
|             @input="$v.databaseData.database_port.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.db_name')" | ||||
|           :error="nameError" | ||||
| @ -92,9 +73,7 @@ | ||||
|             @input="$v.databaseData.database_username.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|         <sw-input-group :label="$t('wizard.database.password')"> | ||||
|           <sw-input | ||||
|             v-model.trim="databaseData.database_password" | ||||
| @ -102,7 +81,9 @@ | ||||
|             name="name" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.host')" | ||||
|           :error="hostnameError" | ||||
| @ -168,9 +149,8 @@ export default { | ||||
|         database_username: null, | ||||
|         database_password: null, | ||||
|         app_url: window.location.origin, | ||||
|         app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''), | ||||
|       }, | ||||
|       connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'], | ||||
|       connections: ['sqlite', 'mysql', 'pgsql'], | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
| @ -197,12 +177,6 @@ export default { | ||||
|           return this.$utils.checkValidUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|       app_domain: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidDomainUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
| @ -219,19 +193,6 @@ export default { | ||||
|         return this.$tc('validation.invalid_url') | ||||
|       } | ||||
|     }, | ||||
|     domainError() { | ||||
|       if (!this.$v.databaseData.app_domain.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.isUrl) { | ||||
|         return this.$tc('validation.invalid_domain_url') | ||||
|       } | ||||
|     }, | ||||
|     connectionError() { | ||||
|       if (!this.$v.databaseData.database_connection.$error) { | ||||
|         return '' | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <template> | ||||
|   <form action="" @submit.prevent="next()"> | ||||
|     <div> | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|       <div class="grid grid-cols-1 gap-5 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_url')" | ||||
|           :error="urlError" | ||||
| @ -16,23 +16,6 @@ | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_domain')" | ||||
|           :error="domainError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_domain.$error" | ||||
|             v-model.trim="databaseData.app_domain" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             placeholder="crater.com" | ||||
|             @input="$v.databaseData.app_domain.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.connection')" | ||||
|           :error="connectionError" | ||||
| @ -62,9 +45,7 @@ | ||||
|             @input="$v.databaseData.database_port.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.db_name')" | ||||
|           :error="nameError" | ||||
| @ -92,9 +73,7 @@ | ||||
|             @input="$v.databaseData.database_username.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|         <sw-input-group :label="$t('wizard.database.password')"> | ||||
|           <sw-input | ||||
|             v-model.trim="databaseData.database_password" | ||||
| @ -134,8 +113,7 @@ | ||||
|  | ||||
| <script> | ||||
| import { SaveIcon } from '@vue-hero-icons/outline' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, numeric, url } = require('vuelidate/lib/validators') | ||||
| const { required, numeric } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
| @ -168,9 +146,8 @@ export default { | ||||
|         database_username: null, | ||||
|         database_password: null, | ||||
|         app_url: window.location.origin, | ||||
|         app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''), | ||||
|       }, | ||||
|       connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'], | ||||
|       connections: ['sqlite', 'mysql', 'pgsql'], | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
| @ -187,19 +164,6 @@ export default { | ||||
|         return this.$tc('validation.invalid_url') | ||||
|       } | ||||
|     }, | ||||
|     domainError() { | ||||
|       if (!this.$v.databaseData.app_domain.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.isUrl) { | ||||
|         return this.$tc('validation.invalid_domain_url') | ||||
|       } | ||||
|     }, | ||||
|     connectionError() { | ||||
|       if (!this.$v.databaseData.database_connection.$error) { | ||||
|         return '' | ||||
| @ -274,12 +238,6 @@ export default { | ||||
|           return this.$utils.checkValidUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|       app_domain: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidDomainUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <template> | ||||
|   <form action="" @submit.prevent="next()"> | ||||
|     <div> | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|       <div class="grid grid-cols-1 gap-5 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_url')" | ||||
|           :error="urlError" | ||||
| @ -16,23 +16,6 @@ | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_domain')" | ||||
|           :error="domainError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_domain.$error" | ||||
|             v-model.trim="databaseData.app_domain" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             placeholder="crater.com" | ||||
|             @input="$v.databaseData.app_domain.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.connection')" | ||||
|           :error="connectionError" | ||||
| @ -81,8 +64,7 @@ | ||||
|  | ||||
| <script> | ||||
| import { SaveIcon } from '@vue-hero-icons/outline' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, numeric, url } = require('vuelidate/lib/validators') | ||||
| const { required } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
| @ -111,9 +93,8 @@ export default { | ||||
|         database_connection: 'mysql', | ||||
|         database_name: null, | ||||
|         app_url: window.location.origin, | ||||
|         app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''), | ||||
|       }, | ||||
|       connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'], | ||||
|       connections: ['sqlite', 'mysql', 'pgsql'], | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
| @ -130,12 +111,6 @@ export default { | ||||
|           return this.$utils.checkValidUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|       app_domain: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidDomainUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
| @ -152,19 +127,6 @@ export default { | ||||
|         return this.$tc('validation.invalid_url') | ||||
|       } | ||||
|     }, | ||||
|     domainError() { | ||||
|       if (!this.$v.databaseData.app_domain.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.isUrl) { | ||||
|         return this.$tc('validation.invalid_domain_url') | ||||
|       } | ||||
|     }, | ||||
|     connectionError() { | ||||
|       if (!this.$v.databaseData.database_connection.$error) { | ||||
|         return '' | ||||
|  | ||||
