diff --git a/app/Http/Controllers/V1/Admin/Customer/CustomerStatsController.php b/app/Http/Controllers/V1/Admin/Customer/CustomerStatsController.php index 1d2c0415a..1bf91f38c 100644 --- a/app/Http/Controllers/V1/Admin/Customer/CustomerStatsController.php +++ b/app/Http/Controllers/V1/Admin/Customer/CustomerStatsController.php @@ -103,6 +103,7 @@ public function __invoke(Request $request, Customer $customer) ) ->whereCompany() ->whereCustomer($customer->id) + ->where('status', '<>', Invoice::STATUS_DRAFT) ->sum('total'); $totalReceipts = Payment::whereBetween( 'payment_date', diff --git a/app/Http/Controllers/V1/Admin/Dashboard/DashboardController.php b/app/Http/Controllers/V1/Admin/Dashboard/DashboardController.php index 4e1d96d22..a92fbc237 100644 --- a/app/Http/Controllers/V1/Admin/Dashboard/DashboardController.php +++ b/app/Http/Controllers/V1/Admin/Dashboard/DashboardController.php @@ -104,6 +104,7 @@ public function __invoke(Request $request) 'invoice_date', [$startDate->format('Y-m-d'), $start->format('Y-m-d')] ) + ->where('status', '<>', Invoice::STATUS_DRAFT) ->whereCompany() ->sum('base_total'); @@ -141,6 +142,7 @@ public function __invoke(Request $request) $recent_due_invoices = Invoice::with('customer') ->whereCompany() ->where('base_due_amount', '>', 0) + ->where('status', '<>', Invoice::STATUS_DRAFT) ->take(5) ->latest() ->get(); diff --git a/app/Http/Controllers/V1/Admin/Invoice/InvoicesController.php b/app/Http/Controllers/V1/Admin/Invoice/InvoicesController.php index 9aeefe518..3890d2899 100644 --- a/app/Http/Controllers/V1/Admin/Invoice/InvoicesController.php +++ b/app/Http/Controllers/V1/Admin/Invoice/InvoicesController.php @@ -24,6 +24,7 @@ public function index(Request $request) $limit = $request->has('limit') ? $request->limit : 10; $invoices = Invoice::whereCompany() + ->whereTabFilters($request->tab_status) ->join('customers', 'customers.id', '=', 'invoices.customer_id') ->applyFilters($request->all()) ->select('invoices.*', 'customers.name') diff --git a/app/Http/Requests/CompaniesRequest.php b/app/Http/Requests/CompaniesRequest.php index 5394592be..661d8777e 100644 --- a/app/Http/Requests/CompaniesRequest.php +++ b/app/Http/Requests/CompaniesRequest.php @@ -3,7 +3,6 @@ namespace Crater\Http\Requests; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Str; use Illuminate\Validation\Rule; class CompaniesRequest extends FormRequest @@ -34,6 +33,10 @@ public function rules() 'currency' => [ 'required' ], + 'slug' => [ + 'required', + Rule::unique('companies') + ], 'address.name' => [ 'nullable', ], @@ -68,11 +71,11 @@ public function getCompanyPayload() { return collect($this->validated()) ->only([ - 'name' + 'name', + 'slug' ]) ->merge([ - 'owner_id' => $this->user()->id, - 'slug' => Str::slug($this->name) + 'owner_id' => $this->user()->id ]) ->toArray(); } diff --git a/app/Http/Requests/CompanyRequest.php b/app/Http/Requests/CompanyRequest.php index c86cd6457..dc22b1ae7 100644 --- a/app/Http/Requests/CompanyRequest.php +++ b/app/Http/Requests/CompanyRequest.php @@ -30,7 +30,8 @@ public function rules() Rule::unique('companies')->ignore($this->header('company'), 'id'), ], 'slug' => [ - 'nullable' + 'required', + Rule::unique('companies')->ignore($this->header('company'), 'id'), ], 'address.country_id' => [ 'required', diff --git a/app/Http/Resources/EstimateResource.php b/app/Http/Resources/EstimateResource.php index 46b69ea39..e7284bd7a 100644 --- a/app/Http/Resources/EstimateResource.php +++ b/app/Http/Resources/EstimateResource.php @@ -23,7 +23,7 @@ public function toArray($request) 'reference_number' => $this->reference_number, 'tax_per_item' => $this->tax_per_item, 'discount_per_item' => $this->discount_per_item, - 'notes' => $this->getNotes(), + 'notes' => $this->notes, 'discount' => $this->discount, 'discount_type' => $this->discount_type, 'discount_val' => $this->discount_val, diff --git a/app/Http/Resources/PaymentResource.php b/app/Http/Resources/PaymentResource.php index 0ac625f85..7350a9127 100644 --- a/app/Http/Resources/PaymentResource.php +++ b/app/Http/Resources/PaymentResource.php @@ -18,7 +18,7 @@ public function toArray($request) 'id' => $this->id, 'payment_number' => $this->payment_number, 'payment_date' => $this->payment_date, - 'notes' => $this->getNotes(), + 'notes' => $this->notes, 'amount' => $this->amount, 'unique_hash' => $this->unique_hash, 'invoice_id' => $this->invoice_id, diff --git a/app/Models/Company.php b/app/Models/Company.php index bf87820b1..a0d9fddbb 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -217,7 +217,7 @@ public function setupDefaultSettings() 'estimate_billing_address_format' => $billingAddressFormat, 'payment_company_address_format' => $companyAddressFormat, 'payment_from_customer_address_format' => $paymentFromCustomerAddress, - 'currency' => request()->currency ?? 13, + 'currency' => request()->currency ?? 1, 'time_zone' => 'Asia/Kolkata', 'language' => 'en', 'fiscal_year' => '1-12', diff --git a/app/Models/Estimate.php b/app/Models/Estimate.php index 5b7c3b8fd..8c916c6a8 100644 --- a/app/Models/Estimate.php +++ b/app/Models/Estimate.php @@ -483,7 +483,8 @@ public function getExtraFields() '{ESTIMATE_DATE}' => $this->formattedEstimateDate, '{ESTIMATE_EXPIRY_DATE}' => $this->formattedExpiryDate, '{ESTIMATE_NUMBER}' => $this->estimate_number, - '{ESTIMATE_REF_NUMBER}' => $this->reference_number, + '{PDF_LINK}' => $this->estimatePdfUrl, + '{TOTAL_AMOUNT}' => format_money_pdf($this->total, $this->customer->currency) ]; } diff --git a/app/Models/Expense.php b/app/Models/Expense.php index bd0aa1e35..01dd69a26 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -240,7 +240,7 @@ public static function createExpense($request) } if ($request->hasFile('attachment_receipt')) { - $expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts'); + $expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local'); } if ($request->customFields) { @@ -262,12 +262,12 @@ public function updateExpense($request) ExchangeRateLog::addExchangeRateLog($this); } - if (isset($request->is_attachment_receipt_removed) && (bool) $request->is_attachment_receipt_removed) { + if (isset($request->is_attachment_receipt_removed) && $request->is_attachment_receipt_removed == "true") { $this->clearMediaCollection('receipts'); } if ($request->hasFile('attachment_receipt')) { $this->clearMediaCollection('receipts'); - $this->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts'); + $this->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local'); } if ($request->customFields) { diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 39cd31659..eb973488e 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -187,16 +187,6 @@ public function getFormattedInvoiceDateAttribute($value) return Carbon::parse($this->invoice_date)->format($dateFormat); } - public function scopeWhereStatus($query, $status) - { - return $query->where('invoices.status', $status); - } - - public function scopeWherePaidStatus($query, $status) - { - return $query->where('invoices.paid_status', $status); - } - public function scopeWhereDueStatus($query, $status) { return $query->whereIn('invoices.paid_status', [ @@ -234,6 +224,40 @@ public function scopeWhereOrder($query, $orderByField, $orderBy) $query->orderBy($orderByField, $orderBy); } + public function scopeWhereStatus($query, $status) + { + return $query->where('invoices.status', $status); + } + + public function scopeWherePaidStatus($query, $status) + { + return $query->where('invoices.paid_status', $status); + } + + public function scopeWhereTabFilters($query, $status) + { + if ($status == "DRAFT") { + return $query->where('invoices.status', $status); + } + + if ($status == "SENT") { + return $query->whereIn('invoices.status', [ + self::STATUS_SENT, + self::STATUS_VIEWED, + self::STATUS_COMPLETED + ]); + } + + if ($status == 'DUE') { + return $query->whereIn('invoices.paid_status', [ + self::STATUS_UNPAID, + self::STATUS_PARTIALLY_PAID, + ]); + } + + return ; + } + public function scopeApplyFilters($query, array $filters) { $filters = collect($filters); @@ -249,17 +273,11 @@ public function scopeApplyFilters($query, array $filters) $filters->get('status') == self::STATUS_PAID ) { $query->wherePaidStatus($filters->get('status')); - } elseif ($filters->get('status') == 'DUE') { - $query->whereDueStatus($filters->get('status')); } else { $query->whereStatus($filters->get('status')); } } - if ($filters->get('paid_status')) { - $query->wherePaidStatus($filters->get('status')); - } - if ($filters->get('invoice_id')) { $query->whereInvoice($filters->get('invoice_id')); } @@ -651,7 +669,9 @@ public function getExtraFields() '{INVOICE_DATE}' => $this->formattedInvoiceDate, '{INVOICE_DUE_DATE}' => $this->formattedDueDate, '{INVOICE_NUMBER}' => $this->invoice_number, - '{INVOICE_REF_NUMBER}' => $this->reference_number, + '{PDF_LINK}' => $this->invoicePdfUrl, + '{DUE_AMOUNT}' => format_money_pdf($this->due_amount, $this->customer->currency), + '{TOTAL_AMOUNT}' => format_money_pdf($this->total, $this->customer->currency) ]; } diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 83a17441d..68a6d6a35 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -435,7 +435,8 @@ public function getExtraFields() '{PAYMENT_DATE}' => $this->formattedPaymentDate, '{PAYMENT_MODE}' => $this->paymentMethod ? $this->paymentMethod->name : null, '{PAYMENT_NUMBER}' => $this->payment_number, - '{PAYMENT_AMOUNT}' => $this->reference_number, + '{PDF_LINK}' => $this->paymentPdfUrl, + '{PAYMENT_AMOUNT}' => format_money_pdf($this->amount, $this->customer->currency) ]; } diff --git a/package.json b/package.json index c8da7a6dc..ac8a14402 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "vite": "^2.6.1" }, "dependencies": { - "@headlessui/vue": "^1.4.0", + "@headlessui/vue": "^1.5.0", "@heroicons/vue": "^1.0.1", "@popperjs/core": "^2.9.2", "@stripe/stripe-js": "^1.21.2", @@ -48,7 +48,8 @@ "mini-svg-data-uri": "^1.3.3", "moment": "^2.29.1", "pinia": "^2.0.4", - "v-money3": "^3.13.5", + "v-calendar": "3.0.0-alpha.8", + "v-money3": "3.16.1", "v-tooltip": "^4.0.0-alpha.1", "vue": "^3.2.0-beta.5", "vue-flatpickr-component": "^9.0.3", diff --git a/resources/scripts/admin/components/CopyInputField.vue b/resources/scripts/admin/components/CopyInputField.vue index 851a0bc4e..66049440d 100644 --- a/resources/scripts/admin/components/CopyInputField.vue +++ b/resources/scripts/admin/components/CopyInputField.vue @@ -7,6 +7,7 @@ py-2 rounded-lg bg-opacity-40 bg-gray-300 + dark:bg-gray-700 dark:border-gray-600 whitespace-nowrap flex-col mt-1 @@ -19,6 +20,7 @@ text-sm font-medium text-black + dark:text-white truncate select-all select-color " diff --git a/resources/scripts/admin/components/SelectNotePopup.vue b/resources/scripts/admin/components/SelectNotePopup.vue index 822a8e2c6..bcc81cca0 100644 --- a/resources/scripts/admin/components/SelectNotePopup.vue +++ b/resources/scripts/admin/components/SelectNotePopup.vue @@ -43,6 +43,12 @@ max-w-full left-0 top-3 + bg-white + dark:border + dark:border-white/10 + dark:text-white + dark:bg-gray-800 + dark:shadow-glass " >
- |
-
- |
-
- |
-
+
+ |
+
+ |
+
+ |
+
+ |
+
+ |
+ |
---|
+
{{ $t('customers.portal_access_text') }}
@@ -425,9 +425,7 @@+
{{ gIndex }}
+
{{ $t('settings.disk.is_default') }}
+
{{ $t('settings.disk.is_default') }}
+
{{ $t('settings.disk.is_default') }}
+
{{ $t('settings.disk.is_default') }}
+
{{
$t('modules.api_token_description', {
url: globalStore.config.base_url.replace(/^http:\/\//, ''),
diff --git a/resources/scripts/admin/views/payments/Create.vue b/resources/scripts/admin/views/payments/Create.vue
index 39888302e..1a6461d0a 100644
--- a/resources/scripts/admin/views/payments/Create.vue
+++ b/resources/scripts/admin/views/payments/Create.vue
@@ -82,9 +82,9 @@
required
>
{{ $t('payments.no_matching_payments') }}
diff --git a/resources/scripts/admin/views/recurring-invoices/Index.vue b/resources/scripts/admin/views/recurring-invoices/Index.vue index 2977d1f70..f0436e5b4 100644 --- a/resources/scripts/admin/views/recurring-invoices/Index.vue +++ b/resources/scripts/admin/views/recurring-invoices/Index.vue @@ -121,6 +121,7 @@ mt-5 list-none border-b-2 border-gray-200 border-solid + dark:border-gray-600 " > @@ -150,12 +151,12 @@ " > {{ $t('general.actions') }} -+
{{ $t('recurring_invoices.send_automatically') }}
{{ $t('recurring_invoices.send_automatically_desc') }} diff --git a/resources/scripts/admin/views/recurring-invoices/partials/RecurringInvoiceViewSidebar.vue b/resources/scripts/admin/views/recurring-invoices/partials/RecurringInvoiceViewSidebar.vue index 42445324c..d444fdfa8 100644 --- a/resources/scripts/admin/views/recurring-invoices/partials/RecurringInvoiceViewSidebar.vue +++ b/resources/scripts/admin/views/recurring-invoices/partials/RecurringInvoiceViewSidebar.vue @@ -152,6 +152,7 @@ onSearched = debounce(onSearched, 500) xl:ml-64 w-88 xl:block + dark:bg-gray-800 " >
{{ $t('invoices.no_matching_invoices') }}
diff --git a/resources/scripts/admin/views/settings/BackupSetting.vue b/resources/scripts/admin/views/settings/BackupSetting.vue index f62e348b5..f0a60d013 100644 --- a/resources/scripts/admin/views/settings/BackupSetting.vue +++ b/resources/scripts/admin/views/settings/BackupSetting.vue @@ -51,14 +51,14 @@{{ $tc('settings.company_info.delete_company_description') }}
@@ -160,6 +173,7 @@ let isSaving = ref(false) const companyForm = reactive({ name: null, + slug: null, logo: null, address: { address_street_1: '', @@ -193,7 +207,14 @@ const rules = computed(() => { name: { required: helpers.withMessage(t('validation.required'), required), minLength: helpers.withMessage( - t('validation.name_min_length'), + t('validation.name_min_length', { count: 3 }), + minLength(3) + ), + }, + slug: { + required: helpers.withMessage(t('validation.required'), required), + minLength: helpers.withMessage( + t('validation.name_min_length', { count: 3 }), minLength(3) ), }, diff --git a/resources/scripts/admin/views/settings/CustomFieldsSetting.vue b/resources/scripts/admin/views/settings/CustomFieldsSetting.vue index 1cad62b00..bc39c082d 100644 --- a/resources/scripts/admin/views/settings/CustomFieldsSetting.vue +++ b/resources/scripts/admin/views/settings/CustomFieldsSetting.vue @@ -27,7 +27,7 @@ > {{ row.data.name }} - ({{ row.data.slug }}) + ({{ row.data.slug }}) @@ -60,7 +60,7 @@
{{ $t('settings.exchange_rate.providers_description') }}
diff --git a/resources/scripts/admin/views/settings/FileDiskSetting.vue b/resources/scripts/admin/views/settings/FileDiskSetting.vue
index 5e5bda80b..99be2f420 100644
--- a/resources/scripts/admin/views/settings/FileDiskSetting.vue
+++ b/resources/scripts/admin/views/settings/FileDiskSetting.vue
@@ -45,27 +45,30 @@
{{ $t('settings.update_app.update_warning') }}
{{ $t('settings.update_app.progress_text') }}
@@ -150,18 +135,11 @@
{{ $t(step.translationKey) }} {{ $t(step.translationKey) }}
- {{
+
+
{{ element.description }}
- {{ $t('settings.customization.estimates.convert_estimate_description') }}
-
+
{{ $t('general.note') }}
-
{{ i }}
@@ -136,7 +121,7 @@
{{ $t('settings.update_app.update_progress') }}
- {{ $t(`settings.customization.${type}s.${type}_number_format`) }}
-
-
@@ -29,6 +29,7 @@
leading-5
text-left text-gray-700
border-t border-b border-gray-200 border-solid
+ dark:border-gray-600
"
>
Component
@@ -55,6 +57,7 @@
leading-5
text-left text-gray-700
border-t border-b border-gray-200 border-solid
+ dark:text-gray-300 dark:border-gray-600
"
>
Parameter
@@ -69,13 +72,14 @@
leading-5
text-left text-gray-700
border-t border-b border-gray-200 border-solid
+ dark:border-gray-600
"
>
+
-