Invoice time support (#269)

* Changed invoice date to datetime

* Fixed code style errors

* Update TimeFormatsController.php

* Update TimeFormatter.php

* Update TimeFormatsController namespace

* Fix missing comma in language file

* Fix formatting

---------

Co-authored-by: troky <troky2001@yahoo.com>
This commit is contained in:
Darko Gjorgjijoski
2025-01-12 13:32:47 +01:00
committed by GitHub
parent 32e03b98a3
commit f52b73f517
14 changed files with 242 additions and 3 deletions

View File

@@ -21,6 +21,7 @@ export const useGlobalStore = (useWindow = false) => {
// Global Lists
timeZones: [],
dateFormats: [],
timeFormats: [],
currencies: [],
countries: [],
languages: [],
@@ -156,6 +157,25 @@ export const useGlobalStore = (useWindow = false) => {
})
},
fetchTimeFormats() {
return new Promise((resolve, reject) => {
if (this.timeFormats.length) {
resolve(this.timeFormats)
} else {
axios
.get('/api/v1/time/formats')
.then((response) => {
this.timeFormats = response.data.time_formats
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
}
})
},
fetchTimeZones() {
return new Promise((resolve, reject) => {
if (this.timeZones.length) {

View File

@@ -499,7 +499,13 @@ export const useInvoiceStore = (useWindow = false) => {
this.newInvoice.sales_tax_address_type = companyStore.selectedCompanySettings.sales_tax_address_type
this.newInvoice.discount_per_item =
companyStore.selectedCompanySettings.discount_per_item
this.newInvoice.invoice_date = moment().format('YYYY-MM-DD')
let dateFormat = 'YYYY-MM-DD';
if (companyStore.selectedCompanySettings.invoice_use_time === 'YES') {
dateFormat += ' HH:mm'
}
this.newInvoice.invoice_date = moment().format(dateFormat)
if (companyStore.selectedCompanySettings.invoice_set_due_date_automatically === 'YES') {
this.newInvoice.due_date = moment()
.add(companyStore.selectedCompanySettings.invoice_due_date_days, 'days')

View File

@@ -20,6 +20,8 @@
:content-loading="isLoading"
:calendar-button="true"
calendar-button-icon="calendar"
:enableTime="enableTime"
:time24hr="time24h"
/>
</BaseInputGroup>
@@ -61,8 +63,10 @@
</template>
<script setup>
import { computed } from 'vue'
import ExchangeRateConverter from '@/scripts/admin/components/estimate-invoice-common/ExchangeRateConverter.vue'
import { useInvoiceStore } from '@/scripts/admin/stores/invoice'
import { useCompanyStore } from '@/scripts/admin/stores/company'
const props = defineProps({
v: {
@@ -80,4 +84,17 @@ const props = defineProps({
})
const invoiceStore = useInvoiceStore()
const companyStore = useCompanyStore()
const enableTime = computed(() => {
return (
companyStore.selectedCompanySettings.invoice_use_time === 'YES'
);
})
const time24h = computed(() => {
return (
companyStore.selectedCompanySettings.carbon_time_format.indexOf('H') > -1
);
})
</script>

View File

@@ -80,10 +80,11 @@
label="display_date"
value-prop="carbon_format_value"
track-by="display_date"
searchable
:searchable="true"
:invalid="v$.carbon_date_format.$error"
class="w-full"
/>
</BaseInputGroup>
<BaseInputGroup
@@ -104,8 +105,36 @@
class="w-full"
/>
</BaseInputGroup>
<BaseInputGroup
:label="$t('settings.preferences.time_format')"
:content-loading="isFetchingInitialData"
:error="
v$.carbon_time_format.$error &&
v$.carbon_time_format.$errors[0].$message
"
required
>
<BaseMultiselect
v-model="settingsForm.carbon_time_format"
:content-loading="isFetchingInitialData"
:options="globalStore.timeFormats"
label="display_time"
value-prop="carbon_format_value"
track-by="display_time"
:searchable="true"
:invalid="v$.carbon_time_format.$error"
class="w-full"
/>
</BaseInputGroup>
</BaseInputGrid>
<BaseSwitchSection
v-model="invoiceUseTimeField"
:title="$t('settings.preferences.invoice_use_time')"
:description="$t('settings.preferences.invoice_use_time_description')"
/>
<BaseButton
:content-loading="isFetchingInitialData"
:disabled="isSaving"
@@ -218,6 +247,33 @@ watch(
}
)
watch(
() => settingsForm.carbon_time_format,
(val) => {
if (val) {
const timeFormatObject = globalStore.timeFormats.find((d) => {
return d.carbon_format_value === val
})
settingsForm.moment_time_format = timeFormatObject.moment_format_value
}
}
)
const invoiceUseTimeField = computed({
get: () => {
return settingsForm.invoice_use_time === 'YES'
},
set: async (newValue) => {
const value = newValue ? 'YES' : 'NO'
let data = {
settings: {
invoice_use_time: value,
},
}
settingsForm.invoice_use_time = value
}
})
const discountPerItemField = computed({
get: () => {
return settingsForm.discount_per_item === 'YES'
@@ -271,12 +327,21 @@ const rules = computed(() => {
moment_date_format: {
required: helpers.withMessage(t('validation.required'), required),
},
carbon_time_format: {
required: helpers.withMessage(t('validation.required'), required),
},
moment_time_format: {
required: helpers.withMessage(t('validation.required'), required),
},
time_zone: {
required: helpers.withMessage(t('validation.required'), required),
},
fiscal_year: {
required: helpers.withMessage(t('validation.required'), required),
},
invoice_use_time: {
required: helpers.withMessage(t('validation.required'), required),
},
}
})
@@ -292,6 +357,7 @@ async function setInitialData() {
Promise.all([
globalStore.fetchCurrencies(),
globalStore.fetchDateFormats(),
globalStore.fetchTimeFormats(),
globalStore.fetchTimeZones(),
]).then(([res1]) => {
isFetchingInitialData.value = false

View File

@@ -254,6 +254,14 @@ const carbonFormat = computed(() => {
return companyStore.selectedCompanySettings?.carbon_date_format
})
const carbonFormatWithTime = computed(() => {
let format = companyStore.selectedCompanySettings?.carbon_date_format
if (companyStore.selectedCompanySettings?.invoice_use_time === 'YES') {
format += ' ' + companyStore.selectedCompanySettings?.carbon_time_format
}
return format.replace("g", "h").replace("a", "K");
})
const hasIconSlot = computed(() => {
return !!slots.icon
})
@@ -301,7 +309,7 @@ watch(
config.altFormat = carbonFormat.value ? carbonFormat.value : 'd M Y'
} else {
config.altFormat = carbonFormat.value
? `${carbonFormat.value} H:i `
? `${carbonFormatWithTime.value}`
: 'd M Y H:i'
}
},