├── .dockerignore ├── .editorconfig ├── .env.example ├── .env.testing ├── .eslintrc.js ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── ci.yaml │ ├── uffizzi-build.yml │ └── uffizzi-preview.yml ├── .gitignore ├── .php-cs-fixer.dist.php ├── .prettierrc.json ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── LICENSE ├── SECURITY.md ├── _ide_helper.php ├── app ├── Console │ ├── Commands │ │ ├── CheckEstimateStatus.php │ │ ├── CheckInvoiceStatus.php │ │ ├── CreateTemplateCommand.php │ │ ├── InstallModuleCommand.php │ │ ├── ResetApp.php │ │ └── UpdateCommand.php │ └── Kernel.php ├── Events │ ├── ModuleDisabledEvent.php │ ├── ModuleEnabledEvent.php │ ├── ModuleInstalledEvent.php │ └── UpdateFinished.php ├── Exceptions │ └── Handler.php ├── Generators │ └── CustomPathGenerator.php ├── Http │ ├── Controllers │ │ ├── AppVersionController.php │ │ ├── Controller.php │ │ └── V1 │ │ │ ├── Admin │ │ │ ├── Auth │ │ │ │ ├── ConfirmPasswordController.php │ │ │ │ ├── ForgotPasswordController.php │ │ │ │ ├── LoginController.php │ │ │ │ ├── RegisterController.php │ │ │ │ ├── ResetPasswordController.php │ │ │ │ └── VerificationController.php │ │ │ ├── Backup │ │ │ │ ├── ApiController.php │ │ │ │ ├── BackupsController.php │ │ │ │ └── DownloadBackupController.php │ │ │ ├── Company │ │ │ │ ├── CompaniesController.php │ │ │ │ └── CompanyController.php │ │ │ ├── Config │ │ │ │ ├── FiscalYearsController.php │ │ │ │ ├── LanguagesController.php │ │ │ │ └── RetrospectiveEditsController.php │ │ │ ├── CustomField │ │ │ │ └── CustomFieldsController.php │ │ │ ├── Customer │ │ │ │ ├── CustomerStatsController.php │ │ │ │ └── CustomersController.php │ │ │ ├── Dashboard │ │ │ │ └── DashboardController.php │ │ │ ├── Estimate │ │ │ │ ├── ChangeEstimateStatusController.php │ │ │ │ ├── ConvertEstimateController.php │ │ │ │ ├── EstimateTemplatesController.php │ │ │ │ ├── EstimatesController.php │ │ │ │ ├── SendEstimateController.php │ │ │ │ └── SendEstimatePreviewController.php │ │ │ ├── ExchangeRate │ │ │ │ ├── ExchangeRateProviderController.php │ │ │ │ ├── GetActiveProviderController.php │ │ │ │ ├── GetExchangeRateController.php │ │ │ │ ├── GetSupportedCurrenciesController.php │ │ │ │ └── GetUsedCurrenciesController.php │ │ │ ├── Expense │ │ │ │ ├── ExpenseCategoriesController.php │ │ │ │ ├── ExpensesController.php │ │ │ │ ├── ShowReceiptController.php │ │ │ │ └── UploadReceiptController.php │ │ │ ├── General │ │ │ │ ├── BootstrapController.php │ │ │ │ ├── BulkExchangeRateController.php │ │ │ │ ├── ConfigController.php │ │ │ │ ├── CountriesController.php │ │ │ │ ├── CurrenciesController.php │ │ │ │ ├── DateFormatsController.php │ │ │ │ ├── GetAllUsedCurrenciesController.php │ │ │ │ ├── NextNumberController.php │ │ │ │ ├── NotesController.php │ │ │ │ ├── NumberPlaceholdersController.php │ │ │ │ ├── SearchController.php │ │ │ │ ├── SearchUsersController.php │ │ │ │ └── TimezonesController.php │ │ │ ├── Invoice │ │ │ │ ├── ChangeInvoiceStatusController.php │ │ │ │ ├── CloneInvoiceController.php │ │ │ │ ├── InvoiceTemplatesController.php │ │ │ │ ├── InvoicesController.php │ │ │ │ ├── SendInvoiceController.php │ │ │ │ └── SendInvoicePreviewController.php │ │ │ ├── Item │ │ │ │ ├── ItemsController.php │ │ │ │ └── UnitsController.php │ │ │ ├── Mobile │ │ │ │ └── AuthController.php │ │ │ ├── Modules │ │ │ │ ├── ApiTokenController.php │ │ │ │ ├── CompleteModuleInstallationController.php │ │ │ │ ├── CopyModuleController.php │ │ │ │ ├── DisableModuleController.php │ │ │ │ ├── DownloadModuleController.php │ │ │ │ ├── EnableModuleController.php │ │ │ │ ├── ModuleController.php │ │ │ │ ├── ModulesController.php │ │ │ │ ├── UnzipModuleController.php │ │ │ │ └── UploadModuleController.php │ │ │ ├── Payment │ │ │ │ ├── PaymentMethodsController.php │ │ │ │ ├── PaymentsController.php │ │ │ │ ├── SendPaymentController.php │ │ │ │ └── SendPaymentPreviewController.php │ │ │ ├── RecurringInvoice │ │ │ │ ├── RecurringInvoiceController.php │ │ │ │ └── RecurringInvoiceFrequencyController.php │ │ │ ├── Report │ │ │ │ ├── CustomerSalesReportController.php │ │ │ │ ├── ExpensesReportController.php │ │ │ │ ├── ItemSalesReportController.php │ │ │ │ ├── ProfitLossReportController.php │ │ │ │ └── TaxSummaryReportController.php │ │ │ ├── Role │ │ │ │ ├── AbilitiesController.php │ │ │ │ └── RolesController.php │ │ │ ├── Settings │ │ │ │ ├── CompanyController.php │ │ │ │ ├── CompanyCurrencyCheckTransactionsController.php │ │ │ │ ├── DiskController.php │ │ │ │ ├── GetCompanyMailConfigurationController.php │ │ │ │ ├── GetCompanySettingsController.php │ │ │ │ ├── GetSettingsController.php │ │ │ │ ├── GetUserSettingsController.php │ │ │ │ ├── MailConfigurationController.php │ │ │ │ ├── TaxTypesController.php │ │ │ │ ├── UpdateCompanySettingsController.php │ │ │ │ ├── UpdateSettingsController.php │ │ │ │ └── UpdateUserSettingsController.php │ │ │ ├── Update │ │ │ │ ├── CheckVersionController.php │ │ │ │ ├── CopyFilesController.php │ │ │ │ ├── DeleteFilesController.php │ │ │ │ ├── DownloadUpdateController.php │ │ │ │ ├── FinishUpdateController.php │ │ │ │ ├── MigrateUpdateController.php │ │ │ │ ├── UnzipUpdateController.php │ │ │ │ └── UpdateController.php │ │ │ └── Users │ │ │ │ └── UsersController.php │ │ │ ├── Customer │ │ │ ├── Auth │ │ │ │ ├── ForgotPasswordController.php │ │ │ │ ├── LoginController.php │ │ │ │ └── ResetPasswordController.php │ │ │ ├── Estimate │ │ │ │ ├── AcceptEstimateController.php │ │ │ │ └── EstimatesController.php │ │ │ ├── EstimatePdfController.php │ │ │ ├── Expense │ │ │ │ └── ExpensesController.php │ │ │ ├── General │ │ │ │ ├── BootstrapController.php │ │ │ │ ├── DashboardController.php │ │ │ │ └── ProfileController.php │ │ │ ├── Invoice │ │ │ │ └── InvoicesController.php │ │ │ ├── InvoicePdfController.php │ │ │ ├── Payment │ │ │ │ ├── PaymentMethodController.php │ │ │ │ └── PaymentsController.php │ │ │ └── PaymentPdfController.php │ │ │ ├── Installation │ │ │ ├── AppDomainController.php │ │ │ ├── DatabaseConfigurationController.php │ │ │ ├── FilePermissionsController.php │ │ │ ├── FinishController.php │ │ │ ├── LoginController.php │ │ │ ├── OnboardingWizardController.php │ │ │ └── RequirementsController.php │ │ │ ├── Modules │ │ │ ├── ScriptController.php │ │ │ └── StyleController.php │ │ │ ├── PDF │ │ │ ├── DownloadInvoicePdfController.php │ │ │ ├── DownloadPaymentPdfController.php │ │ │ ├── DownloadReceiptController.php │ │ │ ├── EstimatePdfController.php │ │ │ ├── InvoicePdfController.php │ │ │ └── PaymentPdfController.php │ │ │ └── Webhook │ │ │ └── CronJobController.php │ ├── Kernel.php │ ├── Middleware │ │ ├── AdminMiddleware.php │ │ ├── Authenticate.php │ │ ├── CompanyMiddleware.php │ │ ├── ConfigMiddleware.php │ │ ├── CronJobMiddleware.php │ │ ├── CustomerPortalMiddleware.php │ │ ├── EncryptCookies.php │ │ ├── InstallationMiddleware.php │ │ ├── PdfMiddleware.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── RedirectIfInstalled.php │ │ ├── RedirectIfUnauthorized.php │ │ ├── ScopeBouncer.php │ │ ├── TrimStrings.php │ │ ├── TrustProxies.php │ │ └── VerifyCsrfToken.php │ ├── Requests │ │ ├── AvatarRequest.php │ │ ├── BulkExchangeRateRequest.php │ │ ├── CompaniesRequest.php │ │ ├── CompanyLogoRequest.php │ │ ├── CompanyRequest.php │ │ ├── CompanySettingRequest.php │ │ ├── CustomFieldRequest.php │ │ ├── Customer │ │ │ ├── CustomerLoginRequest.php │ │ │ └── CustomerProfileRequest.php │ │ ├── CustomerEstimateStatusRequest.php │ │ ├── CustomerRequest.php │ │ ├── DatabaseEnvironmentRequest.php │ │ ├── DeleteCustomersRequest.php │ │ ├── DeleteEstimatesRequest.php │ │ ├── DeleteExpensesRequest.php │ │ ├── DeleteInvoiceRequest.php │ │ ├── DeleteItemsRequest.php │ │ ├── DeletePaymentsRequest.php │ │ ├── DeleteUserRequest.php │ │ ├── DiskEnvironmentRequest.php │ │ ├── DomainEnvironmentRequest.php │ │ ├── EstimatesRequest.php │ │ ├── ExchangeRateLogRequest.php │ │ ├── ExchangeRateProviderRequest.php │ │ ├── ExpenseCategoryRequest.php │ │ ├── ExpenseRequest.php │ │ ├── GetSettingRequest.php │ │ ├── GetSettingsRequest.php │ │ ├── InvoicesRequest.php │ │ ├── ItemsRequest.php │ │ ├── LoginRequest.php │ │ ├── MailEnvironmentRequest.php │ │ ├── NotesRequest.php │ │ ├── PaymentMethodRequest.php │ │ ├── PaymentRequest.php │ │ ├── ProfileRequest.php │ │ ├── RecurringInvoiceRequest.php │ │ ├── Request.php │ │ ├── RoleRequest.php │ │ ├── SendEstimatesRequest.php │ │ ├── SendInvoiceRequest.php │ │ ├── SendPaymentRequest.php │ │ ├── SettingKeyRequest.php │ │ ├── SettingRequest.php │ │ ├── TaxTypeRequest.php │ │ ├── UnitRequest.php │ │ ├── UnzipUpdateRequest.php │ │ ├── UpdateSettingsRequest.php │ │ ├── UploadExpenseReceiptRequest.php │ │ ├── UploadModuleRequest.php │ │ └── UserRequest.php │ └── Resources │ │ ├── AbilityCollection.php │ │ ├── AbilityResource.php │ │ ├── AddressCollection.php │ │ ├── AddressResource.php │ │ ├── CompanyCollection.php │ │ ├── CompanyResource.php │ │ ├── CountryCollection.php │ │ ├── CountryResource.php │ │ ├── CurrencyCollection.php │ │ ├── CurrencyResource.php │ │ ├── CustomFieldCollection.php │ │ ├── CustomFieldResource.php │ │ ├── CustomFieldValueCollection.php │ │ ├── CustomFieldValueResource.php │ │ ├── Customer │ │ ├── AddressCollection.php │ │ ├── AddressResource.php │ │ ├── CompanyResource.php │ │ ├── CountryCollection.php │ │ ├── CountryResource.php │ │ ├── CurrencyCollection.php │ │ ├── CurrencyResource.php │ │ ├── CustomFieldCollection.php │ │ ├── CustomFieldResource.php │ │ ├── CustomFieldValueCollection.php │ │ ├── CustomFieldValueResource.php │ │ ├── CustomerCollection.php │ │ ├── CustomerResource.php │ │ ├── EstimateCollection.php │ │ ├── EstimateItemCollection.php │ │ ├── EstimateItemResource.php │ │ ├── EstimateResource.php │ │ ├── ExpenseCategoryCollection.php │ │ ├── ExpenseCategoryResource.php │ │ ├── ExpenseCollection.php │ │ ├── ExpenseResource.php │ │ ├── InvoiceCollection.php │ │ ├── InvoiceItemCollection.php │ │ ├── InvoiceItemResource.php │ │ ├── InvoiceResource.php │ │ ├── ItemCollection.php │ │ ├── PaymentCollection.php │ │ ├── PaymentMethodCollection.php │ │ ├── PaymentMethodResource.php │ │ ├── PaymentResource.php │ │ ├── RecurringInvoiceCollection.php │ │ ├── RecurringInvoiceResource.php │ │ ├── TaxCollection.php │ │ ├── TaxResource.php │ │ ├── TaxTypeCollection.php │ │ ├── TaxTypeResource.php │ │ ├── TransactionCollection.php │ │ ├── TransactionResource.php │ │ ├── UserCollection.php │ │ └── UserResource.php │ │ ├── CustomerCollection.php │ │ ├── CustomerResource.php │ │ ├── EstimateCollection.php │ │ ├── EstimateItemCollection.php │ │ ├── EstimateItemResource.php │ │ ├── EstimateResource.php │ │ ├── ExchangeRateLogCollection.php │ │ ├── ExchangeRateLogResource.php │ │ ├── ExchangeRateProviderCollection.php │ │ ├── ExchangeRateProviderResource.php │ │ ├── ExpenseCategoryCollection.php │ │ ├── ExpenseCategoryResource.php │ │ ├── ExpenseCollection.php │ │ ├── ExpenseResource.php │ │ ├── FileDiskCollection.php │ │ ├── FileDiskResource.php │ │ ├── InvoiceCollection.php │ │ ├── InvoiceItemCollection.php │ │ ├── InvoiceItemResource.php │ │ ├── InvoiceResource.php │ │ ├── ItemCollection.php │ │ ├── ItemResource.php │ │ ├── ModuleCollection.php │ │ ├── ModuleResource.php │ │ ├── NoteCollection.php │ │ ├── NoteResource.php │ │ ├── PaymentCollection.php │ │ ├── PaymentMethodCollection.php │ │ ├── PaymentMethodResource.php │ │ ├── PaymentResource.php │ │ ├── RecurringInvoiceCollection.php │ │ ├── RecurringInvoiceResource.php │ │ ├── RoleCollection.php │ │ ├── RoleResource.php │ │ ├── TaxCollection.php │ │ ├── TaxResource.php │ │ ├── TaxTypeCollection.php │ │ ├── TaxTypeResource.php │ │ ├── TransactionCollection.php │ │ ├── TransactionResource.php │ │ ├── UnitCollection.php │ │ ├── UnitResource.php │ │ ├── UserCollection.php │ │ └── UserResource.php ├── Jobs │ ├── CreateBackupJob.php │ ├── GenerateEstimatePdfJob.php │ ├── GenerateInvoicePdfJob.php │ └── GeneratePaymentPdfJob.php ├── Listeners │ └── Updates │ │ ├── Listener.php │ │ ├── v1 │ │ └── Version110.php │ │ ├── v2 │ │ ├── Version200.php │ │ ├── Version201.php │ │ ├── Version202.php │ │ └── Version210.php │ │ └── v3 │ │ ├── Version300.php │ │ ├── Version310.php │ │ └── Version311.php ├── Mail │ ├── EstimateViewedMail.php │ ├── InvoiceViewedMail.php │ ├── SendEstimateMail.php │ ├── SendInvoiceMail.php │ ├── SendPaymentMail.php │ └── TestMail.php ├── Models │ ├── Address.php │ ├── Company.php │ ├── CompanySetting.php │ ├── Country.php │ ├── Currency.php │ ├── CustomField.php │ ├── CustomFieldValue.php │ ├── Customer.php │ ├── EmailLog.php │ ├── Estimate.php │ ├── EstimateItem.php │ ├── ExchangeRateLog.php │ ├── ExchangeRateProvider.php │ ├── Expense.php │ ├── ExpenseCategory.php │ ├── FileDisk.php │ ├── Invoice.php │ ├── InvoiceItem.php │ ├── Item.php │ ├── Module.php │ ├── Note.php │ ├── Payment.php │ ├── PaymentMethod.php │ ├── RecurringInvoice.php │ ├── Setting.php │ ├── Tax.php │ ├── TaxType.php │ ├── Transaction.php │ ├── Unit.php │ ├── User.php │ └── UserSetting.php ├── Notifications │ ├── CustomerMailResetPasswordNotification.php │ └── MailResetPasswordNotification.php ├── Policies │ ├── CompanyPolicy.php │ ├── CustomFieldPolicy.php │ ├── CustomerPolicy.php │ ├── DashboardPolicy.php │ ├── EstimatePolicy.php │ ├── ExchangeRateProviderPolicy.php │ ├── ExpenseCategoryPolicy.php │ ├── ExpensePolicy.php │ ├── InvoicePolicy.php │ ├── ItemPolicy.php │ ├── ModulesPolicy.php │ ├── NotePolicy.php │ ├── OwnerPolicy.php │ ├── PaymentMethodPolicy.php │ ├── PaymentPolicy.php │ ├── RecurringInvoicePolicy.php │ ├── ReportPolicy.php │ ├── RolePolicy.php │ ├── SettingsPolicy.php │ ├── TaxTypePolicy.php │ ├── UnitPolicy.php │ └── UserPolicy.php ├── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── DropboxServiceProvider.php │ ├── EventServiceProvider.php │ ├── RouteServiceProvider.php │ └── ViewServiceProvider.php ├── Rules │ ├── Backup │ │ ├── BackupDisk.php │ │ ├── FilesystemDisks.php │ │ └── PathToZip.php │ ├── Base64Mime.php │ └── RelationNotExist.php ├── Services │ ├── Module │ │ ├── Module.php │ │ └── ModuleFacade.php │ └── SerialNumberFormatter.php ├── Space │ ├── DateFormatter.php │ ├── EnvironmentManager.php │ ├── FilePermissionChecker.php │ ├── ModuleInstaller.php │ ├── RequirementsChecker.php │ ├── SiteApi.php │ ├── TimeZones.php │ ├── Updater.php │ └── helpers.php └── Traits │ ├── ExchangeRateProvidersTrait.php │ ├── GeneratesMenuTrait.php │ ├── GeneratesPdfTrait.php │ └── HasCustomFieldsTrait.php ├── artisan ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── composer.json ├── composer.lock ├── config ├── abilities.php ├── app.php ├── auth.php ├── backup.php ├── broadcasting.php ├── cache.php ├── compile.php ├── cors.php ├── crater.php ├── database.php ├── dompdf.php ├── filesystems.php ├── hashids.php ├── hashing.php ├── image.php ├── installer.php ├── logging.php ├── mail.php ├── media-library.php ├── modules.php ├── queue.php ├── sanctum.php ├── services.php ├── session.php ├── trustedproxy.php ├── view.php └── vite.php ├── crater.code-workspace ├── crowdin.yml ├── database ├── .gitignore ├── factories │ ├── AddressFactory.php │ ├── CompanyFactory.php │ ├── CompanySettingFactory.php │ ├── CustomFieldFactory.php │ ├── CustomFieldValueFactory.php │ ├── CustomerFactory.php │ ├── EmailLogFactory.php │ ├── EstimateFactory.php │ ├── EstimateItemFactory.php │ ├── ExchangeRateLogFactory.php │ ├── ExchangeRateProviderFactory.php │ ├── ExpenseCategoryFactory.php │ ├── ExpenseFactory.php │ ├── FileDiskFactory.php │ ├── InvoiceFactory.php │ ├── InvoiceItemFactory.php │ ├── ItemFactory.php │ ├── NoteFactory.php │ ├── PaymentFactory.php │ ├── PaymentMethodFactory.php │ ├── RecurringInvoiceFactory.php │ ├── TaxFactory.php │ ├── TaxTypeFactory.php │ ├── UnitFactory.php │ └── UserFactory.php ├── migrations │ ├── 2014_10_11_071840_create_companies_table.php │ ├── 2014_10_11_125754_create_currencies_table.php │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2016_05_13_060834_create_settings_table.php │ ├── 2017_04_11_064308_create_units_table.php │ ├── 2017_04_11_081227_create_items_table.php │ ├── 2017_04_12_090759_create_invoices_table.php │ ├── 2017_04_12_091015_create_invoice_items_table.php │ ├── 2017_05_05_055609_create_estimates_table.php │ ├── 2017_05_05_073927_create_notifications_table.php │ ├── 2017_05_06_173745_create_countries_table.php │ ├── 2017_10_02_123501_create_estimate_items_table.php │ ├── 2018_11_02_133825_create_ expense_categories_table.php │ ├── 2018_11_02_133956_create_expenses_table.php │ ├── 2019_08_30_072639_create_addresses_table.php │ ├── 2019_09_02_053155_create_payment_methods_table.php │ ├── 2019_09_03_135234_create_payments_table.php │ ├── 2019_09_14_120124_create_media_table.php │ ├── 2019_09_21_052540_create_tax_types_table.php │ ├── 2019_09_21_052548_create_taxes_table.php │ ├── 2019_09_26_145012_create_company_settings_table.php │ ├── 2019_12_14_000001_create_personal_access_tokens_table.php │ ├── 2020_02_01_063235_create_custom_fields_table.php │ ├── 2020_02_01_063509_create_custom_field_values_table.php │ ├── 2020_05_12_154129_add_user_id_to_expenses_table.php │ ├── 2020_09_07_103054_create_file_disks_table.php │ ├── 2020_09_22_153617_add_columns_to_media_table.php │ ├── 2020_09_26_100951_create_user_settings_table.php │ ├── 2020_10_01_102913_add_company_to_addresses_table.php │ ├── 2020_10_17_074745_create_notes_table.php │ ├── 2020_10_24_091934_change_value_column_to_text_on_company_settings_table.php │ ├── 2020_11_23_050206_add_creator_in_invoices_table.php │ ├── 2020_11_23_050252_add_creator_in_estimates_table.php │ ├── 2020_11_23_050316_add_creator_in_payments_table.php │ ├── 2020_11_23_050333_add_creator_in_expenses_table.php │ ├── 2020_11_23_050406_add_creator_in_items_table.php │ ├── 2020_11_23_065815_add_creator_in_users_table.php │ ├── 2020_11_23_074154_create_email_logs_table.php │ ├── 2020_12_02_064933_update_crater_version_320.php │ ├── 2020_12_02_090527_update_crater_version_400.php │ ├── 2020_12_08_065715_change_description_and_notes_column_type.php │ ├── 2020_12_08_133131_update_crater_version_401.php │ ├── 2020_12_14_044717_add_template_name_to_invoices_table.php │ ├── 2020_12_14_045310_add_template_name_to_estimates_table.php │ ├── 2020_12_14_051450_remove_template_id_from_invoices_and_estimates_table.php │ ├── 2020_12_23_061302_update_crater_version_402.php │ ├── 2020_12_31_100816_update_crater_version_403.php │ ├── 2021_01_22_085644_update_crater_version_404.php │ ├── 2021_03_03_155223_add_unit_name_to_pdf.php │ ├── 2021_03_23_145012_add_number_length_setting.php │ ├── 2021_05_05_063533_update_crater_version_410.php │ ├── 2021_06_19_121939_update_crater_version_420.php │ ├── 2021_06_28_105334_create_bouncer_tables.php │ ├── 2021_06_28_111647_create_customers_table.php │ ├── 2021_06_28_120010_add_customer_id_to_estimates_table.php │ ├── 2021_06_28_120133_add_customer_id_to_expenses_table.php │ ├── 2021_06_28_120208_add_customer_id_to_invoices_table.php │ ├── 2021_06_28_120231_add_customer_id_to_payments_table.php │ ├── 2021_06_29_052745_add_customer_id_to_addresses_table.php │ ├── 2021_06_30_062411_update_customer_id_in_all_tables.php │ ├── 2021_07_01_060700_create_user_company_table.php │ ├── 2021_07_05_100256_change_relationship_of_company.php │ ├── 2021_07_06_070204_add_owner_id_to_companies_table.php │ ├── 2021_07_08_110940_add_company_to_notes_table.php │ ├── 2021_07_09_063502_create_recurring_invoices_table.php │ ├── 2021_07_09_063712_add_recurring_invoice_id_to_invoices_table.php │ ├── 2021_07_09_063755_add_recurring_invoice_id_to_invoice_items_table.php │ ├── 2021_07_15_054753_make_due_date_optional_in_invoices_table.php │ ├── 2021_07_15_054929_make_expiry_date_optional_estimates_table.php │ ├── 2021_07_16_072458_add_base_columns_into_invoices_table.php │ ├── 2021_07_16_072925_add_base_columns_into_invoice_items_table.php │ ├── 2021_07_16_073040_add_base_columns_into_estimates_table.php │ ├── 2021_07_16_073441_add_base_columns_into_estimate_items_table.php │ ├── 2021_07_16_074810_add_base_column_into_payments_table.php │ ├── 2021_07_16_075100_add_base_values_into_taxes_table.php │ ├── 2021_07_16_080253_add_currency_id_into_invoices_table.php │ ├── 2021_07_16_080508_add_currency_id_into_payments_table.php │ ├── 2021_07_16_080611_add_currency_id_into_items_table.php │ ├── 2021_07_16_080702_add_currency_id_into_taxes_table.php │ ├── 2021_07_16_112429_add_currency_id_into_estimates_table.php │ ├── 2021_08_05_103535_create_exchange_rate_logs_table.php │ ├── 2021_08_16_091413_add_tax_per_item_into_items_table.php │ ├── 2021_08_19_063244_add_base_columns_to_expense_table.php │ ├── 2021_09_28_081543_create_exchange_rate_providers_table.php │ ├── 2021_09_28_130822_add_sequence_column.php │ ├── 2021_10_06_100539_add_recurring_invoice_id_to_taxes_table.php │ ├── 2021_11_13_051127_add_payment_method_to_expense_table.php │ ├── 2021_11_13_114808_calculate_base_values_for_existing_data.php │ ├── 2021_11_23_092111_add_new_company_settings.php │ ├── 2021_11_23_093811_update_crater_version_500.php │ ├── 2021_12_01_120956_update_crater_version_501.php │ ├── 2021_12_02_063005_calculate_base_due_amount.php │ ├── 2021_12_02_074516_migrate_templates_from_version_4.php │ ├── 2021_12_02_123007_update_crater_version_502.php │ ├── 2021_12_03_154423_update_crater_version_503.php │ ├── 2021_12_04_122255_create_transactions_table.php │ ├── 2021_12_04_123315_add_transaction_id_to_payments_table.php │ ├── 2021_12_04_123415_add_type_to_payment_methods_table.php │ ├── 2021_12_06_131201_update_crater_version_504.php │ ├── 2021_12_09_054033_calculate_base_values_for_expenses.php │ ├── 2021_12_09_062434_update_crater_version_505.php │ ├── 2021_12_09_065718_drop_unique_email_on_customers_table.php │ ├── 2021_12_10_121739_update_creater_version_506.php │ ├── 2021_12_13_055813_calculate_base_amount_of_payments_table.php │ ├── 2021_12_13_093701_add_fields_to_email_logs_table.php │ ├── 2021_12_15_053223_create_modules_table.php │ ├── 2021_12_21_102521_change_enable_portal_field_of_customers_table.php │ ├── 2021_12_31_042453_add_type_to_tax_types_table.php │ ├── 2022_01_05_101841_add_sales_tax_fields_to_invoices_table.php │ ├── 2022_01_05_102538_add_sales_tax_fields_to_estimates_table.php │ ├── 2022_01_05_103607_add_sales_tax_fields_to_recurring_invoices_table.php │ ├── 2022_01_05_115423_update_crater_version_600.php │ ├── 2022_01_06_103536_add_slug_to_companies.php │ ├── 2022_01_12_132859_update_crater_version_601.php │ ├── 2022_01_13_123829_update_crater_version_602.php │ ├── 2022_02_15_113648_update_crater_version_603.php │ ├── 2022_02_17_081723_update_crater_version_604.php │ ├── 2022_02_23_130108_update_value_column_to_nullable_on_settings_table.php │ ├── 2022_03_02_120210_add_overdue_to_invoices_table.php │ ├── 2022_03_03_060121_crater_version_605.php │ ├── 2022_03_03_063237_change_over_due_status_to_sent.php │ ├── 2022_03_04_051438_calculate_base_values_for_invoice_items.php │ └── 2022_03_06_070829_update_crater_version_606.php └── seeders │ ├── CountriesTableSeeder.php │ ├── CurrenciesTableSeeder.php │ ├── DatabaseSeeder.php │ ├── DemoSeeder.php │ └── UsersTableSeeder.php ├── docker-compose.yml ├── docker-compose ├── cron.dockerfile ├── crontab ├── nginx │ └── nginx.conf ├── php │ └── uploads.ini └── setup.sh ├── package-lock.json ├── package.json ├── phpunit.xml ├── postcss.config.js ├── public ├── .htaccess ├── build │ ├── assets │ │ ├── 404.e81599b7.js │ │ ├── AccountSetting.7f3b69b7.js │ │ ├── AddressInformation.7455dbc9.js │ │ ├── AstronautIcon.82b952e2.js │ │ ├── BackupSetting.135768cd.js │ │ ├── BaseEditor.bacb9608.css │ │ ├── BaseEditor.c76beb41.js │ │ ├── BaseListItem.3b6ffe7a.js │ │ ├── BaseMultiselect.2950bd7a.js │ │ ├── BaseTable.ec8995dc.js │ │ ├── CapsuleIcon.37dfa933.js │ │ ├── CategoryModal.6fabb0b3.js │ │ ├── CompanyInfoSettings.23b88ef4.js │ │ ├── Create.1d6bd807.js │ │ ├── Create.68c99c93.js │ │ ├── Create.c666337c.js │ │ ├── Create.ddeb574a.js │ │ ├── Create.f0feda6b.js │ │ ├── CreateCustomFields.c1c460e4.js │ │ ├── CustomFieldsSetting.feceee26.js │ │ ├── CustomerIndexDropdown.bf4b48d6.js │ │ ├── CustomerSettings.295ae76d.js │ │ ├── CustomizationSetting.31d8c655.js │ │ ├── Dashboard.db3b8908.js │ │ ├── Dashboard.f55bd37e.js │ │ ├── DateTimeType.6886ff98.js │ │ ├── DateType.12fc8765.js │ │ ├── DragIcon.2da3872a.js │ │ ├── DropdownType.2d01b840.js │ │ ├── EstimateCreate.82c0b5df.js │ │ ├── EstimateIcon.7f89fb19.js │ │ ├── EstimateIndexDropdown.8917d9cc.js │ │ ├── ExchangeRateConverter.d865db6a.js │ │ ├── ExchangeRateProviderSetting.3f82b267.js │ │ ├── ExpenseCategorySetting.424a740a.js │ │ ├── FileDiskSetting.9303276f.js │ │ ├── ForgotPassword.5c338168.js │ │ ├── ForgotPassword.cb7a698c.js │ │ ├── Index.0d95203a.js │ │ ├── Index.113c6776.js │ │ ├── Index.17f3f1bc.js │ │ ├── Index.5bf16119.js │ │ ├── Index.622e547e.js │ │ ├── Index.6424247c.js │ │ ├── Index.7f1d6a8c.js │ │ ├── Index.91b66939.js │ │ ├── Index.9afe39cc.js │ │ ├── Index.d826dbf4.js │ │ ├── Index.edd0a47c.js │ │ ├── Index.f458eba6.js │ │ ├── Index.ff30d2b8.js │ │ ├── InputType.cf0dfc7c.js │ │ ├── Installation.f2c5c029.js │ │ ├── InvoiceCreate.2736eea6.js │ │ ├── InvoiceIndexDropdown.c4bcaa08.js │ │ ├── InvoicePublicPage.57c1fc66.js │ │ ├── ItemUnitModal.031bb625.js │ │ ├── LayoutBasic.7c57f411.js │ │ ├── LayoutBasic.c6db5172.js │ │ ├── LayoutInstallation.356e17fb.js │ │ ├── LayoutLogin.4f8baaf6.js │ │ ├── LayoutLogin.b71420b8.js │ │ ├── LineChart.8ef63104.js │ │ ├── LoadingIcon.b704202b.js │ │ ├── Login.30b20f3a.js │ │ ├── Login.4db30a10.js │ │ ├── MailConfigSetting.cd95a416.js │ │ ├── MoonwalkerIcon.b55d3604.js │ │ ├── NoteModal.3245b7d3.css │ │ ├── NoteModal.ebe10cf0.js │ │ ├── NotesSetting.b0c00c6b.js │ │ ├── NotificationRoot.5fd2c2c8.js │ │ ├── NotificationsSetting.20e5fa7f.js │ │ ├── NumberType.7b73360f.js │ │ ├── ObservatoryIcon.528a64ab.js │ │ ├── PaymentModeModal.a0b58785.js │ │ ├── PaymentsModeSetting.c898ec15.js │ │ ├── PhoneType.29ae66c8.js │ │ ├── PreferencesSetting.1dc581b2.js │ │ ├── RecurringInvoiceCreate.30ae0989.js │ │ ├── RecurringInvoiceIndexDropdown.5e1ae0da.js │ │ ├── ResetPassword.92fe39b8.js │ │ ├── ResetPassword.b82bdbf4.js │ │ ├── RolesSettings.72f183c6.js │ │ ├── SalesTax.75d66dd0.js │ │ ├── SelectNotePopup.2e678c03.js │ │ ├── SendEstimateModal.01516700.js │ │ ├── SendInvoiceModal.f818e383.js │ │ ├── SendPaymentModal.26ce23d7.js │ │ ├── SettingsIndex.47aad06d.js │ │ ├── SettingsIndex.f5b34c1b.js │ │ ├── SwitchType.591a8b07.js │ │ ├── TaxTypeModal.d37d74ed.js │ │ ├── TaxTypesSetting.320c1628.js │ │ ├── TextAreaType.27565abe.js │ │ ├── TimeType.8ac8afd1.js │ │ ├── UpdateAppSetting.428e199e.js │ │ ├── UpdateAppSetting.7d8b987a.css │ │ ├── UrlType.d123ab64.js │ │ ├── View.0b4de6cf.js │ │ ├── View.1c478abb.js │ │ ├── View.2505fbc0.js │ │ ├── View.44f27c50.js │ │ ├── View.7e060296.js │ │ ├── View.ae81e386.js │ │ ├── View.b91609b3.js │ │ ├── View.ca01e745.js │ │ ├── View.f92113cb.js │ │ ├── auth.c88ceb4c.js │ │ ├── category.c88b90cd.js │ │ ├── disk.0ffde448.js │ │ ├── estimate.f77ffc39.js │ │ ├── exchange-rate.85b564e2.js │ │ ├── expense.ea1e799e.js │ │ ├── global.dc565c4e.js │ │ ├── index.esm.85b4999a.js │ │ ├── invoice.735a98ac.js │ │ ├── mail-driver.0a974f6a.js │ │ ├── main.40833226.css │ │ ├── main.465728e1.js │ │ ├── payment.93619753.js │ │ ├── payment.e5b74251.js │ │ ├── users.27a53e97.js │ │ └── vendor.d12b5734.js │ ├── fonts │ │ ├── Poppins-Black.ttf │ │ ├── Poppins-Light.ttf │ │ ├── Poppins-Medium.ttf │ │ ├── Poppins-Regular.ttf │ │ └── Poppins-SemiBold.ttf │ ├── img │ │ ├── PDF │ │ │ ├── estimate1.png │ │ │ ├── estimate2.png │ │ │ ├── estimate3.png │ │ │ ├── invoice1.png │ │ │ ├── invoice2.png │ │ │ └── invoice3.png │ │ ├── c-mobile.png │ │ ├── crater-logo-gray.png │ │ ├── crater-logo.png │ │ ├── crater-white-small.png │ │ ├── default-avatar.jpg │ │ ├── login │ │ │ ├── frame.svg │ │ │ ├── login-vector1.svg │ │ │ ├── login-vector2.svg │ │ │ └── login-vector3.svg │ │ ├── logo-white.png │ │ └── tick.png │ └── manifest.json ├── favicons │ ├── android-chrome-192x192.png │ ├── android-chrome-256x256.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── mstile-150x150.png │ ├── safari-pinned-tab.svg │ └── site.webmanifest ├── index.php ├── robots.txt └── web.config ├── readme.md ├── resources ├── lang │ ├── en │ │ ├── auth.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ └── validation.php │ └── vendor │ │ └── backup │ │ ├── ar │ │ └── notifications.php │ │ ├── cs │ │ └── notifications.php │ │ ├── da │ │ └── notifications.php │ │ ├── de │ │ └── notifications.php │ │ ├── en │ │ └── notifications.php │ │ ├── es │ │ └── notifications.php │ │ ├── fa │ │ └── notifications.php │ │ ├── fi │ │ └── notifications.php │ │ ├── fr │ │ └── notifications.php │ │ ├── hi │ │ └── notifications.php │ │ ├── id │ │ └── notifications.php │ │ ├── it │ │ └── notifications.php │ │ ├── nl │ │ └── notifications.php │ │ ├── pl │ │ └── notifications.php │ │ ├── pt-BR │ │ └── notifications.php │ │ ├── ro │ │ └── notifications.php │ │ ├── ru │ │ └── notifications.php │ │ ├── tr │ │ └── notifications.php │ │ ├── uk │ │ └── notifications.php │ │ ├── vi │ │ └── notifications.php │ │ ├── zh-CN │ │ └── notifications.php │ │ └── zh-TW │ │ └── notifications.php ├── sass │ ├── components │ │ ├── animation.scss │ │ ├── pace-loader.scss │ │ └── v-tooltips.scss │ ├── crater.scss │ └── themes.scss ├── scripts │ ├── App.vue │ ├── Crater.js │ ├── admin │ │ ├── admin-router.js │ │ ├── components │ │ │ ├── CopyInputField.vue │ │ │ ├── SelectNotePopup.vue │ │ │ ├── charts │ │ │ │ └── LineChart.vue │ │ │ ├── currency-exchange-rate │ │ │ │ └── ExchangeRateBulkUpdate.vue │ │ │ ├── custom-fields │ │ │ │ ├── CreateCustomFields.vue │ │ │ │ ├── CreateCustomFieldsSingle.vue │ │ │ │ └── types │ │ │ │ │ ├── DateTimeType.vue │ │ │ │ │ ├── DateType.vue │ │ │ │ │ ├── DropdownType.vue │ │ │ │ │ ├── InputType.vue │ │ │ │ │ ├── NumberType.vue │ │ │ │ │ ├── PhoneType.vue │ │ │ │ │ ├── SwitchType.vue │ │ │ │ │ ├── TextAreaType.vue │ │ │ │ │ ├── TimeType.vue │ │ │ │ │ └── UrlType.vue │ │ │ ├── dropdowns │ │ │ │ ├── CustomFieldIndexDropdown.vue │ │ │ │ ├── CustomerIndexDropdown.vue │ │ │ │ ├── EstimateIndexDropdown.vue │ │ │ │ ├── ExpenseCategoryIndexDropdown.vue │ │ │ │ ├── ExpenseIndexDropdown.vue │ │ │ │ ├── InvoiceIndexDropdown.vue │ │ │ │ ├── ItemIndexDropdown.vue │ │ │ │ ├── NoteIndexDropdown.vue │ │ │ │ ├── PaymentIndexDropdown.vue │ │ │ │ ├── PaymentModeIndexDropdown.vue │ │ │ │ ├── RecurringInvoiceIndexDropdown.vue │ │ │ │ ├── RoleIndexDropdown.vue │ │ │ │ ├── TaxTypeIndexDropdown.vue │ │ │ │ └── UserIndexDropdown.vue │ │ │ ├── estimate-invoice-common │ │ │ │ ├── CreateItemRow.vue │ │ │ │ ├── CreateItemRowTax.vue │ │ │ │ ├── CreateItems.vue │ │ │ │ ├── CreateNotesField.vue │ │ │ │ ├── CreateTotal.vue │ │ │ │ ├── CreateTotalTaxes.vue │ │ │ │ ├── ExchangeRateConverter.vue │ │ │ │ ├── SalesTax.vue │ │ │ │ ├── SelectTaxPopup.vue │ │ │ │ └── SelectTemplateButton.vue │ │ │ └── modal-components │ │ │ │ ├── BackupModal.vue │ │ │ │ ├── CategoryModal.vue │ │ │ │ ├── CompanyModal.vue │ │ │ │ ├── CustomerModal.vue │ │ │ │ ├── DeleteCompanyModal.vue │ │ │ │ ├── ExchangeRateBulkUpdateModal.vue │ │ │ │ ├── ExchangeRateProviderModal.vue │ │ │ │ ├── FileDiskModal.vue │ │ │ │ ├── ItemModal.vue │ │ │ │ ├── ItemUnitModal.vue │ │ │ │ ├── MailTestModal.vue │ │ │ │ ├── NoteModal.vue │ │ │ │ ├── PaymentModeModal.vue │ │ │ │ ├── RolesModal.vue │ │ │ │ ├── SelectTemplateModal.vue │ │ │ │ ├── SendEstimateModal.vue │ │ │ │ ├── SendInvoiceModal.vue │ │ │ │ ├── SendPaymentModal.vue │ │ │ │ ├── TaxTypeModal.vue │ │ │ │ ├── TaxationAddressModal.vue │ │ │ │ ├── custom-fields │ │ │ │ ├── CustomFieldModal.vue │ │ │ │ └── OptionsCreate.vue │ │ │ │ └── disks │ │ │ │ ├── DoSpacesDisk.vue │ │ │ │ ├── DropboxDisk.vue │ │ │ │ ├── LocalDisk.vue │ │ │ │ └── S3Disk.vue │ │ ├── layouts │ │ │ ├── LayoutBasic.vue │ │ │ ├── LayoutInstallation.vue │ │ │ ├── LayoutLogin.vue │ │ │ └── partials │ │ │ │ ├── TheSiteHeader.vue │ │ │ │ └── TheSiteSidebar.vue │ │ ├── stores │ │ │ ├── auth.js │ │ │ ├── backup.js │ │ │ ├── category.js │ │ │ ├── company.js │ │ │ ├── custom-field.js │ │ │ ├── customer.js │ │ │ ├── dashboard.js │ │ │ ├── disk.js │ │ │ ├── estimate.js │ │ │ ├── exchange-rate.js │ │ │ ├── expense.js │ │ │ ├── global.js │ │ │ ├── installation.js │ │ │ ├── invoice.js │ │ │ ├── item.js │ │ │ ├── mail-driver.js │ │ │ ├── module.js │ │ │ ├── note.js │ │ │ ├── payment.js │ │ │ ├── recurring-invoice.js │ │ │ ├── reset.js │ │ │ ├── role.js │ │ │ ├── tax-type.js │ │ │ ├── user.js │ │ │ └── users.js │ │ ├── stub │ │ │ ├── abilities.js │ │ │ ├── address.js │ │ │ ├── custom-field.js │ │ │ ├── customer.js │ │ │ ├── estimate-item.js │ │ │ ├── estimate.js │ │ │ ├── expense.js │ │ │ ├── invoice-item.js │ │ │ ├── invoice.js │ │ │ ├── payment.js │ │ │ ├── recurring-invoice-item.js │ │ │ ├── recurring-invoice.js │ │ │ └── tax.js │ │ └── views │ │ │ ├── SampleTable.vue │ │ │ ├── auth │ │ │ ├── ForgotPassword.vue │ │ │ ├── Login.vue │ │ │ └── ResetPassword.vue │ │ │ ├── customers │ │ │ ├── Create.vue │ │ │ ├── Index.vue │ │ │ ├── View.vue │ │ │ └── partials │ │ │ │ ├── CustomerChart.vue │ │ │ │ ├── CustomerChartPlaceholder.vue │ │ │ │ ├── CustomerInfo.vue │ │ │ │ └── CustomerViewSidebar.vue │ │ │ ├── dashboard │ │ │ ├── Dashboard.vue │ │ │ ├── DashboardChart.vue │ │ │ ├── DashboardChartPlaceholder.vue │ │ │ ├── DashboardStats.vue │ │ │ ├── DashboardStatsItem.vue │ │ │ ├── DashboardStatsPlaceholder.vue │ │ │ ├── DashboardStatsSmPlaceholder.vue │ │ │ └── DashboardTable.vue │ │ │ ├── errors │ │ │ └── 404.vue │ │ │ ├── estimates │ │ │ ├── Index.vue │ │ │ ├── View.vue │ │ │ └── create │ │ │ │ ├── EstimateCreate.vue │ │ │ │ └── EstimateCreateBasicFields.vue │ │ │ ├── expenses │ │ │ ├── Create.vue │ │ │ └── Index.vue │ │ │ ├── installation │ │ │ ├── Installation.vue │ │ │ ├── Step1RequirementsCheck.vue │ │ │ ├── Step2PermissionCheck.vue │ │ │ ├── Step3DatabaseConfig.vue │ │ │ ├── Step4VerifyDomain.vue │ │ │ ├── Step5EmailConfig.vue │ │ │ ├── Step6AccountSettings.vue │ │ │ ├── Step7CompanyInfo.vue │ │ │ ├── Step8CompanyPreferences.vue │ │ │ ├── database │ │ │ │ ├── MysqlDatabase.vue │ │ │ │ ├── PgsqlDatabase.vue │ │ │ │ └── SqliteDatabase.vue │ │ │ └── mail-driver │ │ │ │ ├── BasicMailDriver.vue │ │ │ │ ├── MailgunMailDriver.vue │ │ │ │ ├── SesMailDriver.vue │ │ │ │ └── SmtpMailDriver.vue │ │ │ ├── invoices │ │ │ ├── Index.vue │ │ │ ├── View.vue │ │ │ └── create │ │ │ │ ├── InvoiceCreate.vue │ │ │ │ └── InvoiceCreateBasicFields.vue │ │ │ ├── items │ │ │ ├── Create.vue │ │ │ └── Index.vue │ │ │ ├── modules │ │ │ ├── Index.vue │ │ │ ├── View.vue │ │ │ └── partials │ │ │ │ ├── ModuleCard.vue │ │ │ │ ├── ModuleCardPlaceholder.vue │ │ │ │ ├── ModulePlaceholder.vue │ │ │ │ └── RecentModuleCard.vue │ │ │ ├── payments │ │ │ ├── Create.vue │ │ │ ├── Index.vue │ │ │ └── View.vue │ │ │ ├── recurring-invoices │ │ │ ├── Index.vue │ │ │ ├── View.vue │ │ │ ├── create │ │ │ │ ├── RecurringInvoiceCreate.vue │ │ │ │ └── RecurringInvoiceCreateBasicFields.vue │ │ │ └── partials │ │ │ │ ├── Invoices.vue │ │ │ │ ├── RecurringInvoiceInfo.vue │ │ │ │ └── RecurringInvoiceViewSidebar.vue │ │ │ ├── reports │ │ │ ├── ExpensesReport.vue │ │ │ ├── ProfitLossReport.vue │ │ │ ├── SalesReports.vue │ │ │ ├── TaxReport.vue │ │ │ └── layout │ │ │ │ └── Index.vue │ │ │ ├── settings │ │ │ ├── AccountSetting.vue │ │ │ ├── BackupSetting.vue │ │ │ ├── CompanyInfoSettings.vue │ │ │ ├── CustomFieldsSetting.vue │ │ │ ├── ExchangeRateProviderSetting.vue │ │ │ ├── ExpenseCategorySetting.vue │ │ │ ├── FileDiskSetting.vue │ │ │ ├── MailConfigSetting.vue │ │ │ ├── NotesSetting.vue │ │ │ ├── NotificationsSetting.vue │ │ │ ├── PaymentsModeSetting.vue │ │ │ ├── PreferencesSetting.vue │ │ │ ├── RolesSettings.vue │ │ │ ├── SettingsIndex.vue │ │ │ ├── TaxTypesSetting.vue │ │ │ ├── UpdateAppSetting.vue │ │ │ ├── customization │ │ │ │ ├── CustomizationSetting.vue │ │ │ │ ├── NumberCustomizer.vue │ │ │ │ ├── estimates │ │ │ │ │ ├── EstimatesTab.vue │ │ │ │ │ ├── EstimatesTabConvertEstimate.vue │ │ │ │ │ ├── EstimatesTabDefaultFormats.vue │ │ │ │ │ ├── EstimatesTabEstimateNumber.vue │ │ │ │ │ └── EstimatesTabExpiryDate.vue │ │ │ │ ├── invoices │ │ │ │ │ ├── InvoicesTab.vue │ │ │ │ │ ├── InvoicesTabDefaultFormats.vue │ │ │ │ │ ├── InvoicesTabDueDate.vue │ │ │ │ │ ├── InvoicesTabInvoiceNumber.vue │ │ │ │ │ └── InvoicesTabRetrospective.vue │ │ │ │ ├── items │ │ │ │ │ └── ItemsTab.vue │ │ │ │ └── payments │ │ │ │ │ ├── PaymentsTab.vue │ │ │ │ │ ├── PaymentsTabDefaultFormats.vue │ │ │ │ │ └── PaymentsTabPaymentNumber.vue │ │ │ └── mail-driver │ │ │ │ ├── BasicMailDriver.vue │ │ │ │ ├── MailgunMailDriver.vue │ │ │ │ ├── SesMailDriver.vue │ │ │ │ └── SmtpMailDriver.vue │ │ │ └── users │ │ │ ├── Create.vue │ │ │ └── Index.vue │ ├── components │ │ ├── CompanySwitcher.vue │ │ ├── GlobalSearchBar.vue │ │ ├── InvoiceInformationCard.vue │ │ ├── InvoicePublicPage.vue │ │ ├── base-select │ │ │ ├── BaseMultiselect.d.ts │ │ │ ├── BaseMultiselect.vue │ │ │ ├── composables │ │ │ │ ├── useClasses.js │ │ │ │ ├── useData.js │ │ │ │ ├── useDropdown.js │ │ │ │ ├── useKeyboard.js │ │ │ │ ├── useMultiselect.js │ │ │ │ ├── useOptions.js │ │ │ │ ├── usePointer.js │ │ │ │ ├── usePointerAction.js │ │ │ │ ├── useSearch.js │ │ │ │ └── useValue.js │ │ │ ├── index.d.ts │ │ │ └── utils │ │ │ │ ├── arraysEqual.js │ │ │ │ ├── isNullish.js │ │ │ │ ├── isObject.js │ │ │ │ └── normalize.js │ │ ├── base │ │ │ ├── BaseBadge.vue │ │ │ ├── BaseBreadcrumb.vue │ │ │ ├── BaseBreadcrumbItem.vue │ │ │ ├── BaseButton.vue │ │ │ ├── BaseCard.vue │ │ │ ├── BaseCheckbox.vue │ │ │ ├── BaseContentPlaceholders.vue │ │ │ ├── BaseContentPlaceholdersBox.vue │ │ │ ├── BaseContentPlaceholdersHeading.vue │ │ │ ├── BaseContentPlaceholdersText.vue │ │ │ ├── BaseCustomInput.vue │ │ │ ├── BaseCustomTag.vue │ │ │ ├── BaseCustomerAddressDisplay.vue │ │ │ ├── BaseCustomerSelectInput.vue │ │ │ ├── BaseCustomerSelectPopup.vue │ │ │ ├── BaseDatePicker.vue │ │ │ ├── BaseDescriptionList.vue │ │ │ ├── BaseDescriptionListItem.vue │ │ │ ├── BaseDialog.vue │ │ │ ├── BaseDivider.vue │ │ │ ├── BaseDropdown.vue │ │ │ ├── BaseDropdownItem.vue │ │ │ ├── BaseEmptyPlaceholder.vue │ │ │ ├── BaseErrorAlert.vue │ │ │ ├── BaseEstimateStatusBadge.vue │ │ │ ├── BaseFileUploader.vue │ │ │ ├── BaseFilterWrapper.vue │ │ │ ├── BaseFormatMoney.vue │ │ │ ├── BaseGlobalLoader.vue │ │ │ ├── BaseHeading.vue │ │ │ ├── BaseIcon.vue │ │ │ ├── BaseInfoAlert.vue │ │ │ ├── BaseInput.vue │ │ │ ├── BaseInputGrid.vue │ │ │ ├── BaseInputGroup.vue │ │ │ ├── BaseInvoiceStatusBadge.vue │ │ │ ├── BaseItemSelect.vue │ │ │ ├── BaseLabel.vue │ │ │ ├── BaseModal.vue │ │ │ ├── BaseMoney.vue │ │ │ ├── BaseNewBadge.vue │ │ │ ├── BasePage.vue │ │ │ ├── BasePageHeader.vue │ │ │ ├── BasePaidStatusBadge.vue │ │ │ ├── BaseRadio.vue │ │ │ ├── BaseRating.vue │ │ │ ├── BaseRecurringInvoiceStatusBadge.vue │ │ │ ├── BaseScrollPane.vue │ │ │ ├── BaseSelectAction.vue │ │ │ ├── BaseSelectInput.vue │ │ │ ├── BaseSettingCard.vue │ │ │ ├── BaseSpinner.vue │ │ │ ├── BaseSwitch.vue │ │ │ ├── BaseSwitchSection.vue │ │ │ ├── BaseTab.vue │ │ │ ├── BaseTabGroup.vue │ │ │ ├── BaseText.vue │ │ │ ├── BaseTextarea.vue │ │ │ ├── BaseTimePicker.vue │ │ │ ├── BaseWizard.vue │ │ │ ├── BaseWizardNavigation.vue │ │ │ ├── BaseWizardStep.vue │ │ │ ├── base-editor │ │ │ │ ├── BaseEditor.vue │ │ │ │ └── icons │ │ │ │ │ ├── BoldIcon.vue │ │ │ │ │ ├── CodeBlockIcon.vue │ │ │ │ │ ├── CodingIcon.vue │ │ │ │ │ ├── ItalicIcon.vue │ │ │ │ │ ├── ListIcon.vue │ │ │ │ │ ├── ListUlIcon.vue │ │ │ │ │ ├── MenuCenterIcon.vue │ │ │ │ │ ├── ParagraphIcon.vue │ │ │ │ │ ├── QuoteIcon.vue │ │ │ │ │ ├── RedoIcon.vue │ │ │ │ │ ├── StrikethroughIcon.vue │ │ │ │ │ ├── UnderlineIcon.vue │ │ │ │ │ ├── UndoIcon.vue │ │ │ │ │ └── index.js │ │ │ └── base-table │ │ │ │ ├── BaseTable.vue │ │ │ │ ├── BaseTablePagination.vue │ │ │ │ ├── Column.js │ │ │ │ ├── Row.js │ │ │ │ └── helpers.js │ │ ├── icons │ │ │ ├── DragIcon.vue │ │ │ ├── LoadingIcon.vue │ │ │ ├── MainLogo.vue │ │ │ ├── SaveIcon.vue │ │ │ ├── SpinnerIcon.vue │ │ │ ├── dashboard │ │ │ │ ├── CustomerIcon.vue │ │ │ │ ├── DollarIcon.vue │ │ │ │ ├── EstimateIcon.vue │ │ │ │ ├── InvoiceIcon.vue │ │ │ │ └── PaymentIcon.vue │ │ │ └── empty │ │ │ │ ├── AstronautIcon.vue │ │ │ │ ├── CapsuleIcon.vue │ │ │ │ ├── MoonwalkerIcon.vue │ │ │ │ ├── ObservatoryIcon.vue │ │ │ │ ├── SatelliteIcon.vue │ │ │ │ └── UFOIcon.vue │ │ ├── list │ │ │ ├── BaseList.vue │ │ │ └── BaseListItem.vue │ │ ├── notifications │ │ │ ├── NotificationItem.vue │ │ │ └── NotificationRoot.vue │ │ └── svg │ │ │ ├── LoginBackground.vue │ │ │ ├── LoginBackgroundOverlay.vue │ │ │ ├── LoginBottomVector.vue │ │ │ └── LoginPlanetCrater.vue │ ├── customer │ │ ├── customer-router.js │ │ ├── helpers │ │ │ └── error-handling.js │ │ ├── layouts │ │ │ ├── LayoutBasic.vue │ │ │ ├── LayoutLogin.vue │ │ │ └── partials │ │ │ │ ├── TheSiteFooter.vue │ │ │ │ ├── TheSiteHeader.vue │ │ │ │ └── TheSiteSidebar.vue │ │ ├── stores │ │ │ ├── auth.js │ │ │ ├── customer.js │ │ │ ├── dashboard.js │ │ │ ├── estimate.js │ │ │ ├── global.js │ │ │ ├── invoice.js │ │ │ ├── payment.js │ │ │ └── user.js │ │ ├── stubs │ │ │ └── address.js │ │ └── views │ │ │ ├── BaseCheckon.vue │ │ │ ├── SamplePage.vue │ │ │ ├── auth │ │ │ ├── ForgotPassword.vue │ │ │ ├── Login.vue │ │ │ └── ResetPassword.vue │ │ │ ├── dashboard │ │ │ ├── Dashboard.vue │ │ │ ├── DashboardStats.vue │ │ │ ├── DashboardStatsItem.vue │ │ │ ├── DashboardStatsPlaceholder.vue │ │ │ ├── DashboardStatsSmPlaceholder.vue │ │ │ └── DashboardTable.vue │ │ │ ├── estimates │ │ │ ├── Index.vue │ │ │ └── View.vue │ │ │ ├── invoices │ │ │ ├── Index.vue │ │ │ └── View.vue │ │ │ ├── payments │ │ │ ├── Index.vue │ │ │ └── View.vue │ │ │ └── settings │ │ │ ├── AddressInformation.vue │ │ │ ├── CustomerSettings.vue │ │ │ └── SettingsIndex.vue │ ├── global-components.js │ ├── helpers │ │ ├── error-handling.js │ │ ├── use-popper.js │ │ └── utilities.js │ ├── locales │ │ ├── ar.json │ │ ├── cs.json │ │ ├── de.json │ │ ├── el.json │ │ ├── en.json │ │ ├── es.json │ │ ├── fa.json │ │ ├── fi.json │ │ ├── fr.json │ │ ├── hi.json │ │ ├── hr.json │ │ ├── id.json │ │ ├── it.json │ │ ├── ja.json │ │ ├── ko.json │ │ ├── locales.js │ │ ├── lt.json │ │ ├── lv.json │ │ ├── nl.json │ │ ├── pl.json │ │ ├── pt-br.json │ │ ├── pt.json │ │ ├── ro.json │ │ ├── ru.json │ │ ├── sk.json │ │ ├── sl.json │ │ ├── sr.json │ │ ├── sv.json │ │ ├── th.json │ │ ├── tr.json │ │ ├── vi.json │ │ └── zh.json │ ├── main.js │ ├── plugins │ │ ├── axios.js │ │ └── i18n.js │ ├── router │ │ └── index.js │ ├── services │ │ └── ls.js │ ├── shims-vue.d.ts │ └── stores │ │ ├── dialog.js │ │ ├── modal.js │ │ └── notification.js ├── static │ ├── fonts │ │ ├── Poppins-Black.ttf │ │ ├── Poppins-Light.ttf │ │ ├── Poppins-Medium.ttf │ │ ├── Poppins-Regular.ttf │ │ ├── Poppins-SemiBold.ttf │ │ ├── THSarabunNew-Bold.ttf │ │ ├── THSarabunNew-BoldItalic.ttf │ │ ├── THSarabunNew-Italic.ttf │ │ └── THSarabunNew.ttf │ └── img │ │ ├── PDF │ │ ├── estimate1.png │ │ ├── estimate2.png │ │ ├── estimate3.png │ │ ├── invoice1.png │ │ ├── invoice2.png │ │ └── invoice3.png │ │ ├── c-mobile.png │ │ ├── crater-logo-gray.png │ │ ├── crater-logo.png │ │ ├── crater-white-small.png │ │ ├── default-avatar.jpg │ │ ├── login │ │ ├── frame.svg │ │ ├── login-vector1.svg │ │ ├── login-vector2.svg │ │ └── login-vector3.svg │ │ ├── logo-white.png │ │ └── tick.png └── views │ ├── app.blade.php │ ├── app │ └── pdf │ │ ├── estimate │ │ ├── estimate1.blade.php │ │ ├── estimate2.blade.php │ │ ├── estimate3.blade.php │ │ └── partials │ │ │ └── table.blade.php │ │ ├── invoice │ │ ├── invoice1.blade.php │ │ ├── invoice2.blade.php │ │ ├── invoice3.blade.php │ │ └── partials │ │ │ └── table.blade.php │ │ ├── locale │ │ └── th.blade.php │ │ ├── payment │ │ └── payment.blade.php │ │ └── reports │ │ ├── expenses.blade.php │ │ ├── profit-loss.blade.php │ │ ├── sales-customers.blade.php │ │ ├── sales-items.blade.php │ │ └── tax-summary.blade.php │ ├── emails │ ├── send │ │ ├── estimate.blade.php │ │ ├── invoice.blade.php │ │ └── payment.blade.php │ ├── test.blade.php │ └── viewed │ │ ├── estimate.blade.php │ │ └── invoice.blade.php │ └── vendor │ ├── .gitkeep │ ├── laravel-menu │ └── bootstrap-navbar-items.blade.php │ ├── mail │ ├── html │ │ ├── button.blade.php │ │ ├── footer.blade.php │ │ ├── header.blade.php │ │ ├── layout.blade.php │ │ ├── message.blade.php │ │ ├── panel.blade.php │ │ ├── promotion.blade.php │ │ ├── promotion │ │ │ └── button.blade.php │ │ ├── subcopy.blade.php │ │ ├── table.blade.php │ │ └── themes │ │ │ └── default.css │ └── text │ │ ├── button.blade.php │ │ ├── footer.blade.php │ │ ├── header.blade.php │ │ ├── layout.blade.php │ │ ├── message.blade.php │ │ ├── panel.blade.php │ │ ├── promotion.blade.php │ │ ├── promotion │ │ └── button.blade.php │ │ ├── subcopy.blade.php │ │ └── table.blade.php │ └── media-library │ ├── image.blade.php │ ├── placeholderSvg.blade.php │ ├── responsiveImage.blade.php │ └── responsiveImageWithPlaceholder.blade.php ├── routes ├── api.php ├── channels.php ├── console.php └── web.php ├── server.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── fonts │ └── .gitkeep ├── framework │ ├── .gitignore │ ├── cache │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tailwind.config.js ├── tests ├── CreatesApplication.php ├── Feature │ ├── Admin │ │ ├── BackupTest.php │ │ ├── CompanySettingTest.php │ │ ├── CompanyTest.php │ │ ├── ConfigTest.php │ │ ├── CurrenciesTest.php │ │ ├── CustomFieldTest.php │ │ ├── CustomerTest.php │ │ ├── DashboardTest.php │ │ ├── EstimateTest.php │ │ ├── ExpenseCategoryTest.php │ │ ├── ExpenseTest.php │ │ ├── FileDiskTest.php │ │ ├── InvoiceTest.php │ │ ├── ItemTest.php │ │ ├── LocationTest.php │ │ ├── NextNumberTest.php │ │ ├── NotesTest.php │ │ ├── PaymentMethodTest.php │ │ ├── PaymentTest.php │ │ ├── RecurringInvoiceTest.php │ │ ├── RoleTest.php │ │ ├── TaxTypeTest.php │ │ ├── UnitTest.php │ │ └── UserTest.php │ └── Customer │ │ ├── DashboardTest.php │ │ ├── EstimateTest.php │ │ ├── ExpenseTest.php │ │ ├── InvoiceTest.php │ │ ├── PaymentTest.php │ │ └── ProfileTest.php ├── Helpers.php ├── Pest.php ├── TestCase.php └── Unit │ ├── AddressTest.php │ ├── CompanySettingTest.php │ ├── CompanyTest.php │ ├── CountryTest.php │ ├── CustomFieldTest.php │ ├── CustomFieldValueTest.php │ ├── CustomerTest.php │ ├── EstimateItemTest.php │ ├── EstimateTest.php │ ├── ExchangeRateLogTest.php │ ├── ExpenseCategoryTest.php │ ├── ExpenseTest.php │ ├── InvoiceItemTest.php │ ├── InvoiceTest.php │ ├── ItemTest.php │ ├── PaymentMethodTest.php │ ├── PaymentTest.php │ ├── RecurringInvoiceTest.php │ ├── SettingTest.php │ ├── TaxTest.php │ ├── TaxTypeTest.php │ ├── UnitTest.php │ └── UserTest.php ├── tsconfig.json ├── uffizzi ├── .env.example ├── Dockerfile ├── crond │ └── Dockerfile ├── docker-compose.uffizzi.yml └── nginx │ ├── Dockerfile │ └── nginx │ └── nginx.conf ├── vite.config.ts └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | .gitignore 3 | *.md 4 | .git/ 5 | .idea/ 6 | .DS_Store/ 7 | docker-compose.* 8 | LICENSE 9 | nginx.conf 10 | yarn.lock 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.yml] 15 | indent_style = space 16 | indent_size = 2 17 | 18 | [*.vue] 19 | indent_size = 2 20 | 21 | [*.js] 22 | indent_size = 2 23 | 24 | [*.json] 25 | indent_size = 2 26 | -------------------------------------------------------------------------------- /.env.testing: -------------------------------------------------------------------------------- 1 | APP_ENV=testing 2 | APP_DEBUG=true 3 | APP_KEY=base64:IdDlpLmYyWA9z4Ruj5st1FSYrhCR7lPOscLGCz2Jf4I= 4 | DB_CONNECTION=sqlite 5 | 6 | MAIL_DRIVER=smtp 7 | MAIL_HOST=smtp.mailtrap.io 8 | MAIL_PORT=587 9 | MAIL_USERNAME=ff538f0e1037f4 10 | MAIL_PASSWORD=c04c81145fcb73 11 | MAIL_ENCRYPTION=tls 12 | MAIL_FROM_ADDRESS="admin@craterapp.com" 13 | MAIL_FROM_NAME="John Doe" 14 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // .eslintrc.js 2 | 3 | module.exports = { 4 | extends: [ 5 | // add more generic rulesets here, such as: 6 | // 'eslint:recommended', 7 | "plugin:vue/vue3-recommended", 8 | "prettier", 9 | ], 10 | rules: { 11 | // override/add rules settings here, such as: 12 | // 'vue/no-unused-vars': 'error' 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Screenshots** 17 | If applicable, add screenshots to help explain your problem. 18 | 19 | **Please complete the following information:** 20 | - Crater version: 21 | - PHP version: 22 | - Database type and version: 23 | 24 | **Optional info** 25 | - OS: [e.g. Ubuntu] 26 | - Browser: [e.g. chrome, safari] 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Modules 2 | /node_modules 3 | /public/storage 4 | /public/hot 5 | /storage/*.key 6 | /vendor 7 | /.idea 8 | Homestead.json 9 | Homestead.yaml 10 | .env 11 | .phpunit.result.cache 12 | .rnd 13 | /.expo 14 | /.vscode 15 | /docker-compose/db/data/ 16 | .gitkeep 17 | /public/docs 18 | /.scribe 19 | !storage/fonts/.gitkeep 20 | .DS_Store 21 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "tabWidth": 2 5 | } 6 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please email security@craterapp.com to report any security vulnerabilities. We will acknowledge receipt of your vulnerability and strive to send you regular updates about our progress. If you're curious about the status of your disclosure please feel free to email us again. 6 | -------------------------------------------------------------------------------- /app/Events/ModuleDisabledEvent.php: -------------------------------------------------------------------------------- 1 | module = $module; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Events/ModuleEnabledEvent.php: -------------------------------------------------------------------------------- 1 | module = $module; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Events/ModuleInstalledEvent.php: -------------------------------------------------------------------------------- 1 | module = $module; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Events/UpdateFinished.php: -------------------------------------------------------------------------------- 1 | old = $old; 23 | $this->new = $new; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/AppVersionController.php: -------------------------------------------------------------------------------- 1 | json([ 21 | 'version' => $version, 22 | ]); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | json([ 19 | 'success' => true, 20 | ]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Company/CompanyController.php: -------------------------------------------------------------------------------- 1 | header('company')); 21 | 22 | return new CompanyResource($company); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Config/FiscalYearsController.php: -------------------------------------------------------------------------------- 1 | json([ 19 | 'fiscal_years' => config('crater.fiscal_years'), 20 | ]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Config/LanguagesController.php: -------------------------------------------------------------------------------- 1 | json([ 19 | 'languages' => config('crater.languages'), 20 | ]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Config/RetrospectiveEditsController.php: -------------------------------------------------------------------------------- 1 | json([ 19 | 'retrospective_edits' => config('crater.retrospective_edits'), 20 | ]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Estimate/SendEstimateController.php: -------------------------------------------------------------------------------- 1 | authorize('send estimate', $estimate); 20 | 21 | $response = $estimate->send($request->all()); 22 | 23 | return response()->json($response); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/General/ConfigController.php: -------------------------------------------------------------------------------- 1 | json([ 19 | $request->key => config('crater.'.$request->key), 20 | ]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/General/CountriesController.php: -------------------------------------------------------------------------------- 1 | get(); 21 | 22 | return CurrencyResource::collection($currencies); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/General/DateFormatsController.php: -------------------------------------------------------------------------------- 1 | json([ 20 | 'date_formats' => DateFormatter::get_list(), 21 | ]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/General/SearchUsersController.php: -------------------------------------------------------------------------------- 1 | authorize('create', User::class); 20 | 21 | $users = User::whereEmail($request->email) 22 | ->latest() 23 | ->paginate(10); 24 | 25 | return response()->json(['users' => $users]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/General/TimezonesController.php: -------------------------------------------------------------------------------- 1 | json([ 20 | 'time_zones' => TimeZones::get_list(), 21 | ]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Invoice/InvoiceTemplatesController.php: -------------------------------------------------------------------------------- 1 | authorize('viewAny', Invoice::class); 20 | 21 | $invoiceTemplates = Invoice::invoiceTemplates(); 22 | 23 | return response()->json([ 24 | 'invoiceTemplates' => $invoiceTemplates, 25 | ]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Modules/ApiTokenController.php: -------------------------------------------------------------------------------- 1 | authorize('manage modules'); 20 | 21 | $response = ModuleInstaller::checkToken($request->api_token); 22 | 23 | return $response; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Modules/CopyModuleController.php: -------------------------------------------------------------------------------- 1 | authorize('manage modules'); 20 | 21 | $response = ModuleInstaller::copyFiles($request->module, $request->path); 22 | 23 | return response()->json([ 24 | 'success' => $response 25 | ]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Modules/DownloadModuleController.php: -------------------------------------------------------------------------------- 1 | authorize('manage modules'); 20 | 21 | $response = ModuleInstaller::download($request->module, $request->version); 22 | 23 | return response()->json($response); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Modules/ModulesController.php: -------------------------------------------------------------------------------- 1 | authorize('manage modules'); 20 | 21 | $response = ModuleInstaller::getModules(); 22 | 23 | return $response; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Modules/UploadModuleController.php: -------------------------------------------------------------------------------- 1 | authorize('manage modules'); 20 | 21 | $response = ModuleInstaller::upload($request); 22 | 23 | return response()->json($response); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Payment/SendPaymentController.php: -------------------------------------------------------------------------------- 1 | authorize('send payment', $payment); 20 | 21 | $response = $payment->send($request->all()); 22 | 23 | return response()->json($response); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/RecurringInvoice/RecurringInvoiceFrequencyController.php: -------------------------------------------------------------------------------- 1 | frequency, $request->starts_at); 14 | 15 | return response()->json([ 16 | 'success' => true, 17 | 'next_invoice_at' => $nextInvoiceAt, 18 | ]); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Role/AbilitiesController.php: -------------------------------------------------------------------------------- 1 | json(['abilities' => config('abilities.abilities')]); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Settings/GetCompanyMailConfigurationController.php: -------------------------------------------------------------------------------- 1 | config('mail.from.name'), 20 | 'from_mail' => config('mail.from.address'), 21 | ]; 22 | 23 | return response()->json($mailConfig); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Settings/GetCompanySettingsController.php: -------------------------------------------------------------------------------- 1 | settings, $request->header('company')); 20 | 21 | return response()->json($settings); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Settings/GetUserSettingsController.php: -------------------------------------------------------------------------------- 1 | user(); 19 | 20 | return response()->json($user->getSettings($request->settings)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Admin/Settings/UpdateUserSettingsController.php: -------------------------------------------------------------------------------- 1 | user(); 19 | 20 | $user->setSettings($request->settings); 21 | 22 | return response()->json([ 23 | 'success' => true, 24 | ]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Customer/Payment/PaymentMethodController.php: -------------------------------------------------------------------------------- 1 | id)->get()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Installation/FinishController.php: -------------------------------------------------------------------------------- 1 | put('database_created', 'database_created'); 19 | 20 | return response()->json(['success' => true]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/PDF/DownloadInvoicePdfController.php: -------------------------------------------------------------------------------- 1 | id.'.pdf'); 19 | 20 | return response()->download($path); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/PDF/DownloadPaymentPdfController.php: -------------------------------------------------------------------------------- 1 | id.'.pdf'); 19 | 20 | return response()->download($path); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/PDF/EstimatePdfController.php: -------------------------------------------------------------------------------- 1 | has('preview')) { 20 | return $estimate->getPDFData(); 21 | } 22 | 23 | 24 | return $estimate->getGeneratedPDFOrStream('estimate'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/PDF/InvoicePdfController.php: -------------------------------------------------------------------------------- 1 | has('preview')) { 20 | return $invoice->getPDFData(); 21 | } 22 | 23 | return $invoice->getGeneratedPDFOrStream('invoice'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/PDF/PaymentPdfController.php: -------------------------------------------------------------------------------- 1 | has('preview')) { 20 | return view('app.pdf.payment.payment'); 21 | } 22 | 23 | return $payment->getGeneratedPDFOrStream('payment'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/V1/Webhook/CronJobController.php: -------------------------------------------------------------------------------- 1 | json(['success' => true]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 18 | return route('login'); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Middleware/CronJobMiddleware.php: -------------------------------------------------------------------------------- 1 | header('x-authorization-token') && $request->header('x-authorization-token') == config('services.cron_job.auth_token')) { 20 | return $next($request); 21 | } 22 | 23 | return response()->json(['unauthorized'], 401); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | check()) { 22 | return redirect(RouteServiceProvider::HOME); 23 | } 24 | 25 | return $next($request); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfInstalled.php: -------------------------------------------------------------------------------- 1 | has('database_created')) { 20 | if (Setting::getSetting('profile_complete') === 'COMPLETED') { 21 | return redirect('login'); 22 | } 23 | } 24 | 25 | return $next($request); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfUnauthorized.php: -------------------------------------------------------------------------------- 1 | check()) { 21 | return $next($request); 22 | } 23 | 24 | return redirect('/login'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | [ 28 | 'required', 29 | 'in:ACCEPTED,REJECTED', 30 | ] 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Http/Requests/DomainEnvironmentRequest.php: -------------------------------------------------------------------------------- 1 | [ 28 | 'required', 29 | ], 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Requests/GetSettingRequest.php: -------------------------------------------------------------------------------- 1 | [ 28 | 'required', 29 | 'string' 30 | ] 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Http/Requests/Request.php: -------------------------------------------------------------------------------- 1 | [ 28 | 'required', 29 | ], 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Requests/SettingRequest.php: -------------------------------------------------------------------------------- 1 | [ 28 | 'required', 29 | ], 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Requests/UpdateSettingsRequest.php: -------------------------------------------------------------------------------- 1 | [ 28 | 'required', 29 | ], 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Resources/AbilityCollection.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'name' => $this->name, 20 | 'entity_id' => $this->entity_id, 21 | 'entity_type' => $this->entity_type, 22 | 'only_owned' => $this->only_owned, 23 | 'options' => $this->options, 24 | 'scope' => $this->scope, 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Resources/AddressCollection.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'code' => $this->code, 20 | 'name' => $this->name, 21 | 'phone_code' => $this->phone_code, 22 | ]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Resources/CurrencyCollection.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'code' => $this->code, 20 | 'name' => $this->name, 21 | 'phonecode' => $this->phonecode, 22 | ]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Resources/Customer/CurrencyCollection.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'name' => $this->name, 20 | 'company_id' => $this->company_id, 21 | 'company' => $this->when($this->company()->exists(), function () { 22 | return new CompanyResource($this->company); 23 | }), 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Resources/Customer/RecurringInvoiceCollection.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'company_id' => $this->company_id, 20 | 'base_currency_id' => $this->base_currency_id, 21 | 'currency_id' => $this->currency_id, 22 | 'exchange_rate' => $this->exchange_rate, 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Resources/ExchangeRateProviderCollection.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'name' => $this->name, 20 | 'type' => $this->type, 21 | 'driver' => $this->driver, 22 | 'set_as_default' => $this->set_as_default, 23 | 'credentials' => $this->credentials, 24 | 'company_id' => $this->company_id, 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Resources/InvoiceCollection.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'type' => $this->type, 20 | 'name' => $this->name, 21 | 'notes' => $this->notes, 22 | 'company' => $this->when($this->company()->exists(), function () { 23 | return new CompanyResource($this->company); 24 | }), 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Resources/PaymentCollection.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'name' => $this->name, 20 | 'company_id' => $this->company_id, 21 | 'company' => $this->when($this->company()->exists(), function () { 22 | return new CompanyResource($this->company); 23 | }), 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Resources/UserCollection.php: -------------------------------------------------------------------------------- 1 | old, '<=')) { 20 | return true; 21 | } 22 | 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Listeners/Updates/v3/Version311.php: -------------------------------------------------------------------------------- 1 | isListenerFired($event)) { 23 | return; 24 | } 25 | 26 | Artisan::call('migrate', ['--force' => true]); 27 | 28 | // Update Crater app version 29 | Setting::setSetting('version', static::VERSION); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Models/Country.php: -------------------------------------------------------------------------------- 1 | hasMany(Address::class); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Models/Currency.php: -------------------------------------------------------------------------------- 1 | belongsTo(User::class); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Policies/DashboardPolicy.php: -------------------------------------------------------------------------------- 1 | hasCompany($company->id)) { 17 | return true; 18 | } 19 | 20 | return false; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Policies/ModulesPolicy.php: -------------------------------------------------------------------------------- 1 | isOwner()) { 15 | return true; 16 | } 17 | 18 | return false; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Policies/NotePolicy.php: -------------------------------------------------------------------------------- 1 | isOwner()) { 15 | return true; 16 | } 17 | 18 | return false; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Policies/ReportPolicy.php: -------------------------------------------------------------------------------- 1 | hasCompany($company->id)) { 17 | return true; 18 | } 19 | 20 | return false; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'api.auth']); 19 | require base_path('routes/channels.php'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Services/Module/ModuleFacade.php: -------------------------------------------------------------------------------- 1 | items->toArray() as $data) { 12 | if ($user->checkAccess($data)) { 13 | $menu[] = [ 14 | 'title' => $data->title, 15 | 'link' => $data->link->path['url'], 16 | 'icon' => $data->data['icon'], 17 | 'name' => $data->data['name'], 18 | 'group' => $data->data['group'], 19 | ]; 20 | } 21 | } 22 | 23 | return $menu; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /config/image.php: -------------------------------------------------------------------------------- 1 | 'gd', 19 | 20 | ]; 21 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /resources/scripts/locales/en.json 3 | translation: /resources/scripts/locales/%two_letters_code%.json 4 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | -------------------------------------------------------------------------------- /database/factories/PaymentMethodFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->name, 27 | 'company_id' => User::find(1)->companies()->first()->id, 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/factories/UnitFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->name, 27 | 'company_id' => User::find(1)->companies()->first()->id, 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2020_12_02_064933_update_crater_version_320.php: -------------------------------------------------------------------------------- 1 | date('expiry_date')->nullable()->change(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | // 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2021_11_23_093811_update_crater_version_500.php: -------------------------------------------------------------------------------- 1 | dropUnique(['email']); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | // 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2021_12_10_121739_update_creater_version_506.php: -------------------------------------------------------------------------------- 1 | string('value')->nullable()->change(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | // 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2022_03_03_060121_crater_version_605.php: -------------------------------------------------------------------------------- 1 | call(CurrenciesTableSeeder::class); 17 | $this->call(CountriesTableSeeder::class); 18 | $this->call(UsersTableSeeder::class); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /database/seeders/DemoSeeder.php: -------------------------------------------------------------------------------- 1 | first(); 20 | 21 | $user->setSettings(['language' => 'en']); 22 | 23 | Address::create(['company_id' => $user->companies()->first()->id, 'country_id' => 1]); 24 | 25 | Setting::setSetting('profile_complete', 'COMPLETED'); 26 | 27 | \Storage::disk('local')->put('database_created', 'database_created'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docker-compose/cron.dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.0-fpm-alpine 2 | 3 | RUN apk add --no-cache \ 4 | php8-bcmath 5 | 6 | RUN docker-php-ext-install pdo pdo_mysql bcmath 7 | 8 | COPY docker-compose/crontab /etc/crontabs/root 9 | 10 | CMD ["crond", "-f"] 11 | -------------------------------------------------------------------------------- /docker-compose/crontab: -------------------------------------------------------------------------------- 1 | * * * * * cd /var/www && php artisan schedule:run >> /dev/stdout 2>&1 2 | -------------------------------------------------------------------------------- /docker-compose/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | client_max_body_size 64M; 3 | listen 80; 4 | index index.php index.html; 5 | error_log /var/log/nginx/error.log; 6 | access_log /var/log/nginx/access.log; 7 | root /var/www/public; 8 | location ~ \.php$ { 9 | try_files $uri =404; 10 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 11 | fastcgi_pass app:9000; 12 | fastcgi_index index.php; 13 | include fastcgi_params; 14 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 15 | fastcgi_param PATH_INFO $fastcgi_path_info; 16 | fastcgi_read_timeout 300; 17 | } 18 | location / { 19 | try_files $uri $uri/ /index.php?$query_string; 20 | gzip_static on; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /docker-compose/php/uploads.ini: -------------------------------------------------------------------------------- 1 | file_uploads = On 2 | upload_max_filesize = 64M 3 | post_max_size = 64M 4 | max_execution_time = 300 5 | -------------------------------------------------------------------------------- /docker-compose/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | docker-compose exec app composer install --no-interaction --prefer-dist --optimize-autoloader 4 | 5 | docker-compose exec app php artisan storage:link || true 6 | docker-compose exec app php artisan key:generate 7 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | // postcss.config.js 2 | module.exports = { 3 | plugins: { 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /public/build/assets/DateTimeType.6886ff98.js: -------------------------------------------------------------------------------- 1 | import{I as r,k as d,r as m,o as p,l as c,u as i,x as f}from"./vendor.d12b5734.js";const k={props:{modelValue:{type:String,default:r().format("YYYY-MM-DD hh:MM")}},emits:["update:modelValue"],setup(t,{emit:l}){const s=t,e=d({get:()=>s.modelValue,set:o=>{l("update:modelValue",o)}});return(o,a)=>{const u=m("BaseDatePicker");return p(),c(u,{modelValue:i(e),"onUpdate:modelValue":a[0]||(a[0]=n=>f(e)?e.value=n:null),"enable-time":""},null,8,["modelValue"])}}};export{k as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/DateType.12fc8765.js: -------------------------------------------------------------------------------- 1 | import{I as r,k as d,r as m,o as p,l as c,u as f,x as i}from"./vendor.d12b5734.js";const k={props:{modelValue:{type:[String,Date],default:r().format("YYYY-MM-DD")}},emits:["update:modelValue"],setup(t,{emit:l}){const s=t,e=d({get:()=>s.modelValue,set:o=>{l("update:modelValue",o)}});return(o,a)=>{const u=m("BaseDatePicker");return p(),c(u,{modelValue:f(e),"onUpdate:modelValue":a[0]||(a[0]=n=>i(e)?e.value=n:null)},null,8,["modelValue"])}}};export{k as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/DropdownType.2d01b840.js: -------------------------------------------------------------------------------- 1 | import{k as p,r,o as d,l as m,u as c,x as i}from"./vendor.d12b5734.js";const f={props:{modelValue:{type:[String,Object,Number],default:null},options:{type:Array,default:()=>[]},valueProp:{type:String,default:"name"},label:{type:String,default:"name"},object:{type:Boolean,default:!1}},emits:["update:modelValue"],setup(e,{emit:a}){const u=e,l=p({get:()=>u.modelValue,set:t=>{a("update:modelValue",t)}});return(t,o)=>{const n=r("BaseMultiselect");return d(),m(n,{modelValue:c(l),"onUpdate:modelValue":o[0]||(o[0]=s=>i(l)?l.value=s:null),options:e.options,label:e.label,"value-prop":e.valueProp,object:e.object},null,8,["modelValue","options","label","value-prop","object"])}}};export{f as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/InputType.cf0dfc7c.js: -------------------------------------------------------------------------------- 1 | import{k as p,r as d,o as r,l as m,u as c,x as V}from"./vendor.d12b5734.js";const i={props:{modelValue:{type:String,default:null}},emits:["update:modelValue"],setup(o,{emit:u}){const a=o,e=p({get:()=>a.modelValue,set:t=>{u("update:modelValue",t)}});return(t,l)=>{const n=d("BaseInput");return r(),m(n,{modelValue:c(e),"onUpdate:modelValue":l[0]||(l[0]=s=>V(e)?e.value=s:null),type:"text"},null,8,["modelValue"])}}};export{i as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/LayoutInstallation.356e17fb.js: -------------------------------------------------------------------------------- 1 | import{N as t}from"./NotificationRoot.5fd2c2c8.js";import{r as s,o as r,e as a,f as o,h as c}from"./vendor.d12b5734.js";import"./main.465728e1.js";const n={class:"h-screen overflow-y-auto text-base"},i={class:"container mx-auto px-4"},u={setup(_){return(m,p)=>{const e=s("router-view");return r(),a("div",n,[o(t),c("div",i,[o(e)])])}}};export{u as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/LoadingIcon.b704202b.js: -------------------------------------------------------------------------------- 1 | import{_ as e}from"./main.465728e1.js";import{o as s,e as t,h as o}from"./vendor.d12b5734.js";const c={},r={xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24"},n=o("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"},null,-1),a=o("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"},null,-1),l=[n,a];function i(_,d){return s(),t("svg",r,l)}var p=e(c,[["render",i]]);export{p as L}; 2 | -------------------------------------------------------------------------------- /public/build/assets/NoteModal.3245b7d3.css: -------------------------------------------------------------------------------- 1 | .note-modal .header-editior .editor-menu-bar{margin-left:.5px;margin-right:0} 2 | -------------------------------------------------------------------------------- /public/build/assets/NumberType.7b73360f.js: -------------------------------------------------------------------------------- 1 | import{k as p,r,o as m,l as d,u as c,x as V}from"./vendor.d12b5734.js";const i={props:{modelValue:{type:[String,Number],default:null}},emits:["update:modelValue"],setup(t,{emit:u}){const a=t,e=p({get:()=>a.modelValue,set:l=>{u("update:modelValue",l)}});return(l,o)=>{const n=r("BaseInput");return m(),d(n,{modelValue:c(e),"onUpdate:modelValue":o[0]||(o[0]=s=>V(e)?e.value=s:null),type:"number"},null,8,["modelValue"])}}};export{i as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/PhoneType.29ae66c8.js: -------------------------------------------------------------------------------- 1 | import{k as p,r,o as d,l as m,u as c,x as V}from"./vendor.d12b5734.js";const i={props:{modelValue:{type:[String,Number],default:null}},emits:["update:modelValue"],setup(o,{emit:u}){const a=o,e=p({get:()=>a.modelValue,set:l=>{u("update:modelValue",l)}});return(l,t)=>{const n=r("BaseInput");return d(),m(n,{modelValue:c(e),"onUpdate:modelValue":t[0]||(t[0]=s=>V(e)?e.value=s:null),type:"tel"},null,8,["modelValue"])}}};export{i as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/SwitchType.591a8b07.js: -------------------------------------------------------------------------------- 1 | import{k as p,r,o as d,l as m,u as c,x as i}from"./vendor.d12b5734.js";const f={props:{modelValue:{type:[String,Number,Boolean],default:null}},emits:["update:modelValue"],setup(t,{emit:a}){const n=t,e=p({get:()=>n.modelValue===1,set:o=>{a("update:modelValue",o?1:0)}});return(o,l)=>{const u=r("BaseSwitch");return d(),m(u,{modelValue:c(e),"onUpdate:modelValue":l[0]||(l[0]=s=>i(e)?e.value=s:null)},null,8,["modelValue"])}}};export{f as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/TextAreaType.27565abe.js: -------------------------------------------------------------------------------- 1 | import{k as r,r as d,o as m,l as p,u as i,x as c}from"./vendor.d12b5734.js";const V={props:{modelValue:{type:String,default:null},rows:{type:String,default:"2"},inputName:{type:String,default:"description"}},emits:["update:modelValue"],setup(e,{emit:l}){const n=e,t=r({get:()=>n.modelValue,set:a=>{l("update:modelValue",a)}});return(a,o)=>{const u=d("BaseTextarea");return m(),p(u,{modelValue:i(t),"onUpdate:modelValue":o[0]||(o[0]=s=>c(t)?t.value=s:null),rows:e.rows,name:e.inputName},null,8,["modelValue","rows","name"])}}};export{V as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/TimeType.8ac8afd1.js: -------------------------------------------------------------------------------- 1 | import{I as r,k as m,r as d,o as p,l as c,u as i,x as f}from"./vendor.d12b5734.js";const k={props:{modelValue:{type:[String,Date,Object],default:r().format("YYYY-MM-DD")}},emits:["update:modelValue"],setup(a,{emit:l}){const s=a,e=m({get:()=>s.modelValue,set:o=>{l("update:modelValue",o)}});return(o,t)=>{const u=d("BaseTimePicker");return p(),c(u,{modelValue:i(e),"onUpdate:modelValue":t[0]||(t[0]=n=>f(e)?e.value=n:null)},null,8,["modelValue"])}}};export{k as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/UpdateAppSetting.7d8b987a.css: -------------------------------------------------------------------------------- 1 | .update-description ul{list-style:disc!important}.update-description li{margin-bottom:4px} 2 | -------------------------------------------------------------------------------- /public/build/assets/UrlType.d123ab64.js: -------------------------------------------------------------------------------- 1 | import{k as p,r,o as d,l as m,u as c,x as V}from"./vendor.d12b5734.js";const i={props:{modelValue:{type:String,default:null}},emits:["update:modelValue"],setup(t,{emit:u}){const a=t,e=p({get:()=>a.modelValue,set:l=>{u("update:modelValue",l)}});return(l,o)=>{const n=r("BaseInput");return d(),m(n,{modelValue:c(e),"onUpdate:modelValue":o[0]||(o[0]=s=>V(e)?e.value=s:null),type:"url"},null,8,["modelValue"])}}};export{i as default}; 2 | -------------------------------------------------------------------------------- /public/build/assets/index.esm.85b4999a.js: -------------------------------------------------------------------------------- 1 | import{T as r}from"./vendor.d12b5734.js";var s={name:"ValidateEach",props:{rules:{type:Object,required:!0},state:{type:Object,required:!0},options:{type:Object,default:()=>({})}},setup(e,{slots:t}){const a=r(e.rules,e.state,e.options);return()=>t.default({v:a.value})}};export{s as V}; 2 | -------------------------------------------------------------------------------- /public/build/fonts/Poppins-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/fonts/Poppins-Black.ttf -------------------------------------------------------------------------------- /public/build/fonts/Poppins-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/fonts/Poppins-Light.ttf -------------------------------------------------------------------------------- /public/build/fonts/Poppins-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/fonts/Poppins-Medium.ttf -------------------------------------------------------------------------------- /public/build/fonts/Poppins-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/fonts/Poppins-Regular.ttf -------------------------------------------------------------------------------- /public/build/fonts/Poppins-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/fonts/Poppins-SemiBold.ttf -------------------------------------------------------------------------------- /public/build/img/PDF/estimate1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/PDF/estimate1.png -------------------------------------------------------------------------------- /public/build/img/PDF/estimate2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/PDF/estimate2.png -------------------------------------------------------------------------------- /public/build/img/PDF/estimate3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/PDF/estimate3.png -------------------------------------------------------------------------------- /public/build/img/PDF/invoice1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/PDF/invoice1.png -------------------------------------------------------------------------------- /public/build/img/PDF/invoice2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/PDF/invoice2.png -------------------------------------------------------------------------------- /public/build/img/PDF/invoice3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/PDF/invoice3.png -------------------------------------------------------------------------------- /public/build/img/c-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/c-mobile.png -------------------------------------------------------------------------------- /public/build/img/crater-logo-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/crater-logo-gray.png -------------------------------------------------------------------------------- /public/build/img/crater-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/crater-logo.png -------------------------------------------------------------------------------- /public/build/img/crater-white-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/crater-white-small.png -------------------------------------------------------------------------------- /public/build/img/default-avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/default-avatar.jpg -------------------------------------------------------------------------------- /public/build/img/login/login-vector1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /public/build/img/login/login-vector2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/build/img/login/login-vector3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/build/img/logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/logo-white.png -------------------------------------------------------------------------------- /public/build/img/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/build/img/tick.png -------------------------------------------------------------------------------- /public/favicons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/favicons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/favicons/android-chrome-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/favicons/android-chrome-256x256.png -------------------------------------------------------------------------------- /public/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffffff 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/favicons/favicon.ico -------------------------------------------------------------------------------- /public/favicons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/public/favicons/mstile-150x150.png -------------------------------------------------------------------------------- /public/favicons/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/favicons/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/favicons/android-chrome-256x256.png", 12 | "sizes": "256x256", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/sass/components/animation.scss: -------------------------------------------------------------------------------- 1 | .shake { 2 | animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; 3 | transform: translate3d(0, 0, 0); 4 | backface-visibility: hidden; 5 | perspective: 1000px; 6 | } 7 | 8 | @keyframes shake { 9 | 10%, 10 | 90% { 11 | transform: translate3d(-1px, 0, 0); 12 | } 13 | 14 | 20%, 15 | 80% { 16 | transform: translate3d(2px, 0, 0); 17 | } 18 | 19 | 30%, 20 | 50%, 21 | 70% { 22 | transform: translate3d(-4px, 0, 0); 23 | } 24 | 25 | 40%, 26 | 60% { 27 | transform: translate3d(4px, 0, 0); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resources/sass/themes.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --color-primary-50: 247, 246, 253; 3 | --color-primary-100: 238, 238, 251; 4 | --color-primary-200: 213, 212, 245; 5 | --color-primary-300: 188, 185, 239; 6 | --color-primary-400: 138, 133, 228; 7 | --color-primary-500: 88, 81, 216; 8 | --color-primary-600: 79, 73, 194; 9 | --color-primary-700: 53, 49, 130; 10 | --color-primary-800: 40, 36, 97; 11 | --color-primary-900: 26, 24, 65; 12 | } 13 | -------------------------------------------------------------------------------- /resources/scripts/App.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/custom-fields/types/DateTimeType.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 25 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/custom-fields/types/DateType.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 25 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/custom-fields/types/InputType.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 24 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/custom-fields/types/NumberType.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 24 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/custom-fields/types/PhoneType.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 24 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/custom-fields/types/SwitchType.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 26 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/custom-fields/types/TextAreaType.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 32 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/custom-fields/types/TimeType.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 25 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/custom-fields/types/UrlType.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 24 | -------------------------------------------------------------------------------- /resources/scripts/admin/components/modal-components/ExchangeRateBulkUpdateModal.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 25 | -------------------------------------------------------------------------------- /resources/scripts/admin/layouts/LayoutInstallation.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 14 | -------------------------------------------------------------------------------- /resources/scripts/admin/stub/address.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: null, 3 | phone: null, 4 | address_street_1: null, 5 | address_street_2: null, 6 | city: null, 7 | state: null, 8 | country_id: null, 9 | zip: null, 10 | type: null, 11 | } 12 | -------------------------------------------------------------------------------- /resources/scripts/admin/stub/custom-field.js: -------------------------------------------------------------------------------- 1 | export default { 2 | id: null, 3 | label: null, 4 | type: null, 5 | name: null, 6 | default_answer: null, 7 | is_required: false, 8 | placeholder: null, 9 | model_type: null, 10 | order: 1, 11 | options: [], 12 | } 13 | -------------------------------------------------------------------------------- /resources/scripts/admin/stub/customer.js: -------------------------------------------------------------------------------- 1 | import addressStub from '@/scripts/admin/stub/address.js' 2 | 3 | export default function () { 4 | return { 5 | name: '', 6 | contact_name: '', 7 | email: '', 8 | phone: null, 9 | password: '', 10 | confirm_password:'', 11 | currency_id: null, 12 | website: null, 13 | billing: { ...addressStub }, 14 | shipping: { ...addressStub }, 15 | customFields: [], 16 | fields: [], 17 | enable_portal: false, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /resources/scripts/admin/stub/estimate-item.js: -------------------------------------------------------------------------------- 1 | export default { 2 | estimate_id: null, 3 | item_id: null, 4 | name: '', 5 | title: '', 6 | description: null, 7 | quantity: 1, 8 | price: 0, 9 | discount_type: 'fixed', 10 | discount_val: 0, 11 | discount: 0, 12 | total: 0, 13 | sub_total: 0, 14 | totalTax: 0, 15 | totalSimpleTax: 0, 16 | totalCompoundTax: 0, 17 | tax: 0, 18 | taxes: [], 19 | } 20 | -------------------------------------------------------------------------------- /resources/scripts/admin/stub/expense.js: -------------------------------------------------------------------------------- 1 | import moment from 'moment' 2 | 3 | export default { 4 | expense_category_id: null, 5 | expense_date: moment().format('YYYY-MM-DD'), 6 | amount: 100, 7 | notes: '', 8 | attachment_receipt: null, 9 | customer_id: '', 10 | currency_id: '', 11 | payment_method_id: '', 12 | receiptFiles: [], 13 | customFields: [], 14 | fields: [], 15 | in_use: false, 16 | selectedCurrency: null 17 | } 18 | -------------------------------------------------------------------------------- /resources/scripts/admin/stub/invoice-item.js: -------------------------------------------------------------------------------- 1 | export default { 2 | invoice_id: null, 3 | item_id: null, 4 | name: '', 5 | title: '', 6 | description: null, 7 | quantity: 1, 8 | price: 0, 9 | discount_type: 'fixed', 10 | discount_val: 0, 11 | discount: 0, 12 | total: 0, 13 | totalTax: 0, 14 | totalSimpleTax: 0, 15 | totalCompoundTax: 0, 16 | tax: 0, 17 | taxes: [], 18 | } 19 | -------------------------------------------------------------------------------- /resources/scripts/admin/stub/payment.js: -------------------------------------------------------------------------------- 1 | export default { 2 | maxPayableAmount: Number.MAX_SAFE_INTEGER, 3 | selectedCustomer: '', 4 | currency: null, 5 | currency_id: '', 6 | customer_id: '', 7 | payment_number: '', 8 | payment_date: '', 9 | amount: 0, 10 | invoice_id: '', 11 | notes: '', 12 | payment_method_id: '', 13 | customFields: [], 14 | fields: [] 15 | } 16 | -------------------------------------------------------------------------------- /resources/scripts/admin/stub/recurring-invoice-item.js: -------------------------------------------------------------------------------- 1 | export default { 2 | recurring_invoice_id: null, 3 | item_id: null, 4 | name: '', 5 | title: '', 6 | sales_tax_type: null, 7 | sales_tax_address_type: null, 8 | description: null, 9 | quantity: 1, 10 | price: 0, 11 | discount_type: 'fixed', 12 | discount_val: 0, 13 | discount: 0, 14 | total: 0, 15 | totalTax: 0, 16 | totalSimpleTax: 0, 17 | totalCompoundTax: 0, 18 | tax: 0, 19 | taxes: [], 20 | } 21 | -------------------------------------------------------------------------------- /resources/scripts/admin/stub/tax.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '', 3 | tax_type_id: 0, 4 | type: 'GENERAL', 5 | amount: null, 6 | percent: null, 7 | compound_tax: false, 8 | } 9 | -------------------------------------------------------------------------------- /resources/scripts/admin/views/dashboard/DashboardStatsPlaceholder.vue: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /resources/scripts/admin/views/settings/customization/estimates/EstimatesTabEstimateNumber.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | -------------------------------------------------------------------------------- /resources/scripts/admin/views/settings/customization/invoices/InvoicesTabInvoiceNumber.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | -------------------------------------------------------------------------------- /resources/scripts/admin/views/settings/customization/payments/PaymentsTabPaymentNumber.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | -------------------------------------------------------------------------------- /resources/scripts/components/base-select/composables/useDropdown.js: -------------------------------------------------------------------------------- 1 | import { ref, toRefs } from 'vue' 2 | 3 | export default function useDropdown(props, context, dep) { 4 | const { disabled } = toRefs(props) 5 | 6 | // ================ DATA ================ 7 | 8 | const isOpen = ref(false) 9 | 10 | // =============== METHODS ============== 11 | 12 | const open = () => { 13 | if (isOpen.value || disabled.value) { 14 | return 15 | } 16 | 17 | isOpen.value = true 18 | context.emit('open') 19 | } 20 | 21 | const close = () => { 22 | if (!isOpen.value) { 23 | return 24 | } 25 | 26 | isOpen.value = false 27 | context.emit('close') 28 | } 29 | 30 | return { 31 | isOpen, 32 | open, 33 | close, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/scripts/components/base-select/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './BaseMultiselect'; 2 | -------------------------------------------------------------------------------- /resources/scripts/components/base-select/utils/arraysEqual.js: -------------------------------------------------------------------------------- 1 | export default function arraysEqual (array1, array2) { 2 | const array2Sorted = array2.slice().sort() 3 | 4 | return array1.length === array2.length && array1.slice().sort().every(function(value, index) { 5 | return value === array2Sorted[index]; 6 | }) 7 | } -------------------------------------------------------------------------------- /resources/scripts/components/base-select/utils/isNullish.js: -------------------------------------------------------------------------------- 1 | export default function isNullish (val) { 2 | return [null, undefined, false].indexOf(val) !== -1 3 | } -------------------------------------------------------------------------------- /resources/scripts/components/base-select/utils/isObject.js: -------------------------------------------------------------------------------- 1 | export default function isObject (variable) { 2 | return Object.prototype.toString.call(variable) === '[object Object]' 3 | } -------------------------------------------------------------------------------- /resources/scripts/components/base-select/utils/normalize.js: -------------------------------------------------------------------------------- 1 | export default function normalize (str, strict = true) { 2 | return strict 3 | ? String(str).toLowerCase().trim() 4 | : String(str).normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase().trim() 5 | } -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseBadge.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 30 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseBreadcrumb.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseContentPlaceholdersBox.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 26 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseContentPlaceholdersHeading.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 26 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseContentPlaceholdersText.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 32 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseCustomTag.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseCustomerAddressDisplay.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 28 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseDescriptionList.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseDivider.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseDropdownItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseHeading.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 26 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseIcon.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 22 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseInputGrid.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 25 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseLabel.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseNewBadge.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 20 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BasePage.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BasePageHeader.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 24 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseScrollPane.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseSelectAction.vue: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseSpinner.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseTab.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 30 | -------------------------------------------------------------------------------- /resources/scripts/components/base/BaseText.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 32 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/BoldIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/CodeBlockIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/CodingIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/ItalicIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/ListUlIcon.vue: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/MenuCenterIcon.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/ParagraphIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/QuoteIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/RedoIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/UnderlineIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/scripts/components/base/base-editor/icons/UndoIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/scripts/components/icons/LoadingIcon.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /resources/scripts/components/icons/SpinnerIcon.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | -------------------------------------------------------------------------------- /resources/scripts/components/list/BaseList.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | -------------------------------------------------------------------------------- /resources/scripts/components/svg/LoginBottomVector.vue: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /resources/scripts/customer/layouts/partials/TheSiteFooter.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /resources/scripts/customer/layouts/partials/TheSiteSidebar.vue: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/scripts/customer/stores/customer.js: -------------------------------------------------------------------------------- 1 | const { defineStore } = window.pinia 2 | 3 | export const useCustomerStore = defineStore({ 4 | id: 'customers', 5 | state: () => ({ 6 | customers: 'okay', 7 | }), 8 | 9 | actions: { 10 | resetCustomers() { 11 | this.customers = 'okay' 12 | }, 13 | } 14 | }) 15 | -------------------------------------------------------------------------------- /resources/scripts/customer/stubs/address.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: null, 3 | phone: null, 4 | address_street_1: null, 5 | address_street_2: null, 6 | city: null, 7 | state: null, 8 | country_id: null, 9 | zip: null, 10 | type: null, 11 | } 12 | -------------------------------------------------------------------------------- /resources/scripts/customer/views/BaseCheckon.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 13 | -------------------------------------------------------------------------------- /resources/scripts/customer/views/SamplePage.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 16 | -------------------------------------------------------------------------------- /resources/scripts/customer/views/dashboard/Dashboard.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 12 | -------------------------------------------------------------------------------- /resources/scripts/customer/views/dashboard/DashboardStatsPlaceholder.vue: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /resources/scripts/main.js: -------------------------------------------------------------------------------- 1 | import '../sass/crater.scss' 2 | import 'v-tooltip/dist/v-tooltip.css' 3 | import '@/scripts/plugins/axios.js' 4 | import * as VueRouter from 'vue-router' 5 | import router from '@/scripts/router/index' 6 | import * as pinia from 'pinia' 7 | import * as Vue from 'vue' 8 | import * as Vuelidate from '@vuelidate/core' 9 | 10 | window.pinia = pinia 11 | window.Vuelidate = Vuelidate 12 | 13 | import Crater from './Crater' 14 | 15 | window.Vue = Vue 16 | window.router = router 17 | window.VueRouter = VueRouter 18 | 19 | window.Crater = new Crater() 20 | -------------------------------------------------------------------------------- /resources/scripts/plugins/axios.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import Ls from '@/scripts/services/ls.js' 3 | 4 | window.Ls = Ls 5 | window.axios = axios 6 | axios.defaults.withCredentials = true 7 | 8 | axios.defaults.headers.common = { 9 | 'X-Requested-With': 'XMLHttpRequest', 10 | } 11 | 12 | /** 13 | * Interceptors 14 | */ 15 | 16 | axios.interceptors.request.use(function (config) { 17 | // Pass selected company to header on all requests 18 | const companyId = Ls.get('selectedCompany') 19 | 20 | const authToken = Ls.get('auth.token') 21 | 22 | if (authToken) { 23 | config.headers.common.Authorization = authToken 24 | } 25 | 26 | if (companyId) { 27 | config.headers.common['company'] = companyId 28 | } 29 | 30 | return config 31 | }) 32 | -------------------------------------------------------------------------------- /resources/scripts/plugins/i18n.js: -------------------------------------------------------------------------------- 1 | import { createI18n } from 'vue-i18n' 2 | 3 | export default (messages) => { 4 | return createI18n({ 5 | locale: 'en', 6 | fallbackLocale: 'en', 7 | messages 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /resources/scripts/services/ls.js: -------------------------------------------------------------------------------- 1 | export default { 2 | get(key) { 3 | return localStorage.getItem(key) ? localStorage.getItem(key) : null 4 | }, 5 | 6 | set(key, val) { 7 | localStorage.setItem(key, val) 8 | }, 9 | 10 | remove(key) { 11 | localStorage.removeItem(key) 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /resources/scripts/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | // This is required for Visual Studio Code to recognize 2 | // imported .vue files 3 | declare module '*.vue' { 4 | import { DefineComponent } from 'vue' 5 | const component: DefineComponent<{}, {}, any> 6 | export default component 7 | } 8 | -------------------------------------------------------------------------------- /resources/static/fonts/Poppins-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/fonts/Poppins-Black.ttf -------------------------------------------------------------------------------- /resources/static/fonts/Poppins-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/fonts/Poppins-Light.ttf -------------------------------------------------------------------------------- /resources/static/fonts/Poppins-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/fonts/Poppins-Medium.ttf -------------------------------------------------------------------------------- /resources/static/fonts/Poppins-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/fonts/Poppins-Regular.ttf -------------------------------------------------------------------------------- /resources/static/fonts/Poppins-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/fonts/Poppins-SemiBold.ttf -------------------------------------------------------------------------------- /resources/static/fonts/THSarabunNew-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/fonts/THSarabunNew-Bold.ttf -------------------------------------------------------------------------------- /resources/static/fonts/THSarabunNew-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/fonts/THSarabunNew-BoldItalic.ttf -------------------------------------------------------------------------------- /resources/static/fonts/THSarabunNew-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/fonts/THSarabunNew-Italic.ttf -------------------------------------------------------------------------------- /resources/static/fonts/THSarabunNew.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/fonts/THSarabunNew.ttf -------------------------------------------------------------------------------- /resources/static/img/PDF/estimate1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/PDF/estimate1.png -------------------------------------------------------------------------------- /resources/static/img/PDF/estimate2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/PDF/estimate2.png -------------------------------------------------------------------------------- /resources/static/img/PDF/estimate3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/PDF/estimate3.png -------------------------------------------------------------------------------- /resources/static/img/PDF/invoice1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/PDF/invoice1.png -------------------------------------------------------------------------------- /resources/static/img/PDF/invoice2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/PDF/invoice2.png -------------------------------------------------------------------------------- /resources/static/img/PDF/invoice3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/PDF/invoice3.png -------------------------------------------------------------------------------- /resources/static/img/c-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/c-mobile.png -------------------------------------------------------------------------------- /resources/static/img/crater-logo-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/crater-logo-gray.png -------------------------------------------------------------------------------- /resources/static/img/crater-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/crater-logo.png -------------------------------------------------------------------------------- /resources/static/img/crater-white-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/crater-white-small.png -------------------------------------------------------------------------------- /resources/static/img/default-avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/default-avatar.jpg -------------------------------------------------------------------------------- /resources/static/img/login/login-vector1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /resources/static/img/login/login-vector2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /resources/static/img/login/login-vector3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/static/img/logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/logo-white.png -------------------------------------------------------------------------------- /resources/static/img/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/resources/static/img/tick.png -------------------------------------------------------------------------------- /resources/views/emails/test.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | # Test Email from Crater 3 | 4 | {{ $my_message }} 5 | 6 | @endcomponent 7 | -------------------------------------------------------------------------------- /resources/views/emails/viewed/estimate.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | {{ $data['user']['name'] }} viewed this Estimate. 3 | 4 | @component('mail::button', ['url' => url('/admin/estimates/'.$data['estimate']['id'].'/view')]) 5 | View Estimate 6 | @endcomponent 7 | 8 | Thanks,
9 | {{ config('app.name') }} 10 | @endcomponent 11 | -------------------------------------------------------------------------------- /resources/views/emails/viewed/invoice.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | {{ $data['user']['name'] }} viewed this Invoice. 3 | 4 | @component('mail::button', ['url' => url('/admin/invoices/'.$data['invoice']['id'].'/view')]) 5 | View Invoice 6 | @endcomponent 7 | 8 | Thanks,
9 | {{ config('app.name') }} 10 | @endcomponent 11 | -------------------------------------------------------------------------------- /resources/views/vendor/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/footer.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/header.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{-- --}} 4 | {{ $slot }} 5 | {{-- --}} 6 | 7 | 8 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/panel.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/promotion.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/promotion/button.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 |
4 | 5 | 6 | 9 | 10 |
7 | {{ $slot }} 8 |
11 |
14 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/subcopy.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/table.blade.php: -------------------------------------------------------------------------------- 1 |
2 | {{ Illuminate\Mail\Markdown::parse($slot) }} 3 |
4 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/button.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }}: {{ $url }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/footer.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/header.blade.php: -------------------------------------------------------------------------------- 1 | [{{ $slot }}]({{ $url }}) 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/layout.blade.php: -------------------------------------------------------------------------------- 1 | {!! strip_tags($header) !!} 2 | 3 | {!! strip_tags($slot) !!} 4 | @isset($subcopy) 5 | 6 | {!! strip_tags($subcopy) !!} 7 | @endisset 8 | 9 | {!! strip_tags($footer) !!} 10 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/panel.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/promotion.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/promotion/button.blade.php: -------------------------------------------------------------------------------- 1 | [{{ $slot }}]({{ $url }}) 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/subcopy.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/table.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/media-library/image.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/views/vendor/media-library/placeholderSvg.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources/views/vendor/media-library/responsiveImage.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/views/vendor/media-library/responsiveImageWithPlaceholder.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | conversation_id === (int) $cid 7 | }); 8 | 9 | Broadcast::channel('user.{uid}', function () { 10 | return true; //(int) $user->conversation_id === (int) $cid 11 | }); 12 | 13 | Broadcast::channel('company.{companyId}', function ($user, $companyId) { 14 | return ['id' => $user->id, 'name' => $user->name]; 15 | }); 16 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->describe('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/fonts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crater-invoice-inc/crater/05d5ce26fdd8d9466009163444e944259bc0cc2a/storage/fonts/.gitkeep -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | schedule-* 4 | compiled.php 5 | services.json 6 | events.scanned.php 7 | routes.scanned.php 8 | down 9 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Feature/Admin/CurrenciesTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 10 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 11 | 12 | $user = User::find(1); 13 | $this->withHeaders([ 14 | 'company' => $user->companies()->first()->id, 15 | ]); 16 | Sanctum::actingAs( 17 | $user, 18 | ['*'] 19 | ); 20 | }); 21 | 22 | test('get all used currencies', function () { 23 | getJson("/api/v1/currencies/used") 24 | ->assertOk(); 25 | }); 26 | -------------------------------------------------------------------------------- /tests/Feature/Admin/DashboardTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 10 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 11 | 12 | $user = User::find(1); 13 | $this->withHeaders([ 14 | 'company' => $user->companies()->first()->id, 15 | ]); 16 | Sanctum::actingAs( 17 | $user, 18 | ['*'] 19 | ); 20 | }); 21 | 22 | getJson('api/v1/dashboard')->assertOk(); 23 | 24 | getJson('api/v1/search?name=ab')->assertOk(); 25 | -------------------------------------------------------------------------------- /tests/Feature/Admin/LocationTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 10 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 11 | 12 | $user = User::find(1); 13 | $this->withHeaders([ 14 | 'company' => $user->companies()->first()->id, 15 | ]); 16 | Sanctum::actingAs( 17 | $user, 18 | ['*'] 19 | ); 20 | }); 21 | 22 | test('get countries', function () { 23 | $response = getJson('api/v1/countries'); 24 | 25 | $response->assertOk(); 26 | }); 27 | -------------------------------------------------------------------------------- /tests/Helpers.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 11 | } 12 | -------------------------------------------------------------------------------- /tests/Pest.php: -------------------------------------------------------------------------------- 1 | in('Feature'); 7 | uses(TestCase::class, RefreshDatabase::class)->in('Unit'); 8 | -------------------------------------------------------------------------------- /tests/Unit/CountryTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 9 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 10 | }); 11 | 12 | test('country has many addresses', function () { 13 | $country = Country::find(1); 14 | 15 | $address = Address::factory()->count(5)->create([ 16 | 'country_id' => $country->id, 17 | ]); 18 | 19 | $this->assertTrue($country->address()->exists()); 20 | }); 21 | -------------------------------------------------------------------------------- /tests/Unit/CustomFieldValueTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 8 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 9 | }); 10 | 11 | test('custom field value belongs to company', function () { 12 | $fieldValue = CustomFieldValue::factory()->create(); 13 | 14 | $this->assertTrue($fieldValue->company()->exists()); 15 | }); 16 | 17 | test('custom field value belongs to custom field', function () { 18 | $fieldValue = CustomFieldValue::factory()->forCustomField()->create(); 19 | 20 | $this->assertTrue($fieldValue->customField()->exists()); 21 | }); 22 | -------------------------------------------------------------------------------- /tests/Unit/ExpenseCategoryTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 8 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 9 | }); 10 | 11 | test('expense category has many expenses', function () { 12 | $category = ExpenseCategory::factory()->hasExpenses(5)->create(); 13 | 14 | $this->assertCount(5, $category->expenses); 15 | $this->assertTrue($category->expenses()->exists()); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/Unit/PaymentMethodTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 8 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 9 | }); 10 | 11 | test('payment method has many payment', function () { 12 | $method = PaymentMethod::factory()->hasPayments(5)->create(); 13 | 14 | $this->assertCount(5, $method->payments); 15 | 16 | $this->assertTrue($method->payments()->exists()); 17 | }); 18 | 19 | test('payment method belongs to company', function () { 20 | $method = PaymentMethod::factory()->create(); 21 | 22 | $this->assertTrue($method->company()->exists()); 23 | }); 24 | -------------------------------------------------------------------------------- /tests/Unit/SettingTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 9 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 10 | }); 11 | 12 | test('set setting', function () { 13 | $key = faker()->name; 14 | 15 | $value = faker()->word; 16 | 17 | Setting::setSetting($key, $value); 18 | 19 | $response = Setting::getSetting($key); 20 | 21 | $this->assertEquals($value, $response); 22 | }); 23 | -------------------------------------------------------------------------------- /tests/Unit/TaxTypeTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 8 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 9 | }); 10 | 11 | test('tax type has many taxes', function () { 12 | $taxtype = TaxType::factory()->hasTaxes(4)->create(); 13 | 14 | $this->assertCount(4, $taxtype->taxes); 15 | $this->assertTrue($taxtype->taxes()->exists()); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/Unit/UserTest.php: -------------------------------------------------------------------------------- 1 | 'DatabaseSeeder', '--force' => true]); 8 | Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); 9 | }); 10 | 11 | test('user belongs to currency', function () { 12 | $user = User::factory()->create(); 13 | 14 | $this->assertTrue($user->currency()->exists()); 15 | }); 16 | 17 | test('user belongs to many companies', function () { 18 | $user = User::factory()->hasCompanies(5)->create(); 19 | 20 | $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $user->companies); 21 | }); 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "strict": true, 7 | "jsx": "preserve", 8 | "sourceMap": true, 9 | "resolveJsonModule": true, 10 | "esModuleInterop": true, 11 | "lib": [ 12 | "esnext", 13 | "dom" 14 | ], 15 | "types": [ 16 | "vite/client" 17 | ], 18 | "baseUrl": ".", 19 | "paths": { 20 | "@/*": [ 21 | "resources/*" 22 | ] 23 | } 24 | }, 25 | "include": [ 26 | "resources/**/*" 27 | ] 28 | } -------------------------------------------------------------------------------- /uffizzi/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BASE_IMAGE 2 | 3 | FROM $BASE_IMAGE as build 4 | FROM nginx:1.17-alpine 5 | 6 | RUN rm /etc/nginx/conf.d/default.conf 7 | 8 | COPY --from=build /var/www /var/www 9 | COPY ./uffizzi/nginx/nginx /etc/nginx/conf.d/ 10 | -------------------------------------------------------------------------------- /uffizzi/nginx/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | client_max_body_size 64M; 3 | listen 80; 4 | index index.php index.html; 5 | error_log /var/log/nginx/error.log; 6 | access_log /var/log/nginx/access.log; 7 | root /var/www/public; 8 | location ~ \.php$ { 9 | try_files $uri =404; 10 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 11 | fastcgi_pass localhost:9000; 12 | fastcgi_index index.php; 13 | include fastcgi_params; 14 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 15 | fastcgi_param PATH_INFO $fastcgi_path_info; 16 | fastcgi_read_timeout 300; 17 | } 18 | location / { 19 | try_files $uri $uri/ /index.php?$query_string; 20 | gzip_static on; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'laravel-vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | export default defineConfig({ 5 | server: { 6 | watch: { 7 | ignored: ['**/.env/**'], 8 | }, 9 | }, 10 | resolve: { 11 | alias: { 12 | "vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js" 13 | } 14 | } 15 | }).withPlugins( 16 | vue 17 | ) 18 | --------------------------------------------------------------------------------