Merge pull request #938 from frappe/mergify/bp/main-hotfix/pr-937

fix: Forecasting Fixes (backport #937)
This commit is contained in:
Shariq Ansari 2025-06-16 17:49:48 +05:30 committed by GitHub
commit 88e5e5e7cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 195 additions and 94 deletions

View File

@ -94,7 +94,7 @@
{
"fieldname": "close_date",
"fieldtype": "Date",
"label": "Expected Closure Date"
"label": "Close Date"
},
{
"fieldname": "next_step",
@ -396,7 +396,7 @@
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-06-11 12:58:22.439045",
"modified": "2025-06-16 11:42:49.413483",
"modified_by": "Administrator",
"module": "FCRM",
"name": "CRM Deal",

View File

@ -151,10 +151,7 @@ declare module 'vue' {
ListIcon: typeof import('./src/components/Icons/ListIcon.vue')['default']
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default']
LucideCalendar: typeof import('~icons/lucide/calendar')['default']
LucideInfo: typeof import('~icons/lucide/info')['default']
LucidePlus: typeof import('~icons/lucide/plus')['default']
LucideSearch: typeof import('~icons/lucide/search')['default']
MarkAsDoneIcon: typeof import('./src/components/Icons/MarkAsDoneIcon.vue')['default']
MaximizeIcon: typeof import('./src/components/Icons/MaximizeIcon.vue')['default']
MenuIcon: typeof import('./src/components/Icons/MenuIcon.vue')['default']

View File

@ -13,7 +13,7 @@
"@tiptap/extension-paragraph": "^2.12.0",
"@twilio/voice-sdk": "^2.10.2",
"@vueuse/integrations": "^10.3.0",
"frappe-ui": "^0.1.145",
"frappe-ui": "^0.1.156",
"gemoji": "^8.1.0",
"lodash": "^4.17.21",
"mime": "^4.0.1",

View File

@ -806,5 +806,5 @@ const callActions = computed(() => {
)
})
defineExpose({ emailBox, all_activities })
defineExpose({ emailBox, all_activities, changeTabTo })
</script>

View File

@ -16,7 +16,9 @@
v-if="isManager() && !isMobileView"
@click="showDataFieldsModal = true"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button
label="Save"

View File

@ -30,20 +30,24 @@
<DragIcon class="h-3.5" />
<div>{{ __(element.label) }}</div>
</div>
<div class="flex cursor-pointer items-center gap-1">
<div class="flex cursor-pointer items-center gap-0.5">
<Button
variant="ghost"
class="!h-5 w-5 !p-1"
@click="editColumn(element)"
>
<EditIcon class="h-3.5" />
<template #icon>
<EditIcon class="h-3.5" />
</template>
</Button>
<Button
variant="ghost"
class="!h-5 w-5 !p-1"
@click="removeColumn(element)"
>
<FeatherIcon name="x" class="h-3.5" />
<template #icon>
<FeatherIcon name="x" class="h-3.5" />
</template>
</Button>
</div>
</div>
@ -215,7 +219,9 @@ const fields = computed(() => {
})
function addColumn(c) {
let align = ['Float', 'Int', 'Percent', 'Currency'].includes(c.type) ? 'right' : 'left'
let align = ['Float', 'Int', 'Percent', 'Currency'].includes(c.type)
? 'right'
: 'left'
let _column = {
label: c.label,
type: c.fieldtype,

View File

@ -58,7 +58,9 @@
variant="outline"
@click="showGridFieldsEditorModal = true"
>
<FeatherIcon name="settings" class="h-4 w-4 text-ink-gray-7" />
<template #icon>
<FeatherIcon name="settings" class="size-4 text-ink-gray-7" />
</template>
</Button>
</div>
</div>
@ -281,7 +283,9 @@
variant="outline"
@click="showRowList[index] = true"
>
<EditIcon class="h-4 w-4 text-ink-gray-7" />
<template #icon>
<EditIcon class="text-ink-gray-7" />
</template>
</Button>
</div>
<GridRowModal

View File

@ -15,10 +15,14 @@
class="w-7"
@click="openGridRowFieldsModal"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<FeatherIcon name="x" class="h-4 w-4" />
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>

View File

@ -31,7 +31,9 @@
class="opacity-0 hover:bg-surface-gray-4 group-hover:opacity-100"
@click="option.onClick"
>
<SuccessIcon />
<template #icon>
<SuccessIcon />
</template>
</Button>
</div>
</Tooltip>
@ -43,7 +45,9 @@
class="opacity-0 hover:bg-surface-gray-4 group-hover:opacity-100"
@click="toggleEditMode"
>
<EditIcon />
<template #icon>
<EditIcon />
</template>
</Button>
</div>
</Tooltip>

View File

@ -15,10 +15,14 @@
class="w-7"
@click="openQuickEntryModal"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<FeatherIcon name="x" class="h-4 w-4" />
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>

View File

@ -39,10 +39,14 @@
class="w-7"
@click="openCallLogModal"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<FeatherIcon name="x" class="h-4 w-4" />
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>

View File

@ -16,10 +16,14 @@
class="w-7"
@click="openQuickEntryModal"
>
<EditIcon class="w-4 h-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<FeatherIcon name="x" class="w-4 h-4" />
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>

View File

@ -15,10 +15,14 @@
class="w-7"
@click="openQuickEntryModal"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<FeatherIcon name="x" class="h-4 w-4" />
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>

View File

@ -15,10 +15,14 @@
class="w-7"
@click="openQuickEntryModal"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<FeatherIcon name="x" class="h-4 w-4" />
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>

View File

@ -15,10 +15,14 @@
class="w-7"
@click="openQuickEntryModal"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<FeatherIcon name="x" class="h-4 w-4" />
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>

View File

@ -15,10 +15,14 @@
class="w-7"
@click="openQuickEntryModal"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<FeatherIcon name="x" class="h-4 w-4" />
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>

View File

@ -15,10 +15,14 @@
class="w-7"
@click="openQuickEntryModal"
>
<EditIcon class="w-4 h-4" />
<template #icon>
<EditIcon />
</template>
</Button>
<Button variant="ghost" class="w-7" @click="show = false">
<FeatherIcon name="x" class="w-4 h-4" />
<template #icon>
<FeatherIcon name="x" class="size-4" />
</template>
</Button>
</div>
</div>

View File

@ -25,7 +25,9 @@
class="w-7 mr-2"
@click="showSidePanelModal = true"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon />
</template>
</Button>
</slot>
</template>
@ -248,6 +250,7 @@
"
:placeholder="field.placeholder"
placement="left-start"
:hideIcon="true"
@change="(v) => fieldChange(v, field)"
/>
</div>
@ -261,6 +264,7 @@
:formatter="(date) => getFormat(date, '', true)"
:placeholder="field.placeholder"
placement="left-start"
:hideIcon="true"
@change="(v) => fieldChange(v, field)"
/>
</div>

View File

@ -41,7 +41,9 @@
variant="ghost"
@click="section.editingLabel = true"
>
<EditIcon class="h-3.5" />
<template #icon>
<EditIcon class="h-3.5" />
</template>
</Button>
<Button
v-if="section.editable !== false"

View File

@ -23,7 +23,14 @@ export function useDocument(doctype, docname) {
toast.success(__('Document updated successfully'))
},
onError: (err) => {
toast.error(__('Error updating document'))
let errorMessage = __('Error updating document')
if (err.exc_type == 'MandatoryError') {
const fieldName = err.messages
.map((msg) => msg.split(': ')[2].trim())
.join(', ')
errorMessage = __('Mandatory field error: {0}', [fieldName])
}
toast.error(errorMessage)
console.error(err)
},
},

View File

@ -92,42 +92,50 @@
<Tooltip v-if="callEnabled" :text="__('Make a call')">
<div>
<Button class="h-7 w-7" @click="triggerCall">
<PhoneIcon class="h-4 w-4" />
<template #icon>
<PhoneIcon />
</template>
</Button>
</div>
</Tooltip>
<Tooltip :text="__('Send an email')">
<div>
<Button class="h-7 w-7">
<Email2Icon
class="h-4 w-4"
@click="
deal.data.email
? openEmailBox()
: toast.error(__('No email set'))
"
/>
<Button
class="h-7 w-7"
@click="
deal.data.email
? openEmailBox()
: toast.error(__('No email set'))
"
>
<template #icon>
<Email2Icon />
</template>
</Button>
</div>
</Tooltip>
<Tooltip :text="__('Go to website')">
<div>
<Button class="h-7 w-7">
<LinkIcon
class="h-4 w-4"
@click="
deal.data.website
? openWebsite(deal.data.website)
: toast.error(__('No website set'))
"
/>
<Button
class="h-7 w-7"
@click="
deal.data.website
? openWebsite(deal.data.website)
: toast.error(__('No website set'))
"
>
<template #icon>
<LinkIcon />
</template>
</Button>
</div>
</Tooltip>
<Tooltip :text="__('Attach a file')">
<div>
<Button class="size-7" @click="showFilesUploader = true">
<AttachmentIcon class="size-4" />
<template #icon>
<AttachmentIcon />
</template>
</Button>
</div>
</Tooltip>
@ -239,14 +247,18 @@
})
"
>
<ArrowUpRightIcon class="h-4 w-4" />
<template #icon>
<ArrowUpRightIcon class="h-4 w-4" />
</template>
</Button>
<Button variant="ghost" @click="toggle()">
<FeatherIcon
name="chevron-right"
class="h-4 w-4 text-ink-gray-9 transition-all duration-300 ease-in-out"
:class="{ 'rotate-90': opened }"
/>
<template #icon>
<FeatherIcon
name="chevron-right"
class="h-4 w-4 text-ink-gray-9 transition-all duration-300 ease-in-out"
:class="{ 'rotate-90': opened }"
/>
</template>
</Button>
</div>
</div>
@ -368,7 +380,7 @@ import {
toast,
} from 'frappe-ui'
import { useOnboarding } from 'frappe-ui/frappe'
import { ref, computed, h, onMounted, onBeforeUnmount } from 'vue'
import { ref, computed, h, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useActiveTabManager } from '@/composables/useActiveTabManager'
@ -730,7 +742,11 @@ async function deleteDeal(name) {
const activities = ref(null)
function openEmailBox() {
activities.value.emailBox.show = true
let currentTab = tabs.value[tabIndex.value]
if (!['Emails', 'Comments', 'Activities'].includes(currentTab.name)) {
activities.value.changeTabTo('emails')
}
nextTick(() => (activities.value.emailBox.show = true))
}
const { assignees, document, triggerOnChange } = useDocument(

View File

@ -142,42 +142,50 @@
: toast.error(__('No phone number set'))
"
>
<PhoneIcon class="h-4 w-4" />
<template #icon>
<PhoneIcon />
</template>
</Button>
</div>
</Tooltip>
<Tooltip :text="__('Send an email')">
<div>
<Button class="h-7 w-7">
<Email2Icon
class="h-4 w-4"
@click="
lead.data.email
? openEmailBox()
: toast.error(__('No email set'))
"
/>
<Button
class="h-7 w-7"
@click="
lead.data.email
? openEmailBox()
: toast.error(__('No email set'))
"
>
<template #icon>
<Email2Icon />
</template>
</Button>
</div>
</Tooltip>
<Tooltip :text="__('Go to website')">
<div>
<Button class="h-7 w-7">
<LinkIcon
class="h-4 w-4"
@click="
lead.data.website
? openWebsite(lead.data.website)
: toast.error(__('No website set'))
"
/>
<Button
class="h-7 w-7"
@click="
lead.data.website
? openWebsite(lead.data.website)
: toast.error(__('No website set'))
"
>
<template #icon>
<LinkIcon />
</template>
</Button>
</div>
</Tooltip>
<Tooltip :text="__('Attach a file')">
<div>
<Button class="h-7 w-7" @click="showFilesUploader = true">
<AttachmentIcon class="h-4 w-4" />
<template #icon>
<AttachmentIcon />
</template>
</Button>
</div>
</Tooltip>
@ -238,14 +246,18 @@
class="w-7"
@click="openQuickEntryModal"
>
<EditIcon class="h-4 w-4" />
<template #icon>
<EditIcon class="h-4 w-4" />
</template>
</Button>
<Button
variant="ghost"
class="w-7"
@click="showConvertToDealModal = false"
>
<FeatherIcon name="x" class="h-4 w-4" />
<template #icon>
<FeatherIcon name="x" class="h-4 w-4" />
</template>
</Button>
</div>
</div>
@ -386,7 +398,7 @@ import {
toast,
} from 'frappe-ui'
import { useOnboarding } from 'frappe-ui/frappe'
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { ref, reactive, computed, onMounted, watch, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useActiveTabManager } from '@/composables/useActiveTabManager'
@ -670,7 +682,11 @@ async function convertToDeal() {
const activities = ref(null)
function openEmailBox() {
activities.value.emailBox.show = true
let currentTab = tabs.value[tabIndex.value]
if (!['Emails', 'Comments', 'Activities'].includes(currentTab.name)) {
activities.value.changeTabTo('emails')
}
nextTick(() => (activities.value.emailBox.show = true))
}
const deal = reactive({})

View File

@ -1320,6 +1320,11 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.10.3.tgz#bf8efb3a580c75b86dce505a63f1ca7450a9aaea"
integrity sha512-AlxXXPCWIvw8hQUDFRskasj32iMNB8Sb19VgyFWqwvntGs2/UffNu8VdsVqxD2HpZ0g5rLYCYtSW4wigs9R3og==
"@tiptap/extension-heading@^2.12.0":
version "2.14.0"
resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.14.0.tgz#c5a9dc761712e9c87073ba8446548cbe4d403360"
integrity sha512-vM//6G3Ox3mxPv9eilhrDqylELCc8kEP1aQ4xUuOw7vCidjNtGggOa1ERnnpV2dCa2A9E8y4FHtN4Xh29stXQg==
"@tiptap/extension-highlight@^2.0.3":
version "2.10.3"
resolved "https://registry.yarnpkg.com/@tiptap/extension-highlight/-/extension-highlight-2.10.3.tgz#d94667d435d9dc556b06e7b764449dc2a6c18743"
@ -2565,10 +2570,10 @@ fraction.js@^4.3.7:
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
frappe-ui@^0.1.145:
version "0.1.145"
resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.1.145.tgz#19ec429badf85f3f2c45a85ec13c3c462ec11ee9"
integrity sha512-DnnSJREu/EpUAJGNFaXEUF3re0hQMmLBOX/MSW9AsQtnCJwXkO5VbH/dyVHAZjqdb9Do3CNQF33/HB4NibNI8Q==
frappe-ui@^0.1.156:
version "0.1.156"
resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.1.156.tgz#1a476aec80b0e0f72470f9dc3990bb023b2ebb09"
integrity sha512-JsIODLL7YYFhKSYfWJJ9M1+VMmj8M0xZ1D5M7Cx0c+OWg5Qm0xda1592Tr+om1a7u0zWcfjuQnW9mHN1lW5HIA==
dependencies:
"@floating-ui/vue" "^1.1.6"
"@headlessui/vue" "^1.7.14"
@ -2579,6 +2584,7 @@ frappe-ui@^0.1.145:
"@tiptap/extension-code-block" "^2.11.9"
"@tiptap/extension-code-block-lowlight" "^2.11.5"
"@tiptap/extension-color" "^2.0.3"
"@tiptap/extension-heading" "^2.12.0"
"@tiptap/extension-highlight" "^2.0.3"
"@tiptap/extension-image" "^2.0.3"
"@tiptap/extension-link" "^2.0.3"
@ -2599,6 +2605,7 @@ frappe-ui@^0.1.145:
dayjs "^1.11.13"
echarts "^5.6.0"
feather-icons "^4.28.0"
highlight.js "^11.11.1"
idb-keyval "^6.2.0"
lowlight "^3.3.0"
lucide-static "^0.479.0"
@ -2806,7 +2813,7 @@ hasown@^2.0.1, hasown@^2.0.2:
dependencies:
function-bind "^1.1.2"
highlight.js@~11.11.0:
highlight.js@^11.11.1, highlight.js@~11.11.0:
version "11.11.1"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.11.1.tgz#fca06fa0e5aeecf6c4d437239135fabc15213585"
integrity sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==