ui: add B2B olmayan stok (orphans) page

This commit is contained in:
M_Kececi
2026-06-25 14:14:23 +03:00
parent 52b39725ec
commit dfad548963
19 changed files with 594 additions and 71 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
<div class="col-12 col-md">
<div class="text-h6">Marka Sınıflandırma</div>
<div class="text-caption text-grey-7">
Kaynak: BAGGI_V3 `cdItemAttribute` (ItemTypeCode=1, AttributeTypeCode=10)
Kaynak: NEBIM_V3 marka bilgileri
</div>
</div>
+2 -2
View File
@@ -371,7 +371,7 @@ const importKeyFieldLabels = [
const importFieldMap = {
AKTIF: 'is_active',
'HESAP AKTIF': 'calc_enabled',
'PG YAYIN': 'publish_postgres',
'B2B YAYIN': 'publish_postgres',
'NEBIM YAYIN': 'publish_nebim',
'TRY TOPTAN YUVARLAMA': 'try_wholesale_step',
'TRY PERAKENDE MODU': 'try_retail_mode',
@@ -454,7 +454,7 @@ const columns = [
col('brand_group', 'MARKA GRUBU', 'brand_group', 76, { classes: 'ps-col', headerClasses: 'ps-col' }),
col('anchor_mode', 'ANCHOR MODE', 'anchor_mode', 66, { classes: 'ps-col', headerClasses: 'ps-col' }),
col('calc_enabled', 'HESAP AKTIF', 'calc_enabled', 66, { classes: 'ps-col', headerClasses: 'ps-col' }),
col('publish_postgres', 'PG YAYIN', 'publish_postgres', 62, { classes: 'ps-col', headerClasses: 'ps-col' }),
col('publish_postgres', 'B2B YAYIN', 'publish_postgres', 62, { classes: 'ps-col', headerClasses: 'ps-col' }),
col('publish_nebim', 'NEBIM YAYIN', 'publish_nebim', 66, { classes: 'ps-col', headerClasses: 'ps-col' }),
col('try_wholesale_step', 'TRY TOPTAN YUVARLAMA', 'try_wholesale_step', 76, { align: 'right', classes: 'try-col', headerClasses: 'try-col' }),
+66 -11
View File
@@ -71,6 +71,31 @@
</q-btn>
</div>
</div>
<div class="col-fixed kategori">
<div class="filter-head">
<span>KATEGORI</span>
<q-btn dense flat round size="sm" icon="filter_list" :color="activeFilterCount('kategori') ? 'primary' : 'grey-8'">
<q-badge v-if="activeFilterCount('kategori')" floating color="primary">{{ activeFilterCount('kategori') }}</q-badge>
<q-menu class="column-filter-menu" anchor="bottom left" self="top left">
<div class="q-pa-sm">
<q-input v-model="filterSearch.kategori" dense outlined clearable placeholder="Ara" autofocus />
<div class="row q-gutter-xs q-mt-sm">
<q-btn dense flat size="sm" label="Tumu" @click="selectAllFilter('kategori')" />
<q-btn dense flat size="sm" label="Temizle" @click="clearFilter('kategori')" />
</div>
<q-separator class="q-my-sm" />
<q-option-group
v-model="columnFilters.kategori"
:options="filteredFilterOptions('kategori')"
type="checkbox"
dense
class="column-filter-options"
/>
</div>
</q-menu>
</q-btn>
</div>
</div>
<div class="col-fixed renk">
<div class="filter-head">
<span>RENK</span>
@@ -214,6 +239,7 @@
>
<div class="sub-col model">{{ row.product_code || '-' }}</div>
<div class="sub-col desc">{{ row.product_description || '-' }}</div>
<div class="sub-col kategori">{{ row.kategori || '-' }}</div>
<div class="sub-col renk">
<div class="renk-kodu">{{ variantCode(row) }}</div>
<div class="renk-aciklama">{{ row.color_title || '-' }}</div>
@@ -287,6 +313,7 @@ const errorMessage = ref('')
const columnFilters = ref({
model: [],
desc: [],
kategori: [],
renk: [],
ana: [],
alt: [],
@@ -295,6 +322,7 @@ const columnFilters = ref({
const filterSearch = ref({
model: '',
desc: '',
kategori: '',
renk: '',
ana: '',
alt: '',
@@ -341,6 +369,7 @@ const productGroups = computed(() => displayRows.value)
const filterOptions = computed(() => ({
model: uniqueOptions(rows.value.map(row => row.product_code)),
desc: uniqueOptions(rows.value.map(row => row.product_description)),
kategori: uniqueOptions(rows.value.map(row => row.kategori)),
renk: uniqueOptions(rows.value.map(row => variantCode(row))),
ana: uniqueOptions(rows.value.map(row => row.urun_ana_grubu)),
alt: uniqueOptions(rows.value.map(row => row.urun_alt_grubu)),
@@ -386,6 +415,7 @@ function clearFilter (key) {
function rowPassesFilters (row) {
return filterMatch('model', row.product_code) &&
filterMatch('desc', row.product_description) &&
filterMatch('kategori', row.kategori) &&
filterMatch('renk', variantCode(row)) &&
filterMatch('ana', row.urun_ana_grubu) &&
filterMatch('alt', row.urun_alt_grubu) &&
@@ -548,7 +578,7 @@ function mapRowSizesToSchema (row) {
const rawSizeLabels = sizeEntries.map(([rawSize]) => normalizeBedenLabel(rawSize))
const schemaMap = getSchemaMap()
const grpKey = detectRowGroupKey(row, rawSizeLabels)
const schema = grpKey && schemaMap?.[grpKey] ? schemaMap[grpKey] : null
const schema = pickSchemaForRow(schemaMap, grpKey, rawSizeLabels)
const schemaLabelMap = normalizedSchemaLabelMap(schema)
const mapped = {}
@@ -569,6 +599,26 @@ function mapRowSizesToSchema (row) {
return { grpKey, schema, mapped }
}
function pickSchemaForRow (schemaMap, grpKey, rawSizeLabels) {
const primary = grpKey && schemaMap?.[grpKey] ? schemaMap[grpKey] : null
const rawSet = new Set((rawSizeLabels || []).map(v => normalizeBedenLabel(v)).filter(Boolean))
if (!rawSet.size) return primary
const primarySet = new Set((primary?.values || []).map(v => normalizeBedenLabel(v)))
if ([...rawSet].some(v => primarySet.has(v))) return primary
let best = primary
let bestScore = 0
for (const schema of Object.values(schemaMap || {})) {
const schemaSet = new Set((schema?.values || []).map(v => normalizeBedenLabel(v)))
const score = [...rawSet].reduce((sum, v) => sum + (schemaSet.has(v) ? 1 : 0), 0)
if (score > bestScore) {
best = schema
bestScore = score
}
}
return best
}
function formatQty (value) {
const n = Number(value || 0)
if (!Number.isFinite(n) || n === 0) return ''
@@ -605,7 +655,7 @@ function escapeHtml (value) {
function exportVisibleExcel () {
const groups = schemaRows.value
const rowSpan = Math.max(groups.length, 1)
const leftHeaders = ['MODEL', 'DESC', 'RENK', 'URUN ANA GRUBU', 'URUN ALT GRUBU', 'MARKA']
const leftHeaders = ['MODEL', 'DESC', 'KATEGORI', 'RENK', 'URUN ANA GRUBU', 'URUN ALT GRUBU', 'MARKA']
const headerRows = (groups.length ? groups : [{ key: 'tak', title: 'TAKIM ELBISE', values: [] }]).map((grp, index) => {
const left = index === 0
? leftHeaders.map(h => `<th rowspan="${rowSpan}">${escapeHtml(h)}</th>`).join('')
@@ -631,6 +681,7 @@ function exportVisibleExcel () {
return `<tr>
<td>${escapeHtml(row.product_code || '')}</td>
<td>${escapeHtml(row.product_description || '')}</td>
<td>${escapeHtml(row.kategori || '')}</td>
<td>${escapeHtml(variantCode(row))}</td>
<td>${escapeHtml(row.urun_ana_grubu || '')}</td>
<td>${escapeHtml(row.urun_alt_grubu || '')}</td>
@@ -665,6 +716,7 @@ onMounted(async () => {
--psq-sticky-offset: 12px;
--grp-title-w: 90px;
--col-desc: var(--col-aciklama);
--col-kategori-series: 86px;
--col-marka-series: var(--col-marka, 90px);
--psq-header-h: var(--grid-header-h);
--series-total-w: 76px;
@@ -681,6 +733,7 @@ onMounted(async () => {
grid-template-columns:
var(--col-model)
var(--col-desc)
var(--col-kategori-series)
var(--col-renk)
var(--col-ana)
var(--col-alt)
@@ -774,11 +827,11 @@ onMounted(async () => {
}
.total-header-cell {
grid-column: 8 / 9;
grid-column: 9 / 10;
}
.series-header-cell {
grid-column: 9 / 10;
grid-column: 10 / 11;
}
.series-flat-row {
@@ -816,12 +869,14 @@ onMounted(async () => {
.series-flat-row .sub-col.model { grid-column: 1; }
.series-flat-row .sub-col.desc { grid-column: 2; }
.series-flat-row .sub-col.renk { grid-column: 3; }
.series-flat-row .sub-col.ana { grid-column: 4; }
.series-flat-row .sub-col.alt { grid-column: 5; }
.series-flat-row .sub-col.marka { grid-column: 6; }
.series-flat-row .sub-col.kategori { grid-column: 3; }
.series-flat-row .sub-col.renk { grid-column: 4; }
.series-flat-row .sub-col.ana { grid-column: 5; }
.series-flat-row .sub-col.alt { grid-column: 6; }
.series-flat-row .sub-col.marka { grid-column: 7; }
.series-flat-row .sub-col.model,
.series-flat-row .sub-col.kategori,
.series-flat-row .sub-col.renk,
.series-flat-row .sub-col.ana,
.series-flat-row .sub-col.alt,
@@ -851,7 +906,7 @@ onMounted(async () => {
}
.flat-size-cells {
grid-column: 7;
grid-column: 8;
display: grid;
grid-auto-flow: column;
grid-auto-columns: var(--beden-w);
@@ -893,7 +948,7 @@ onMounted(async () => {
}
.total-cell {
grid-column: 8;
grid-column: 9;
display: flex;
align-items: center;
justify-content: flex-end;
@@ -906,7 +961,7 @@ onMounted(async () => {
}
.series-select-cell {
grid-column: 9 / 10;
grid-column: 10 / 11;
display: flex;
flex-direction: column;
justify-content: center;
+66 -11
View File
@@ -70,6 +70,31 @@
</q-btn>
</div>
</div>
<div class="col-fixed kategori">
<div class="filter-head">
<span>KATEGORI</span>
<q-btn dense flat round size="sm" icon="filter_list" :color="activeFilterCount('kategori') ? 'primary' : 'grey-8'">
<q-badge v-if="activeFilterCount('kategori')" floating color="primary">{{ activeFilterCount('kategori') }}</q-badge>
<q-menu class="column-filter-menu" anchor="bottom left" self="top left">
<div class="q-pa-sm">
<q-input v-model="filterSearch.kategori" dense outlined clearable placeholder="Ara" autofocus />
<div class="row q-gutter-xs q-mt-sm">
<q-btn dense flat size="sm" label="Tumu" @click="selectAllFilter('kategori')" />
<q-btn dense flat size="sm" label="Temizle" @click="clearFilter('kategori')" />
</div>
<q-separator class="q-my-sm" />
<q-option-group
v-model="columnFilters.kategori"
:options="filteredFilterOptions('kategori')"
type="checkbox"
dense
class="column-filter-options"
/>
</div>
</q-menu>
</q-btn>
</div>
</div>
<div class="col-fixed renk">
<div class="filter-head">
<span>RENK</span>
@@ -212,6 +237,7 @@
>
<div class="sub-col model">{{ row.product_code || '-' }}</div>
<div class="sub-col desc">{{ row.product_description || '-' }}</div>
<div class="sub-col kategori">{{ row.kategori || '-' }}</div>
<div class="sub-col renk">
<div class="renk-kodu">{{ variantCode(row) }}</div>
<div class="renk-aciklama">{{ row.color_title || '-' }}</div>
@@ -273,6 +299,7 @@ const errorMessage = ref('')
const columnFilters = ref({
model: [],
desc: [],
kategori: [],
renk: [],
ana: [],
alt: [],
@@ -281,6 +308,7 @@ const columnFilters = ref({
const filterSearch = ref({
model: '',
desc: '',
kategori: '',
renk: '',
ana: '',
alt: '',
@@ -325,6 +353,7 @@ const productGroups = computed(() => displayRows.value)
const filterOptions = computed(() => ({
model: uniqueOptions(rows.value.map(row => row.product_code)),
desc: uniqueOptions(rows.value.map(row => row.product_description)),
kategori: uniqueOptions(rows.value.map(row => row.kategori)),
renk: uniqueOptions(rows.value.map(row => variantCode(row))),
ana: uniqueOptions(rows.value.map(row => row.urun_ana_grubu)),
alt: uniqueOptions(rows.value.map(row => row.urun_alt_grubu)),
@@ -370,6 +399,7 @@ function clearFilter (key) {
function rowPassesFilters (row) {
return filterMatch('model', row.product_code) &&
filterMatch('desc', row.product_description) &&
filterMatch('kategori', row.kategori) &&
filterMatch('renk', variantCode(row)) &&
filterMatch('ana', row.urun_ana_grubu) &&
filterMatch('alt', row.urun_alt_grubu) &&
@@ -492,7 +522,7 @@ function mapRowSizesToSchema (row) {
const rawSizeLabels = sizeEntries.map(([rawSize]) => normalizeBedenLabel(rawSize))
const schemaMap = getSchemaMap()
const grpKey = detectRowGroupKey(row, rawSizeLabels)
const schema = grpKey && schemaMap?.[grpKey] ? schemaMap[grpKey] : null
const schema = pickSchemaForRow(schemaMap, grpKey, rawSizeLabels)
const schemaLabelMap = normalizedSchemaLabelMap(schema)
const mapped = {}
@@ -513,6 +543,26 @@ function mapRowSizesToSchema (row) {
return { grpKey, schema, mapped }
}
function pickSchemaForRow (schemaMap, grpKey, rawSizeLabels) {
const primary = grpKey && schemaMap?.[grpKey] ? schemaMap[grpKey] : null
const rawSet = new Set((rawSizeLabels || []).map(v => normalizeBedenLabel(v)).filter(Boolean))
if (!rawSet.size) return primary
const primarySet = new Set((primary?.values || []).map(v => normalizeBedenLabel(v)))
if ([...rawSet].some(v => primarySet.has(v))) return primary
let best = primary
let bestScore = 0
for (const schema of Object.values(schemaMap || {})) {
const schemaSet = new Set((schema?.values || []).map(v => normalizeBedenLabel(v)))
const score = [...rawSet].reduce((sum, v) => sum + (schemaSet.has(v) ? 1 : 0), 0)
if (score > bestScore) {
best = schema
bestScore = score
}
}
return best
}
function formatQty (value) {
const n = Number(value || 0)
if (!Number.isFinite(n) || n === 0) return ''
@@ -544,7 +594,7 @@ function csvEscape (v) {
}
function exportVisibleExcel () {
const cols = ['MODEL', 'DESC', 'RENK', 'URUN ANA GRUBU', 'URUN ALT GRUBU', 'MARKA']
const cols = ['MODEL', 'DESC', 'KATEGORI', 'RENK', 'URUN ANA GRUBU', 'URUN ALT GRUBU', 'MARKA']
const sizeCols = schemaRows.value.flatMap(grp => paddedSchemaValues(grp).map(v => (v.ghost ? '' : v.value))).filter(Boolean)
cols.push(...sizeCols)
cols.push('TOPLAM', 'SERI', 'UYARI')
@@ -559,6 +609,7 @@ function exportVisibleExcel () {
lines.push([
row.product_code || '',
row.product_description || '',
row.kategori || '',
variantCode(row),
row.urun_ana_grubu || '',
row.urun_alt_grubu || '',
@@ -590,6 +641,7 @@ onMounted(() => reload())
--psq-sticky-offset: 12px;
--grp-title-w: 90px;
--col-desc: var(--col-aciklama);
--col-kategori-series: 86px;
--col-marka-series: var(--col-marka, 90px);
--psq-header-h: var(--grid-header-h);
--series-total-w: 76px;
@@ -606,6 +658,7 @@ onMounted(() => reload())
grid-template-columns:
var(--col-model)
var(--col-desc)
var(--col-kategori-series)
var(--col-renk)
var(--col-ana)
var(--col-alt)
@@ -699,11 +752,11 @@ onMounted(() => reload())
}
.total-header-cell {
grid-column: 8 / 9;
grid-column: 9 / 10;
}
.series-header-cell {
grid-column: 9 / 10;
grid-column: 10 / 11;
}
.series-flat-row {
@@ -741,12 +794,14 @@ onMounted(() => reload())
.series-flat-row .sub-col.model { grid-column: 1; }
.series-flat-row .sub-col.desc { grid-column: 2; }
.series-flat-row .sub-col.renk { grid-column: 3; }
.series-flat-row .sub-col.ana { grid-column: 4; }
.series-flat-row .sub-col.alt { grid-column: 5; }
.series-flat-row .sub-col.marka { grid-column: 6; }
.series-flat-row .sub-col.kategori { grid-column: 3; }
.series-flat-row .sub-col.renk { grid-column: 4; }
.series-flat-row .sub-col.ana { grid-column: 5; }
.series-flat-row .sub-col.alt { grid-column: 6; }
.series-flat-row .sub-col.marka { grid-column: 7; }
.series-flat-row .sub-col.model,
.series-flat-row .sub-col.kategori,
.series-flat-row .sub-col.renk,
.series-flat-row .sub-col.ana,
.series-flat-row .sub-col.alt,
@@ -776,7 +831,7 @@ onMounted(() => reload())
}
.flat-size-cells {
grid-column: 7;
grid-column: 8;
display: grid;
grid-auto-flow: column;
grid-auto-columns: var(--beden-w);
@@ -818,7 +873,7 @@ onMounted(() => reload())
}
.total-cell {
grid-column: 8;
grid-column: 9;
display: flex;
align-items: center;
justify-content: flex-end;
@@ -831,7 +886,7 @@ onMounted(() => reload())
}
.series-select-cell {
grid-column: 9 / 10;
grid-column: 10 / 11;
display: flex;
flex-direction: column;
justify-content: center;
@@ -840,7 +840,7 @@
<div>
<div class="text-subtitle1 text-weight-bold">Fiyat Kontrolu (Satinalma Ortalama)</div>
<div class="text-caption text-grey-7">
BAGGI_V3 satinalma gecmisindeki son 10 USD ortalamasindan %10'dan fazla sapan tum satirlar.
NEBIM_V3 satinalma gecmisindeki son 10 USD ortalamasindan %10'dan fazla sapan tum satirlar.
</div>
</div>
<q-badge color="primary" outline>{{ priceDeviationRows.length }} satir</q-badge>
@@ -1105,6 +1105,7 @@ import { onBeforeRouteLeave, useRoute, useRouter } from 'vue-router'
import { usePermission } from 'src/composables/usePermission'
import { get, post, download, extractApiErrorDetail } from 'src/services/api'
import { createTraceId, slog } from 'src/utils/slog'
import { formatDataSourceLabel } from 'src/utils/formatters'
const route = useRoute()
const router = useRouter()
@@ -2334,8 +2335,8 @@ function resolveHistorySourceType (item, forcedType = '') {
}
function resolveHistorySourceLabel (sourceType) {
if (sourceType === 'purchase') return 'BAGGI_V3'
if (sourceType === 'recipe') return 'URETIM'
if (sourceType === 'purchase') return formatDataSourceLabel('BAGGI_V3')
if (sourceType === 'recipe') return formatDataSourceLabel('URETIM')
return 'HISTORY'
}
@@ -4770,7 +4771,7 @@ async function confirmBrPriceDeviationIfNeeded () {
html: true,
message: `
<div style="margin-bottom:10px;">
Bazı satırlarda girilen fiyat, BAGGI_V3 satınalma geçmişindeki <b>son 10</b> kaydın USD ortalamasından <b>%10</b>'dan fazla sapıyor.
Bazı satırlarda girilen fiyat, NEBIM_V3 satınalma geçmişindeki <b>son 10</b> kaydın USD ortalamasından <b>%10</b>'dan fazla sapıyor.
</div>
<div style="max-height: 360px; overflow:auto; border:1px solid #e0e0e0; border-radius:6px;">
<table style="width:100%; border-collapse:collapse; font-size:13px;">
@@ -5,7 +5,7 @@
<div class="col">
<div class="text-h6">Maliyet Parca Eslestirme</div>
<div class="text-caption text-grey-7">
V3 Urun Ilk Grubu (42. ozellik) + Urun Ana/Alt Grup + URETIM Parca Bolum + Hammadde Turleri eslestirmesi (URETIM mk_ tablolarinda tutulur)
NEBIM_V3 urun gruplari + TEDARIK URETIM PROGRAMI parca bolum + hammadde turleri eslestirmesi
</div>
</div>
+5 -9
View File
@@ -207,6 +207,7 @@ import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useQuasar } from 'quasar'
import { usePermission } from 'src/composables/usePermission'
import { useTranslationStore } from 'src/stores/translationStore'
import { formatDataSourceLabel } from 'src/utils/formatters'
const $q = useQuasar()
const store = useTranslationStore()
@@ -231,15 +232,10 @@ const tablePagination = ref({
let filterReloadTimer = null
const sourceTypeOptions = [
{ label: 'dummy', value: 'dummy' },
{ label: 'postgre', value: 'postgre' },
{ label: 'mssql', value: 'mssql' }
{ label: formatDataSourceLabel('dummy'), value: 'dummy' },
{ label: formatDataSourceLabel('postgre'), value: 'postgre' },
{ label: formatDataSourceLabel('mssql'), value: 'mssql' }
]
const sourceTypeLabelMap = {
dummy: 'UI',
postgre: 'PostgreSQL',
mssql: 'MSSQL'
}
const columns = [
{ name: 'actions', label: 'Güncelle', field: 'actions', align: 'left' },
@@ -413,7 +409,7 @@ function cellClass (key, field) {
function sourceTypeLabel (key) {
const val = String(rowDraft(key).source_type || 'dummy').toLowerCase()
return sourceTypeLabelMap[val] || val || '-'
return formatDataSourceLabel(val)
}
function toggleSelected (key, checked) {
+24 -24
View File
@@ -3,9 +3,8 @@
v-if="canReadUser"
class="q-pa-md user-sync-page"
>
<div class="row items-center justify-between q-mb-md">
<div class="text-h6 text-primary">👤 Kullanıcı Yönetimi</div>
<div class="text-h6 text-primary">Kullanici Yonetimi</div>
<q-btn
v-if="canUpdateUser"
color="primary"
@@ -20,11 +19,10 @@
<q-separator />
<div class="row q-col-gutter-md q-mt-md">
<!-- 🔹 PostgreSQL Kullanıcıları -->
<div class="col-6">
<q-card flat bordered>
<q-card-section class="bg-primary text-white text-subtitle1">
PostgreSQL Kullanıcıları
B2B Kullanicilari
</q-card-section>
<q-table
@@ -36,7 +34,7 @@
bordered
separator="cell"
>
<template v-slot:body-cell-sync_status="props">
<template #body-cell-sync_status="props">
<q-td :props="props">
<q-chip
:color="statusColor(props.row.sync_status)"
@@ -48,23 +46,27 @@
</q-td>
</template>
<template v-slot:body-cell-actions="props">
<template #body-cell-actions="props">
<q-td :props="props">
<q-btn
v-if="canUpdateUser"
dense flat icon="link"
dense
flat
icon="link"
color="primary"
size="sm"
@click="openMapDialog(props.row)"
:disable="store.loading || !canUpdateUser"
@click="openMapDialog(props.row)"
/>
<q-btn
v-if="canUpdateUser"
dense flat icon="link_off"
dense
flat
icon="link_off"
color="negative"
size="sm"
@click="store.unmap(props.row.id)"
:disable="store.loading || !props.row.mssql_username || !canUpdateUser"
@click="store.unmap(props.row.id)"
/>
</q-td>
</template>
@@ -72,11 +74,10 @@
</q-card>
</div>
<!-- 🔸 MSSQL Kullanıcıları -->
<div class="col-6">
<q-card flat bordered>
<q-card-section class="bg-secondary text-white text-subtitle1">
MSSQL Kullanıcıları
NEBIM_V3 Kullanicilari
</q-card-section>
<q-table
@@ -88,7 +89,7 @@
bordered
separator="cell"
>
<template v-slot:body-cell-is_blocked="props">
<template #body-cell-is_blocked="props">
<q-td :props="props">
<q-chip
:color="props.row.is_blocked ? 'negative' : 'positive'"
@@ -117,9 +118,9 @@
<script setup>
import { onMounted } from 'vue'
import { useUserSyncStore } from 'src/stores/userSyncStore'
import { Dialog } from 'quasar'
import { usePermission } from 'src/composables/usePermission'
import { useUserSyncStore } from 'src/stores/userSyncStore'
const { canRead, canUpdate } = usePermission()
const canReadUser = canRead('user')
@@ -132,20 +133,20 @@ const pgColumns = [
{ name: 'code', label: 'Kodu', field: 'code', align: 'left' },
{ name: 'full_name', label: 'Ad Soyad', field: 'full_name', align: 'left' },
{ name: 'email', label: 'E-posta', field: 'email', align: 'left' },
{ name: 'mssql_username', label: 'MSSQL Kullanıcı', field: 'mssql_username', align: 'left' },
{ name: 'mssql_username', label: 'NEBIM_V3 Kullanicisi', field: 'mssql_username', align: 'left' },
{ name: 'sync_status', label: 'Durum', field: 'sync_status', align: 'center' },
{ name: 'actions', label: 'İşlemler', field: 'actions', align: 'center' }
{ name: 'actions', label: 'Islemler', field: 'actions', align: 'center' }
]
const msColumns = [
{ name: 'username', label: 'Kullanıcı Adı', field: 'username', align: 'left' },
{ name: 'username', label: 'Kullanici Adi', field: 'username', align: 'left' },
{ name: 'first_name', label: 'Ad', field: 'first_name', align: 'left' },
{ name: 'last_name', label: 'Soyad', field: 'last_name', align: 'left' },
{ name: 'email', label: 'E-posta', field: 'email', align: 'left' },
{ name: 'is_blocked', label: 'Durum', field: 'is_blocked', align: 'center' }
]
function statusColor(status) {
function statusColor (status) {
switch (status) {
case 'synced': return 'positive'
case 'manual': return 'primary'
@@ -155,14 +156,12 @@ function statusColor(status) {
}
}
function openMapDialog(pgUser) {
if (!canUpdateUser.value) {
return
}
function openMapDialog (pgUser) {
if (!canUpdateUser.value) return
Dialog.create({
title: 'Kullanıcı Eşleme',
message: 'Bu PostgreSQL kullanıcısını hangi MSSQL kullanıcısına bağlamak istiyorsunuz?',
title: 'Kullanici Esleme',
message: 'Bu B2B kullanicisini hangi NEBIM_V3 kullanicisina baglamak istiyorsunuz?',
options: {
type: 'radio',
model: '',
@@ -186,6 +185,7 @@ onMounted(() => {
.user-sync-page {
background: #fafafa;
}
.q-card-section {
font-weight: 600;
}