1c connect
This commit is contained in:
parent
25da63fd82
commit
9337050c5b
|
@ -54,6 +54,7 @@ jobs:
|
|||
echo VTK_KEYS=${{ secrets.VTK_KEYS }} > .env
|
||||
echo BX_API_CALL=${{ secrets.BX_API_CALL }} >> .env
|
||||
echo TG_TOKEN=${{ secrets.TG_TOKEN }} >> .env
|
||||
echo ODATA_AUTH=${{ secrets.ODATA_AUTH }} >> .env
|
||||
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} ci.svs-tech.pro
|
||||
docker compose down
|
||||
docker compose push
|
||||
|
|
|
@ -1,22 +1,31 @@
|
|||
<script setup lang="ts">
|
||||
const links = [[
|
||||
{
|
||||
label: 'Состояние вендотеков',
|
||||
icon: 'i-heroicons-credit-card',
|
||||
to: '/vtk'
|
||||
},
|
||||
{ label: 'Офис', to: '/vtk/office' },
|
||||
{ label: 'Парк', to: '/vtk/park' },
|
||||
],
|
||||
[
|
||||
{
|
||||
label: 'Вебхуки битрикса',
|
||||
icon: 'i-heroicons-clipboard-document-list',
|
||||
to: '/bx'
|
||||
},
|
||||
{ label: 'Gitea', to: '/bx/gitea' },
|
||||
{ label: 'Tg', to: '/bx/tg' },
|
||||
]]
|
||||
const links = [
|
||||
[
|
||||
{
|
||||
label: 'Состояние вендотеков',
|
||||
icon: 'i-heroicons-credit-card',
|
||||
to: '/vtk'
|
||||
},
|
||||
{ label: 'Офис', to: '/vtk/office' },
|
||||
{ label: 'Парк', to: '/vtk/park' },
|
||||
],
|
||||
[
|
||||
{
|
||||
label: 'Вебхуки битрикса',
|
||||
icon: 'i-heroicons-clipboard-document-list',
|
||||
to: '/bx'
|
||||
},
|
||||
{ label: 'Gitea', to: '/bx/gitea' },
|
||||
{ label: 'Tg', to: '/bx/tg' },
|
||||
],
|
||||
[
|
||||
{
|
||||
label: 'Инвентаризация',
|
||||
icon: 'i-heroicons-archive-box',
|
||||
to: '/inventory'
|
||||
}
|
||||
]
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -77,7 +77,7 @@ const retryStep = async (stepName: typeof steps[number]) => {
|
|||
}
|
||||
}
|
||||
|
||||
const copyOnClick = (e:Event) => {
|
||||
const copyOnClick = (e: Event) => {
|
||||
navigator.clipboard.writeText(e.currentTarget.textContent)
|
||||
}
|
||||
</script>
|
||||
|
@ -88,12 +88,14 @@ const copyOnClick = (e:Event) => {
|
|||
</template>
|
||||
<ol class="list-decimal pl-4">
|
||||
<li :class="isPassed('get_me')" v-if="isShown('get_me')">
|
||||
<p>Напишите вот этому боту - чтобы он мог слать вам уведомления <ULink :external="true" target="_blank" :to="`https://t.me/SVSnewsbot?start=service_monitoring`">@SVSnewsbot</ULink></p>
|
||||
<p>Напишите вот этому боту - чтобы он мог слать вам уведомления <ULink :external="true" target="_blank"
|
||||
:to="`https://t.me/SVSnewsbot?start=service_monitoring`">@SVSnewsbot</ULink>
|
||||
</p>
|
||||
<p>А теперь этому боту <ULink :external="true" target="_blank"
|
||||
:to="`https://t.me/${data.data.username}?start=service_monitoring`">@{{
|
||||
data.data.username }}
|
||||
</ULink>, чтобы узнать ваш айди (мы не сохраняем данные)
|
||||
</p>
|
||||
:to="`https://t.me/${data.data.username}?start=service_monitoring`">@{{
|
||||
data.data.username }}
|
||||
</ULink>, чтобы узнать ваш айди (мы не сохраняем данные)
|
||||
</p>
|
||||
</li>
|
||||
<li :class="isPassed('get_user_id')" v-if="isShown('get_user_id') && tg_data">
|
||||
Ваши данные пользователя. Нажмите зеленую кнопку, если все верно:
|
||||
|
@ -116,7 +118,8 @@ const copyOnClick = (e:Event) => {
|
|||
<li :class="isPassed('end_step')" v-if="shown_steps.includes('end_step')">
|
||||
<p>
|
||||
Вот ваша ссылка для формирования вебхука
|
||||
<code @click="copyOnClick">https://gi.svs-tech.pro/integration_tg/{{ selected_bx.id }}/{{ selected_tg }}</code>
|
||||
<code @click="copyOnClick">https://gi.svs-tech.pro/integration_tg/{{ selected_bx.id }}/{{ selected_tg
|
||||
}}</code>
|
||||
</p>
|
||||
<p>
|
||||
Теперь вам осталось <ULink to="https://crm.svs-tech.pro/devops/section/standard/" target="_blank">
|
||||
|
@ -132,12 +135,12 @@ const copyOnClick = (e:Event) => {
|
|||
<UButton color="orange" v-if="['get_user_id'].includes(step)" @click="retryStep(step)"
|
||||
:loading="loading" :disabled="disabled">Ошибка в данных
|
||||
</UButton>
|
||||
|
||||
<UButton v-if="step !== 'end_step'" :loading="loading" :disabled="disabled || (step == 'get_bx' && !selected_bx)"
|
||||
@click="nextStep">
|
||||
|
||||
<UButton v-if="step !== 'end_step'" :loading="loading"
|
||||
:disabled="disabled || (step == 'get_bx' && !selected_bx)" @click="nextStep">
|
||||
Сделано</UButton>
|
||||
|
||||
<p v-if="step=='end_step'">Вот и все!</p>
|
||||
<p v-if="step == 'end_step'">Вот и все!</p>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<script setup lang="ts">
|
||||
const config = useRuntimeConfig()
|
||||
const route = useRoute()
|
||||
interface APIBody {
|
||||
data: any[],
|
||||
status: 'success' | 'error'
|
||||
}
|
||||
|
||||
const { data, pending, error, status } = await useLazyFetch<APIBody>(`${config.public.apiBase}/api/nomen`, { server: false })
|
||||
const selected_nomen = ref()
|
||||
const selected_item = ref()
|
||||
|
||||
const loading = ref(true)
|
||||
|
||||
const child_cat_data = ref<any[]>([])
|
||||
const child_cat_pending = ref()
|
||||
|
||||
const item_data = ref()
|
||||
const item_pending = ref()
|
||||
|
||||
const onCategoryChange = async () => {
|
||||
const { data, pending } = await useFetch<APIBody>(`${config.public.apiBase}/api/nomen/${selected_nomen.value.id}`, { server: false })
|
||||
child_cat_data.value = data.value.data
|
||||
child_cat_pending.value = pending.value
|
||||
|
||||
item_data.value = undefined
|
||||
selected_item.value = undefined
|
||||
}
|
||||
|
||||
const onItemChange = async () => {
|
||||
const { data, pending } = await useFetch<APIBody>(`${config.public.apiBase}/api/nomen_item/${selected_item.value.id}`, { server: false })
|
||||
item_data.value = data.value.data
|
||||
item_pending.value = pending.value
|
||||
}
|
||||
|
||||
watch([pending, child_cat_pending], () => {
|
||||
loading.value = pending.value
|
||||
})
|
||||
onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<USelectMenu clear-search-on-close class="w-full my-2" placeholder="Категории номенклатуры" searchable
|
||||
searchable-placeholder="Искать..." :options="data?.data" size="lg" v-model="selected_nomen"
|
||||
@change="onCategoryChange" :loading="loading" />
|
||||
|
||||
<USelectMenu clear-search-on-close class="w-full my-2" :placeholder="`Элементы (${child_cat_data.length})`"
|
||||
searchable searchable-placeholder="Искать..." :options="child_cat_data" size="lg" v-model="selected_item"
|
||||
@change="onItemChange" :loading="loading" :disabled="!child_cat_data.length" />
|
||||
|
||||
<template v-if="item_data && Object.keys(item_data).length">
|
||||
<dl class="text-sm">
|
||||
<template v-for="item in ['Code', 'Description', 'Комментарий']">
|
||||
<dt>{{item}}</dt>
|
||||
<dd class="mb-2">{{ item_data[item] }}</dd>
|
||||
</template>
|
||||
</dl>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
69
main.py
69
main.py
|
@ -29,6 +29,7 @@ vtk = json.loads(os.getenv("VTK_KEYS"))
|
|||
vtk_org = {}
|
||||
BX_API_CALL = os.getenv("BX_API_CALL")
|
||||
TG_TOKEN = os.getenv("TG_TOKEN")
|
||||
ODATA_AUTH = os.getenv("ODATA_AUTH")
|
||||
|
||||
api_app = FastAPI(title="api app")
|
||||
|
||||
|
@ -118,7 +119,8 @@ async def get_tg_data():
|
|||
except Exception as e:
|
||||
logger.error(e)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
|
||||
@api_app.get("/bx/get_users")
|
||||
async def get_bx_users():
|
||||
try:
|
||||
|
@ -126,12 +128,75 @@ async def get_bx_users():
|
|||
res = requests.get(url)
|
||||
logger.info(url)
|
||||
data = res.json()
|
||||
return {"status": "success", "data": [v for v in data["result"] if v["UF_DEPARTMENT"][0] not in [15,16]]}
|
||||
return {
|
||||
"status": "success",
|
||||
"data": [
|
||||
v for v in data["result"] if v["UF_DEPARTMENT"][0] not in [15, 16]
|
||||
],
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@api_app.get("/nomen")
|
||||
async def get_parent_nomen():
|
||||
try:
|
||||
parent_ids = [
|
||||
"a6aadfe8-7e0f-11ee-ab5a-a47a2bd811cb",
|
||||
"8a988ff-0911-11ee-ab4e-e3e667c628bd",
|
||||
"a0fb742f-09f5-11ee-ab4e-e3e667c628bd",
|
||||
]
|
||||
url = "https://1c.svs-tech.pro/UNF/odata/standard.odata/Catalog_КатегорииНоменклатуры?$format=json"
|
||||
url += "&"
|
||||
url + " or ".join([f"Ref_Key eq guid'{p}'" for p in parent_ids])
|
||||
url += "&$select=Description,Ref_Key"
|
||||
res = requests.get(url, headers={"Authorization": ODATA_AUTH})
|
||||
data = res.json()
|
||||
return {
|
||||
"status": "success",
|
||||
"data": [
|
||||
{"label": d["Description"], "id": d["Ref_Key"]} for d in data["value"]
|
||||
],
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@api_app.get("/nomen/{nomen_id}")
|
||||
async def get_nomen_items(nomen_id):
|
||||
try:
|
||||
url = "https://1c.svs-tech.pro/UNF/odata/standard.odata/Catalog_Номенклатура?$format=json"
|
||||
url += "&$select=Ref_Key,Description"
|
||||
url += f"&$filter=КатегорияНоменклатуры_Key eq guid'{nomen_id}'"
|
||||
res = requests.get(url, headers={"Authorization": ODATA_AUTH})
|
||||
data = res.json()
|
||||
return {
|
||||
"status": "success",
|
||||
"data": [
|
||||
{"label": d["Description"], "id": d["Ref_Key"]} for d in data["value"]
|
||||
],
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@api_app.get("/nomen_item/{item_id}")
|
||||
async def get_nomen_items(item_id):
|
||||
try:
|
||||
url = f"https://1c.svs-tech.pro/UNF/odata/standard.odata/Catalog_Номенклатура(guid'{item_id}')?$format=json"
|
||||
res = requests.get(url, headers={"Authorization": ODATA_AUTH})
|
||||
data = res.json()
|
||||
return {
|
||||
"status": "success",
|
||||
"data": data,
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
app = FastAPI(title="main app")
|
||||
app.exception_handler(404)
|
||||
|
|
Loading…
Reference in New Issue