├── .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 |
10 |
11 |
--------------------------------------------------------------------------------
/public/build/img/login/login-vector2.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/public/build/img/login/login-vector3.svg:
--------------------------------------------------------------------------------
1 |
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 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/custom-fields/types/DateTimeType.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
25 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/custom-fields/types/DateType.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
25 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/custom-fields/types/InputType.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
24 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/custom-fields/types/NumberType.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
24 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/custom-fields/types/PhoneType.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
24 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/custom-fields/types/SwitchType.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
26 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/custom-fields/types/TextAreaType.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
32 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/custom-fields/types/TimeType.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
25 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/custom-fields/types/UrlType.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
24 |
--------------------------------------------------------------------------------
/resources/scripts/admin/components/modal-components/ExchangeRateBulkUpdateModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
25 |
--------------------------------------------------------------------------------
/resources/scripts/admin/layouts/LayoutInstallation.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
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 |
2 |
6 |
7 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/resources/scripts/admin/views/settings/customization/estimates/EstimatesTabEstimateNumber.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
15 |
--------------------------------------------------------------------------------
/resources/scripts/admin/views/settings/customization/invoices/InvoicesTabInvoiceNumber.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
15 |
--------------------------------------------------------------------------------
/resources/scripts/admin/views/settings/customization/payments/PaymentsTabPaymentNumber.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
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 |
2 |
14 |
15 |
16 |
17 |
18 |
30 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseBreadcrumb.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseContentPlaceholdersBox.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
26 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseContentPlaceholdersHeading.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
26 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseContentPlaceholdersText.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
32 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseCustomTag.vue:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseCustomerAddressDisplay.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
{{ address?.address_street_1 }},
7 |
8 |
{{ address?.address_street_2 }},
9 |
10 |
{{ address?.city }},
11 |
12 |
{{ address?.state }},
13 |
14 |
{{ address?.country?.name }},
15 |
16 |
{{ address?.zip }}.
17 |
18 |
19 |
20 |
28 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseDescriptionList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseDivider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseDropdownItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
18 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseHeading.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
26 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
22 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseInputGrid.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseLabel.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseNewBadge.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
20 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BasePage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BasePageHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ title }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
24 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseScrollPane.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseSelectAction.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseSpinner.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseTab.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
30 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/BaseText.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ displayText }}
4 |
5 |
6 |
7 |
32 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/BoldIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/CodeBlockIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/CodingIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/ItalicIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/ListUlIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/MenuCenterIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/ParagraphIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/QuoteIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/RedoIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/UnderlineIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/scripts/components/base/base-editor/icons/UndoIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/scripts/components/icons/LoadingIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/resources/scripts/components/icons/SpinnerIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/resources/scripts/components/list/BaseList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
--------------------------------------------------------------------------------
/resources/scripts/components/svg/LoginBottomVector.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
--------------------------------------------------------------------------------
/resources/scripts/customer/layouts/partials/TheSiteFooter.vue:
--------------------------------------------------------------------------------
1 |
2 |
27 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
13 |
--------------------------------------------------------------------------------
/resources/scripts/customer/views/SamplePage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Samplez Pages
4 | Hello
5 | {{ customerStore.customers }}
6 |
7 |
8 |
9 |
10 |
16 |
--------------------------------------------------------------------------------
/resources/scripts/customer/views/dashboard/Dashboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
--------------------------------------------------------------------------------
/resources/scripts/customer/views/dashboard/DashboardStatsPlaceholder.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
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 |
10 |
11 |
--------------------------------------------------------------------------------
/resources/static/img/login/login-vector2.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/resources/static/img/login/login-vector3.svg:
--------------------------------------------------------------------------------
1 |
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 |
10 | |
11 |
12 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/html/header.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/html/panel.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ Illuminate\Mail\Markdown::parse($slot) }}
8 | |
9 |
10 |
11 | |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/html/promotion.blade.php:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/html/promotion/button.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 | |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/html/subcopy.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ Illuminate\Mail\Markdown::parse($slot) }}
5 | |
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------