feat: chat-rct

feat/issue-23/chat-rct
Frédérik Benoist 2024-02-20 00:13:23 +01:00
parent c4f87d7b14
commit fe0d48703b
5 changed files with 268 additions and 91 deletions

View File

@ -126,6 +126,21 @@
"Note: Click on the button below to access DOTSOFT Back-office": "Note: Click on the button below to access DOTSOFT Back-office", "Note: Click on the button below to access DOTSOFT Back-office": "Note: Click on the button below to access DOTSOFT Back-office",
"Open Back-office": "Open Back-office", "Open Back-office": "Open Back-office",
"Mount drive": "Mount drive", "Mount drive": "Mount drive",
"Chat RCT": "Chat RCT",
"Your RCT Item": "Your RCT Item",
"Store Distributor": "Store Distributor",
"Possible actions to realize": "Possible actions to realize",
"Store where item is required": "Store where item is required",
"Specify an RCT": "Specify an RCT",
"Previous": "Previous",
"Next": "Next",
"Select distributor": "Select distributor",
"Select store": "Select store",
"Yes": "Yes",
"No": "No",
"Resend RCT": "Resend RCT ?",
"Summary": "Summary",
"The request has been processed successfully": "The request has been processed successfully",
"---------------------------": "---------------------------", "---------------------------": "---------------------------",
"UI Elements": "عناصر واجهة المستخدم", "UI Elements": "عناصر واجهة المستخدم",
"Forms & Tables": "النماذج والجداول", "Forms & Tables": "النماذج والجداول",

View File

@ -126,6 +126,21 @@
"Note: Click on the button below to access DOTSOFT Back-office": "Note: Click on the button below to access DOTSOFT Back-office", "Note: Click on the button below to access DOTSOFT Back-office": "Note: Click on the button below to access DOTSOFT Back-office",
"Open Back-office": "Open Back-office", "Open Back-office": "Open Back-office",
"Mount drive": "Mount drive", "Mount drive": "Mount drive",
"Chat RCT": "Chat RCT",
"Your RCT Item": "Your RCT Item",
"Store Distributor": "Store Distributor",
"Store where item is required": "Store where item is required",
"Possible actions to realize": "Possible actions to realize",
"Specify an RCT": "Specify an RCT",
"Previous": "Previous",
"Next": "Next",
"Select distributor": "Select distributor",
"Select store": "Select store",
"Yes": "Yes",
"No": "No",
"Resend RCT": "Resend RCT ?",
"Summary": "Summary",
"The request has been processed successfully": "The request has been processed successfully",
"---------------------------": "---------------------------", "---------------------------": "---------------------------",
"UI Elements": "UI Elements", "UI Elements": "UI Elements",
"Forms & Tables": "Forms & Tables", "Forms & Tables": "Forms & Tables",

View File

@ -127,6 +127,21 @@
"Note: Click on the button below to access DOTSOFT Back-office": "Note: Cliquez sur le bouton ci-dessous pour accéder au Back-office DOTSOFT", "Note: Click on the button below to access DOTSOFT Back-office": "Note: Cliquez sur le bouton ci-dessous pour accéder au Back-office DOTSOFT",
"Open Back-office": "Ouvrir DOTSOFT", "Open Back-office": "Ouvrir DOTSOFT",
"Mount drive": "Monter lecteur", "Mount drive": "Monter lecteur",
"Chat RCT": "Chat RCT",
"Your RCT Item": "RCT recherchée",
"Store Distributor": "Sélection distributeur",
"Store where item is required": "Sélection Boutique",
"Possible actions to realize": "Actions possibles à effectuer",
"Specify an RCT": "Saisissez la RCT",
"Previous": "Précédent",
"Next": "Suivant",
"Select distributor": "Selectionner un distributeur",
"Select store": "Selectionner une boutique",
"Yes": "Oui",
"No": "Non",
"Resend RCT": "Renvoyer RCT ?",
"Summary": "Résumé",
"The request has been processed successfully": "La demande a été traitée avec succès",
"---------------------------": "---------------------------", "---------------------------": "---------------------------",
"UI Elements": "ÉLÉMENTS DE L'UI", "UI Elements": "ÉLÉMENTS DE L'UI",
"Forms & Tables": "Formulaires et tableaux", "Forms & Tables": "Formulaires et tableaux",

View File

@ -1,13 +1,21 @@
export const useChatRctStore = defineStore('chatrct', { export const useChatRctStore = defineStore('chatrct', {
state: () => ({ state: () => ({
rct: 'XY10000-08-3A', ref_rct: null,
ref_r: null,
id_produit: 0, id_produit: 0,
distributor: null, distributor: null,
store: 4, distributor_list: [],
store: null,
store_list: [],
prompt_rct: '### Bonjour,\n Indiquez-moi la RCT sur laquelle vous souhaitez faire des recherches ...', prompt_rct: '### Bonjour,\n Indiquez-moi la RCT sur laquelle vous souhaitez faire des recherches ...',
prompt_distributor: '', prompt_distributor: '',
prompt_store: '', prompt_store: '',
output_actions: '',
loading: false, loading: false,
actions_lib: [],
actions_flag: false,
actions_proc: 'cache',
resend_data: 'No',
prompt_gen() { prompt_gen() {
return `${this.prompt_rct}\n${this.prompt_distributor}\n${this.prompt_store}` return `${this.prompt_rct}\n${this.prompt_distributor}\n${this.prompt_store}`
}, },
@ -16,11 +24,16 @@ export const useChatRctStore = defineStore('chatrct', {
async validateRct() { async validateRct() {
this.loading = true this.loading = true
const { data } = await useApi<any>(`/chatrct/rct/${this.rct}`) const { data } = await useApi<any>(`/chatrct/rct?itemId=${this.ref_rct}`)
if (data.value) { if (data.value) {
const jsonData = JSON.parse(data.value) const jsonData = JSON.parse(data.value)
this.id_produit = jsonData.response.id_produit if (jsonData.response.id_produit) {
this.id_produit = jsonData.response.id_produit
this.ref_r = jsonData.response.ref_r
this.distributor_list = jsonData.response.distributor_list
}
else { this.id_produit = 0 }
this.prompt_store = '' this.prompt_store = ''
this.prompt_distributor = '' this.prompt_distributor = ''
@ -29,43 +42,103 @@ export const useChatRctStore = defineStore('chatrct', {
this.loading = false this.loading = false
return true // TODO A VERIFIER SI REF N'EXISTE PAS return (this.id_produit > 0)
}, },
async validateDistributor() { async validateDistributor() {
this.loading = true this.loading = true
const { data } = await useApi<any>(`/chatrct/distributor/${this.distributor}?itemId=${this.rct}&produitId=${this.id_produit}`) const { data } = await useApi<any>(`/chatrct/distributor/${this.distributor}?itemId=${this.ref_rct}&produitId=${this.id_produit}`)
if (data.value) { if (data.value) {
const jsonData = JSON.parse(data.value) const jsonData = JSON.parse(data.value)
this.prompt_distributor = jsonData.response.lines.join('\n') this.prompt_distributor = jsonData.response.lines.join('\n')
this.store = null
this.store_list = jsonData.response.store_list
} }
this.loading = false this.loading = false
return true return true
}, },
setRct(rct: string) { async validateStore() {
this.rct = rct this.loading = true
const { data } = await useApi<any>(`/chatrct/store/${this.store}?distributorId=${this.distributor}&itemId=${this.ref_rct}&produitId=${this.id_produit}`)
if (data.value) {
const jsonData = JSON.parse(data.value)
this.prompt_store = jsonData.response.lines.join('\n')
this.actions_lib = jsonData.response.actions
this.actions_flag = jsonData.response.actions_flag
this.actions_proc = jsonData.response.actions_proc
}
this.loading = false
return true
},
async validateActions() {
this.loading = true
if (this.actions_proc === 'cache') {
const currentDate = new Date().toISOString().slice(0, 10).replace(/-/g, '')
const requestBodyCache = {
itemId: this.ref_r,
comment: `HDPOS Force Cache ${currentDate}`,
proc: this.actions_proc,
}
const { data } = await useApi<any>('/chatrct/rct/forceCache', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBodyCache),
})
if (data.value)
this.output_actions = data.value.output
}
else if (this.actions_proc === 'exception') {
const tomorrowDate = new Date(Date.now() + 86400000).toISOString().slice(0, 10).replace(/-/g, '')
const requestBodyException = {
id_produit: this.id_produit,
id_distrib: this.distributor,
fdate: tomorrowDate,
forcer_cache: 1,
modul_trait: 'HDPOS',
}
const { data } = await useApi<any>('/chatrct/rct/forceException', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBodyException),
})
if (data.value)
this.output_actions = data.value.output
}
this.loading = false
// Check for "ERREUR" at the beginning of the string
return !this.output_actions.startsWith('ERREUR')
}, },
clearState() { clearState() {
this.rct = '' this.ref_rct = null
this.distributor = null this.distributor = null
this.store = null this.store = null
this.resend_data = 'No'
}, },
getRct() { clearPrompts() {
return this.rct
},
getDistrib() {
return this.distributor
},
getStore() {
return this.store
},
ClearPrompts() {
this.prompt_rct = '### Bonjour,\n Indiquez-moi la RCT sur laquelle vous souhaitez faire des recherches ...' this.prompt_rct = '### Bonjour,\n Indiquez-moi la RCT sur laquelle vous souhaitez faire des recherches ...'
this.prompt_distributor = '' this.prompt_distributor = ''
this.prompt_store = '' this.prompt_store = ''
this.output_actions = ''
}, },
}, },
}) })

View File

@ -2,33 +2,24 @@
import { VForm } from 'vuetify/components/VForm' import { VForm } from 'vuetify/components/VForm'
import { useChatRctStore } from '@stores/chatrct.store' import { useChatRctStore } from '@stores/chatrct.store'
const { t } = useI18n()
const numberedSteps = [ const numberedSteps = [
{ {
title: 'Item', title: t('Item'),
subtitle: 'Your RCT Item', subtitle: t('Your RCT Item'),
}, },
{ {
title: 'Distributor', title: t('Distributor'),
subtitle: 'Store Distributor', subtitle: t('Store Distributor'),
}, },
{ {
title: 'Store', title: t('Store'),
subtitle: 'Store where item is sold', subtitle: t('Store where item is required'),
}, },
{ {
title: 'Actions', title: t('Actions'),
subtitle: 'Possible actions to realize', subtitle: t('Possible actions to realize'),
},
]
const distributors = [
{
name: 'IKKS',
id: 1,
},
{
name: 'XO',
id: 6,
}, },
] ]
@ -40,8 +31,13 @@ const refDistributorForm = ref<VForm>()
const refStoreForm = ref<VForm>() const refStoreForm = ref<VForm>()
const refActionsForm = ref<VForm>() const refActionsForm = ref<VForm>()
const isSnackbarActions = ref(false)
const store = useChatRctStore() const store = useChatRctStore()
store.clearState()
store.clearPrompts()
const validateRctForm = async () => { const validateRctForm = async () => {
const validRctForm = await refRctForm.value?.validate() const validRctForm = await refRctForm.value?.validate()
if (validRctForm && validRctForm.valid) { if (validRctForm && validRctForm.valid) {
@ -51,9 +47,7 @@ const validateRctForm = async () => {
currentStep.value++ currentStep.value++
isCurrentStepValid.value = true isCurrentStepValid.value = true
} }
else { else { isCurrentStepValid.value = false }
isCurrentStepValid.value = false
}
} }
} }
@ -66,41 +60,57 @@ const validateDistributorForm = async () => {
currentStep.value++ currentStep.value++
isCurrentStepValid.value = true isCurrentStepValid.value = true
} }
else { else { isCurrentStepValid.value = false }
isCurrentStepValid.value = false
}
} }
} }
const validateStoreForm = () => { const validateStoreForm = async () => {
refStoreForm.value?.validate().then(valid => { const validStoreForm = await refStoreForm.value?.validate()
if (valid) { if (validStoreForm && validStoreForm.valid) {
currentStep.value++ if (store.store_list && Array.isArray(store.store_list) && store.store_list.length > 0) {
isCurrentStepValid.value = true const valid = store.store_list.some((s: { id: any }) => s.id === store.store)
const validStore = await store.validateStore()
if (valid && validStore) {
currentStep.value++
isCurrentStepValid.value = true
}
else { isCurrentStepValid.value = false }
} }
else { else { isCurrentStepValid.value = false }
isCurrentStepValid.value = false }
}
})
} }
const validateActionsForm = () => { const validateActionsForm = async () => {
isCurrentStepValid.value = true const validActionsForm = await refActionsForm.value?.validate()
if (validActionsForm && validActionsForm.valid) {
if (store.resend_data === 'Yes') {
const valid = await store.validateActions()
// refActionsForm.value?.validate().then(valid => { if (valid) {
// if (valid.valid) currentStep.value++
// isCurrentStepValid.value = true isCurrentStepValid.value = true
// else isCurrentStepValid.value = false isSnackbarActions.value = true
// }) }
else { isCurrentStepValid.value = false }
}
else { isCurrentStepValid.value = false }
}
} }
const decrementStep = () => { const decrementStep = () => {
currentStep.value-- currentStep.value--
if (currentStep.value === 0) if (currentStep.value === 0) {
store.ClearPrompts() store.clearPrompts()
else if (currentStep.value === 1) }
else if (currentStep.value === 1) {
store.prompt_distributor = '' store.prompt_distributor = ''
}
else if (currentStep.value === 2) {
store.prompt_store = ''
store.output_actions = ''
}
} }
</script> </script>
@ -132,10 +142,10 @@ const decrementStep = () => {
<VRow> <VRow>
<VCol cols="12"> <VCol cols="12">
<h6 class="text-h6 font-weight-medium"> <h6 class="text-h6 font-weight-medium">
Item {{ $t('Item') }}
</h6> </h6>
<p class="mb-0"> <p class="mb-0">
Your RCT Item {{ $t('Your RCT Item') }}
</p> </p>
</VCol> </VCol>
@ -144,8 +154,8 @@ const decrementStep = () => {
md="6" md="6"
> >
<AppTextField <AppTextField
v-model="store.rct" v-model="store.ref_rct"
placeholder="BX10100" :placeholder="$t('Specify an RCT')"
:rules="[requiredValidator]" :rules="[requiredValidator]"
label="RCT" label="RCT"
/> />
@ -163,11 +173,11 @@ const decrementStep = () => {
start start
class="flip-in-rtl" class="flip-in-rtl"
/> />
Previous {{ $t('Previous') }}
</VBtn> </VBtn>
<VBtn type="submit"> <VBtn type="submit">
Next {{ $t('Next') }}
<VIcon <VIcon
icon="tabler-arrow-right" icon="tabler-arrow-right"
end end
@ -189,10 +199,10 @@ const decrementStep = () => {
<VRow> <VRow>
<VCol cols="12"> <VCol cols="12">
<h6 class="text-h6 font-weight-medium"> <h6 class="text-h6 font-weight-medium">
Distributor {{ $t('Distributor') }}
</h6> </h6>
<p class="mb-0"> <p class="mb-0">
Distributor where item are sold {{ $t('Store Distributor') }}
</p> </p>
</VCol> </VCol>
@ -202,12 +212,13 @@ const decrementStep = () => {
> >
<AppSelect <AppSelect
v-model="store.distributor" v-model="store.distributor"
:items="distributors" :items="store.distributor_list"
placeholder="Select Distributor" :placeholder="$t('Select distributor')"
:rules="[requiredValidator]" :rules="[requiredValidator]"
item-title="name" item-title="name"
item-value="id" item-value="id"
label="Distributor" :label="$t('Distributor')"
:return-object="false"
/> />
</VCol> </VCol>
<VCol cols="12"> <VCol cols="12">
@ -222,11 +233,11 @@ const decrementStep = () => {
start start
class="flip-in-rtl" class="flip-in-rtl"
/> />
Previous {{ $t('Previous') }}
</VBtn> </VBtn>
<VBtn type="submit"> <VBtn type="submit">
Next {{ $t('Next') }}
<VIcon <VIcon
icon="tabler-arrow-right" icon="tabler-arrow-right"
end end
@ -248,10 +259,10 @@ const decrementStep = () => {
<VRow> <VRow>
<VCol cols="12"> <VCol cols="12">
<h6 class="text-h6 font-weight-medium"> <h6 class="text-h6 font-weight-medium">
Store search {{ $t('Store') }}
</h6> </h6>
<p class="mb-0"> <p class="mb-0">
Possible store to search data on ... {{ $t('Store where item is required') }}
</p> </p>
</VCol> </VCol>
@ -259,11 +270,15 @@ const decrementStep = () => {
cols="12" cols="12"
md="6" md="6"
> >
<AppTextField <AppCombobox
v-model="store.store" v-model="store.store"
placeholder="Store ID" :items="store.store_list"
:placeholder="$t('Select store')"
:rules="[requiredValidator]" :rules="[requiredValidator]"
label="Store ID" item-title="name"
item-value="id"
:label="$t('Store')"
:return-object="false"
/> />
</VCol> </VCol>
@ -279,11 +294,11 @@ const decrementStep = () => {
start start
class="flip-in-rtl" class="flip-in-rtl"
/> />
Previous {{ $t('Previous') }}
</VBtn> </VBtn>
<VBtn type="submit"> <VBtn type="submit">
Next {{ $t('Next') }}
<VIcon <VIcon
icon="tabler-arrow-right" icon="tabler-arrow-right"
end end
@ -304,15 +319,42 @@ const decrementStep = () => {
> >
<VRow> <VRow>
<VCol cols="12"> <VCol cols="12">
<h6 class="text-h6 font-weight-medium"> <p
List of Actions v-for="(action, index) in store.actions_lib"
</h6> :key="index"
class="mb-0"
>
{{ action }}
</p>
</VCol> </VCol>
<VCol <VCol
v-if="store.actions_flag"
cols="12" cols="12"
md="6" sm="8"
/> >
<VRadioGroup
v-model="store.resend_data"
class="mb-3"
>
<template #label>
<div class="text-high-emphasis">
{{ $t('Resend RCT') }}
</div>
</template>
<VRadio
value="Yes"
:label="$t('Yes')"
class="ms-2"
/>
<VRadio
value="No"
:label="$t('No')"
class="ms-2"
/>
</VRadioGroup>
{{ store.output_actions }}
</VCol>
<VCol cols="12"> <VCol cols="12">
<div class="d-flex flex-wrap gap-4 justify-sm-space-between justify-center mt-8"> <div class="d-flex flex-wrap gap-4 justify-sm-space-between justify-center mt-8">
@ -326,19 +368,36 @@ const decrementStep = () => {
start start
class="flip-in-rtl" class="flip-in-rtl"
/> />
Previous {{ $t('Previous') }}
</VBtn> </VBtn>
<VBtn <VBtn
v-if="store.actions_flag"
color="success" color="success"
type="submit" type="submit"
> >
submit {{ $t('Submit') }}
</VBtn> </VBtn>
</div> </div>
</VCol> </VCol>
</VRow> </VRow>
</VForm> </VForm>
<!-- Snackbar Export -->
<VSnackbar
v-model="isSnackbarActions"
location="center"
>
{{ $t('The request has been processed successfully') }}
<template #actions>
<VBtn
color="error"
@click="isSnackbarActions = false"
>
{{ $t("Close") }}
</VBtn>
</template>
</VSnackbar>
</VWindowItem> </VWindowItem>
</VWindow> </VWindow>
</VCardText> </VCardText>