- fix invoice status not updating issue

- date range selection issues on report for non-english languages
- fix invoice all tab issue (always showing draft even in all tab)
This commit is contained in:
Harsh Jagad
2022-02-24 05:22:32 +00:00
committed by Mohit Panjwani
parent 7202fdcbf2
commit 1322ed15dc
15 changed files with 268 additions and 61 deletions

View File

@ -40,7 +40,9 @@ class CheckInvoiceStatus extends Command
public function handle() public function handle()
{ {
$date = Carbon::now(); $date = Carbon::now();
$invoices = Invoice::where('status', '<>', Invoice::STATUS_COMPLETED)->whereDate('due_date', '<', $date)->get(); $invoices = Invoice::whereNotIn('status', [Invoice::STATUS_COMPLETED, Invoice::STATUS_DRAFT])
->whereDate('due_date', '<', $date)
->get();
foreach ($invoices as $invoice) { foreach ($invoices as $invoice) {
$invoice->status = Invoice::STATUS_OVERDUE; $invoice->status = Invoice::STATUS_OVERDUE;

View File

@ -170,6 +170,8 @@ let estimateMailForm = reactive({
body: null, body: null,
}) })
const emit = defineEmits(['update'])
const modalActive = computed(() => { const modalActive = computed(() => {
return modalStore.active && modalStore.componentName === 'SendEstimateModal' return modalStore.active && modalStore.componentName === 'SendEstimateModal'
}) })
@ -249,6 +251,7 @@ async function submitForm() {
isLoading.value = false isLoading.value = false
if (response.data.success) { if (response.data.success) {
emit('update')
closeSendEstimateModal() closeSendEstimateModal()
return true return true
} }

View File

@ -167,6 +167,8 @@ let isLoading = ref(false)
const templateUrl = ref('') const templateUrl = ref('')
const isPreview = ref(false) const isPreview = ref(false)
const emit = defineEmits(['update'])
const invoiceMailFields = ref([ const invoiceMailFields = ref([
'customer', 'customer',
'customerCustom', 'customerCustom',
@ -263,6 +265,7 @@ async function submitForm() {
isLoading.value = false isLoading.value = false
if (response.data.success) { if (response.data.success) {
emit('update', modalStore.id)
closeSendInvoiceModal() closeSendInvoiceModal()
return true return true
} }

View File

@ -272,7 +272,7 @@ const router = useRouter()
let filters = reactive({ let filters = reactive({
customer_id: '', customer_id: '',
status: 'DRAFT', status: '',
from_date: '', from_date: '',
to_date: '', to_date: '',
estimate_number: '', estimate_number: '',

View File

@ -1,5 +1,5 @@
<template> <template>
<SendEstimateModal /> <SendEstimateModal @update="updateSentEstimate" />
<BasePage v-if="estimateData" class="xl:pl-96 xl:ml-8"> <BasePage v-if="estimateData" class="xl:pl-96 xl:ml-8">
<BasePageHeader :title="pageTitle"> <BasePageHeader :title="pageTitle">
<template #actions> <template #actions>
@ -526,4 +526,15 @@ async function removeEstimate(id) {
} }
}) })
} }
function updateSentEstimate() {
let pos = estimateList.value.findIndex(
(estimate) => estimate.id === estimateData.value.id
)
if (estimateList.value[pos]) {
estimateList.value[pos].status = 'SENT'
estimateData.value.status = 'SENT'
}
}
</script> </script>

View File

@ -299,7 +299,7 @@ const userStore = useUserStore()
let filters = reactive({ let filters = reactive({
customer_id: '', customer_id: '',
status: 'DRAFT', status: '',
from_date: '', from_date: '',
to_date: '', to_date: '',
invoice_number: '', invoice_number: '',

View File

@ -212,13 +212,24 @@ function sortData() {
return true return true
} }
function updateSentInvoice() {
let pos = invoiceList.value.findIndex(
(invoice) => invoice.id === invoiceData.value.id
)
if (invoiceList.value[pos]) {
invoiceList.value[pos].status = 'SENT'
invoiceData.value.status = 'SENT'
}
}
loadInvoices() loadInvoices()
loadInvoice() loadInvoice()
onSearched = debounce(onSearched, 500) onSearched = debounce(onSearched, 500)
</script> </script>
<template> <template>
<SendInvoiceModal /> <SendInvoiceModal @update="updateSentInvoice" />
<BasePage v-if="invoiceData" class="xl:pl-96 xl:ml-8"> <BasePage v-if="invoiceData" class="xl:pl-96 xl:ml-8">
<BasePageHeader :title="pageTitle"> <BasePageHeader :title="pageTitle">

View File

@ -283,7 +283,7 @@ const router = useRouter()
let filters = reactive({ let filters = reactive({
customer_id: '', customer_id: '',
status: 'ACTIVE', status: '',
from_date: '', from_date: '',
to_date: '', to_date: '',
}) })

View File

@ -27,12 +27,7 @@
to="#" to="#"
active active
/> />
<BaseBreadcrumbItem <BaseBreadcrumbItem v-else :title="pageTitle" to="#" active />
v-else
:title="pageTitle"
to="#"
active
/>
</BaseBreadcrumb> </BaseBreadcrumb>
<template #actions> <template #actions>
@ -143,6 +138,8 @@
import { computed, ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useNotificationStore } from '@/scripts/stores/notification'
import { useModalStore } from '@/scripts/stores/modal'
import CreateItems from '@/scripts/admin/components/estimate-invoice-common/CreateItems.vue' import CreateItems from '@/scripts/admin/components/estimate-invoice-common/CreateItems.vue'
import CreateTotal from '@/scripts/admin/components/estimate-invoice-common/CreateTotal.vue' import CreateTotal from '@/scripts/admin/components/estimate-invoice-common/CreateTotal.vue'
import SelectTemplateButton from '@/scripts/admin/components/estimate-invoice-common/SelectTemplateButton.vue' import SelectTemplateButton from '@/scripts/admin/components/estimate-invoice-common/SelectTemplateButton.vue'
@ -165,6 +162,7 @@ import { useCompanyStore } from '@/scripts/admin/stores/company'
import { useCustomFieldStore } from '@/scripts/admin/stores/custom-field' import { useCustomFieldStore } from '@/scripts/admin/stores/custom-field'
import { useRecurringInvoiceStore } from '@/scripts/admin/stores/recurring-invoice' import { useRecurringInvoiceStore } from '@/scripts/admin/stores/recurring-invoice'
import { useModuleStore } from '@/scripts/admin/stores/module' import { useModuleStore } from '@/scripts/admin/stores/module'
import { useCustomerStore } from '@/scripts/admin/stores/customer'
import SelectTemplateModal from '@/scripts/admin/components/modal-components/SelectTemplateModal.vue' import SelectTemplateModal from '@/scripts/admin/components/modal-components/SelectTemplateModal.vue'
import TaxTypeModal from '@/scripts/admin/components/modal-components/TaxTypeModal.vue' import TaxTypeModal from '@/scripts/admin/components/modal-components/TaxTypeModal.vue'
import ItemModal from '@/scripts/admin/components/modal-components/ItemModal.vue' import ItemModal from '@/scripts/admin/components/modal-components/ItemModal.vue'
@ -173,7 +171,10 @@ const recurringInvoiceStore = useRecurringInvoiceStore()
const companyStore = useCompanyStore() const companyStore = useCompanyStore()
const customFieldStore = useCustomFieldStore() const customFieldStore = useCustomFieldStore()
const moduleStore = useModuleStore() const moduleStore = useModuleStore()
const modalStore = useModalStore()
const customerStore = useCustomerStore()
const recurringInvoiceValidationScope = 'newRecurringInvoice' const recurringInvoiceValidationScope = 'newRecurringInvoice'
const notificationStore = useNotificationStore()
const { t } = useI18n() const { t } = useI18n()
let isSaving = ref(false) let isSaving = ref(false)
@ -292,6 +293,16 @@ async function submitForm() {
tax: recurringInvoiceStore.getTotalTax, tax: recurringInvoiceStore.getTotalTax,
} }
if (data.customer && !data.customer.email && data.send_automatically) {
notificationStore.showNotification({
type: 'error',
message: t('recurring_invoices.add_customer_email'),
})
editCustomer()
isSaving.value = false
return
}
if (route.params.id) { if (route.params.id) {
recurringInvoiceStore recurringInvoiceStore
.updateRecurringInvoice(data) .updateRecurringInvoice(data)
@ -309,6 +320,16 @@ async function submitForm() {
} }
} }
async function editCustomer() {
let selectedCustomer = recurringInvoiceStore.newRecurringInvoice.customer.id
await customerStore.fetchCustomer(selectedCustomer)
modalStore.openModal({
title: t('customers.edit_customer'),
componentName: 'CustomerModal',
})
}
function submitCreate(data) { function submitCreate(data) {
recurringInvoiceStore recurringInvoiceStore
.addRecurringInvoice(data) .addRecurringInvoice(data)

View File

@ -1,5 +1,5 @@
<template> <template>
<SendInvoiceModal /> <SendInvoiceModal @update="updateSentInvoiceStatus" />
<div class="relative table-container"> <div class="relative table-container">
<BaseTable <BaseTable
ref="table" ref="table"
@ -97,4 +97,14 @@ function hasAtleastOneAbility() {
function refreshTable() { function refreshTable() {
table.value && table.value.refresh() table.value && table.value.refresh()
} }
function updateSentInvoiceStatus(id) {
let pos = recurringInvoiceStore.newRecurringInvoice.invoices.findIndex(
(invoice) => invoice.id === id
)
if (recurringInvoiceStore.newRecurringInvoice.invoices[pos]) {
recurringInvoiceStore.newRecurringInvoice.invoices[pos].status = 'SENT'
}
}
</script> </script>

View File

@ -8,6 +8,10 @@
<BaseMultiselect <BaseMultiselect
v-model="selectedRange" v-model="selectedRange"
:options="dateRange" :options="dateRange"
value-prop="key"
track-by="key"
label="label"
object
@update:modelValue="onChangeDateRange" @update:modelValue="onChangeDateRange"
/> />
</BaseInputGroup> </BaseInputGroup>
@ -97,19 +101,49 @@ const { t } = useI18n()
globalStore.downloadReport = downloadReport globalStore.downloadReport = downloadReport
const dateRange = reactive([ const dateRange = reactive([
t('dateRange.today'), {
t('dateRange.this_week'), label: t('dateRange.today'),
t('dateRange.this_month'), key: 'Today',
t('dateRange.this_quarter'), },
t('dateRange.this_year'), {
t('dateRange.previous_week'), label: t('dateRange.this_week'),
t('dateRange.previous_month'), key: 'This Week',
t('dateRange.previous_quarter'), },
t('dateRange.previous_year'), {
t('dateRange.custom'), label: t('dateRange.this_month'),
key: 'This Month',
},
{
label: t('dateRange.this_quarter'),
key: 'This Quarter',
},
{
label: t('dateRange.this_year'),
key: 'This Year',
},
{
label: t('dateRange.previous_week'),
key: 'Previous Week',
},
{
label: t('dateRange.previous_month'),
key: 'Previous Month',
},
{
label: t('dateRange.previous_quarter'),
key: 'Previous Quarter',
},
{
label: t('dateRange.previous_year'),
key: 'Previous Year',
},
{
label: t('dateRange.custom'),
key: 'Custom',
},
]) ])
const selectedRange = ref(t('dateRange.this_month')) const selectedRange = ref(dateRange[2])
let range = ref(new Date()) let range = ref(new Date())
let url = ref(null) let url = ref(null)
let siteURL = ref(null) let siteURL = ref(null)
@ -155,7 +189,9 @@ function getPreDate(type, time) {
} }
function onChangeDateRange() { function onChangeDateRange() {
switch (selectedRange.value) { let key = selectedRange.value.key
switch (key) {
case 'Today': case 'Today':
formData.from_date = moment().format('YYYY-MM-DD') formData.from_date = moment().format('YYYY-MM-DD')
formData.to_date = moment().format('YYYY-MM-DD') formData.to_date = moment().format('YYYY-MM-DD')

View File

@ -8,6 +8,10 @@
<BaseMultiselect <BaseMultiselect
v-model="selectedRange" v-model="selectedRange"
:options="dateRange" :options="dateRange"
value-prop="key"
track-by="key"
label="label"
object
@update:modelValue="onChangeDateRange" @update:modelValue="onChangeDateRange"
/> />
</BaseInputGroup> </BaseInputGroup>
@ -95,18 +99,49 @@ const { t } = useI18n()
globalStore.downloadReport = downloadReport globalStore.downloadReport = downloadReport
const dateRange = reactive([ const dateRange = reactive([
t('dateRange.today'), {
t('dateRange.this_week'), label: t('dateRange.today'),
t('dateRange.this_month'), key: 'Today',
t('dateRange.this_quarter'), },
t('dateRange.this_year'), {
t('dateRange.previous_week'), label: t('dateRange.this_week'),
t('dateRange.previous_month'), key: 'This Week',
t('dateRange.previous_quarter'), },
t('dateRange.previous_year'), {
t('dateRange.custom'), label: t('dateRange.this_month'),
key: 'This Month',
},
{
label: t('dateRange.this_quarter'),
key: 'This Quarter',
},
{
label: t('dateRange.this_year'),
key: 'This Year',
},
{
label: t('dateRange.previous_week'),
key: 'Previous Week',
},
{
label: t('dateRange.previous_month'),
key: 'Previous Month',
},
{
label: t('dateRange.previous_quarter'),
key: 'Previous Quarter',
},
{
label: t('dateRange.previous_year'),
key: 'Previous Year',
},
{
label: t('dateRange.custom'),
key: 'Custom',
},
]) ])
const selectedRange = ref(t('dateRange.this_month'))
const selectedRange = ref(dateRange[2])
let url = ref(null) let url = ref(null)
let siteURL = ref(null) let siteURL = ref(null)
let range = ref(new Date()) let range = ref(new Date())
@ -149,7 +184,9 @@ function getPreDate(type, time) {
} }
function onChangeDateRange() { function onChangeDateRange() {
switch (selectedRange.value) { let key = selectedRange.value.key
switch (key) {
case 'Today': case 'Today':
formData.from_date = moment().format('YYYY-MM-DD') formData.from_date = moment().format('YYYY-MM-DD')
formData.to_date = moment().format('YYYY-MM-DD') formData.to_date = moment().format('YYYY-MM-DD')

View File

@ -8,6 +8,10 @@
<BaseMultiselect <BaseMultiselect
v-model="selectedRange" v-model="selectedRange"
:options="dateRange" :options="dateRange"
value-prop="key"
track-by="key"
label="label"
object
@update:modelValue="onChangeDateRange" @update:modelValue="onChangeDateRange"
/> />
</BaseInputGroup> </BaseInputGroup>
@ -109,21 +113,51 @@ const globalStore = useGlobalStore()
globalStore.downloadReport = downloadReport globalStore.downloadReport = downloadReport
const dateRange = reactive([ const dateRange = reactive([
t('dateRange.today'), {
t('dateRange.this_week'), label: t('dateRange.today'),
t('dateRange.this_month'), key: 'Today',
t('dateRange.this_quarter'), },
t('dateRange.this_year'), {
t('dateRange.previous_week'), label: t('dateRange.this_week'),
t('dateRange.previous_month'), key: 'This Week',
t('dateRange.previous_quarter'), },
t('dateRange.previous_year'), {
t('dateRange.custom'), label: t('dateRange.this_month'),
key: 'This Month',
},
{
label: t('dateRange.this_quarter'),
key: 'This Quarter',
},
{
label: t('dateRange.this_year'),
key: 'This Year',
},
{
label: t('dateRange.previous_week'),
key: 'Previous Week',
},
{
label: t('dateRange.previous_month'),
key: 'Previous Month',
},
{
label: t('dateRange.previous_quarter'),
key: 'Previous Quarter',
},
{
label: t('dateRange.previous_year'),
key: 'Previous Year',
},
{
label: t('dateRange.custom'),
key: 'Custom',
},
]) ])
const selectedRange = ref(dateRange[2])
const reportTypes = ref(['By Customer', 'By Item']) const reportTypes = ref(['By Customer', 'By Item'])
const selectedType = ref('By Customer') const selectedType = ref('By Customer')
const selectedRange = ref(t('dateRange.this_month'))
let range = ref(new Date()) let range = ref(new Date())
let url = ref(null) let url = ref(null)
let customerSiteURL = ref(null) let customerSiteURL = ref(null)
@ -178,7 +212,9 @@ function getPreDate(type, time) {
} }
function onChangeDateRange() { function onChangeDateRange() {
switch (selectedRange.value) { let key = selectedRange.value.key
switch (key) {
case 'Today': case 'Today':
formData.from_date = moment().format('YYYY-MM-DD') formData.from_date = moment().format('YYYY-MM-DD')
formData.to_date = moment().format('YYYY-MM-DD') formData.to_date = moment().format('YYYY-MM-DD')

View File

@ -8,6 +8,10 @@
<BaseMultiselect <BaseMultiselect
v-model="selectedRange" v-model="selectedRange"
:options="dateRange" :options="dateRange"
value-prop="key"
track-by="key"
label="label"
object
@update:modelValue="onChangeDateRange" @update:modelValue="onChangeDateRange"
/> />
</BaseInputGroup> </BaseInputGroup>
@ -94,19 +98,49 @@ globalStore.downloadReport = downloadReport
const { t } = useI18n() const { t } = useI18n()
const dateRange = reactive([ const dateRange = reactive([
t('dateRange.today'), {
t('dateRange.this_week'), label: t('dateRange.today'),
t('dateRange.this_month'), key: 'Today',
t('dateRange.this_quarter'), },
t('dateRange.this_year'), {
t('dateRange.previous_week'), label: t('dateRange.this_week'),
t('dateRange.previous_month'), key: 'This Week',
t('dateRange.previous_quarter'), },
t('dateRange.previous_year'), {
t('dateRange.custom'), label: t('dateRange.this_month'),
key: 'This Month',
},
{
label: t('dateRange.this_quarter'),
key: 'This Quarter',
},
{
label: t('dateRange.this_year'),
key: 'This Year',
},
{
label: t('dateRange.previous_week'),
key: 'Previous Week',
},
{
label: t('dateRange.previous_month'),
key: 'Previous Month',
},
{
label: t('dateRange.previous_quarter'),
key: 'Previous Quarter',
},
{
label: t('dateRange.previous_year'),
key: 'Previous Year',
},
{
label: t('dateRange.custom'),
key: 'Custom',
},
]) ])
const selectedRange = ref(t('dateRange.this_month')) const selectedRange = ref(dateRange[2])
const formData = reactive({ const formData = reactive({
from_date: moment().startOf('month').format('YYYY-MM-DD').toString(), from_date: moment().startOf('month').format('YYYY-MM-DD').toString(),
@ -153,7 +187,9 @@ function getPreDate(type, time) {
} }
function onChangeDateRange() { function onChangeDateRange() {
switch (selectedRange.value) { let key = selectedRange.value.key
switch (key) {
case 'Today': case 'Today':
formData.from_date = moment().format('YYYY-MM-DD') formData.from_date = moment().format('YYYY-MM-DD')
formData.to_date = moment().format('YYYY-MM-DD') formData.to_date = moment().format('YYYY-MM-DD')

View File

@ -526,6 +526,7 @@
"cloned_successfully": "Recurring Invoice cloned successfully", "cloned_successfully": "Recurring Invoice cloned successfully",
"clone_invoice": "Clone Recurring Invoice", "clone_invoice": "Clone Recurring Invoice",
"confirm_clone": "This recurring invoice will be cloned into a new Recurring Invoice", "confirm_clone": "This recurring invoice will be cloned into a new Recurring Invoice",
"add_customer_email": "Please add an email address for this customer to send invoices automatically.",
"item": { "item": {
"title": "Item Title", "title": "Item Title",
"description": "Description", "description": "Description",