Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -19,760 +19,760 @@
|
||||
======================================================== -->
|
||||
<div class="sticky-stack">
|
||||
|
||||
<!-- 🔸 1. Satır: Filtre Bar -->
|
||||
<div class="filter-bar row q-col-gutter-md q-mb-sm">
|
||||
<!-- 🔸 1. Satır: Filtre Bar -->
|
||||
<div class="filter-bar row q-col-gutter-md q-mb-sm">
|
||||
|
||||
<!-- 🧾 Cari Seçimi -->
|
||||
<div class="col-5">
|
||||
<q-select
|
||||
v-model="form.CurrAccCode"
|
||||
:options="filteredCariOptions"
|
||||
label="Cari Seçimi"
|
||||
filled
|
||||
dense
|
||||
use-input
|
||||
input-debounce="300"
|
||||
emit-value
|
||||
map-options
|
||||
option-value="Cari_Kod"
|
||||
:option-label="opt => `${opt.Cari_Kod} - ${opt.Cari_Ad}`"
|
||||
@filter="filterCari"
|
||||
@update:model-value="onCariChange"
|
||||
:loading="loadingCari"
|
||||
:disable="isEditMode || isClosedOrder || isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
clearable
|
||||
|
||||
>
|
||||
|
||||
<template #option="scope">
|
||||
<q-item v-bind="scope.itemProps">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ scope.opt.Cari_Ad }}</q-item-label>
|
||||
<q-item-label caption>{{ scope.opt.Cari_Kod }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
|
||||
<!-- 🔢 Sipariş No -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
v-model="form.OrderNumber"
|
||||
label="Sipariş No"
|
||||
filled
|
||||
dense
|
||||
:disable="isEditMode || isClosedOrder || isViewOnly"
|
||||
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 📅 Oluşturulma Tarihi -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
:model-value="formatDateInput(form.OrderDate)"
|
||||
label="Oluşturulma Tarihi"
|
||||
type="date"
|
||||
filled
|
||||
dense
|
||||
@update:model-value="v => form.OrderDate = v"
|
||||
:disable="isEditMode || isClosedOrder || isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 📅 Tahmini Termin Tarihi (AverageDueDate kilitlenmeyecek) -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
:model-value="formatDateInput(form.AverageDueDate)"
|
||||
label="Tahmini Termin Tarihi"
|
||||
type="date"
|
||||
filled
|
||||
dense
|
||||
@update:model-value="v => form.AverageDueDate = v"
|
||||
:readonly="isViewOnly"
|
||||
:disable="isViewOnly"
|
||||
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 🔹 Cari Bilgi Satırı (2. Satır) -->
|
||||
<div
|
||||
v-if="cariInfo"
|
||||
v-show="!filterBarCollapsed"
|
||||
class="col-12 row q-col-gutter-md q-mt-xs cari-info-bar"
|
||||
>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
:model-value="cariInfo.Musteri_Temsilcisi || '-'"
|
||||
label="Müşteri Temsilcisi"
|
||||
filled dense readonly
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
:model-value="cariInfo.Musteri_Ana_Grubu || '-'"
|
||||
label="Ana Grup"
|
||||
filled dense readonly
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
:model-value="cariInfo.Piyasa || '-'"
|
||||
label="Piyasa"
|
||||
filled dense readonly
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
:model-value="cariInfo.Ulke || '-'"
|
||||
label="Ülke"
|
||||
filled dense readonly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 💰 TOPLAM TUTAR + KDV -->
|
||||
<div v-show="!filterBarCollapsed" class="col-12 row q-col-gutter-sm q-mt-xs items-center">
|
||||
<!-- 💰 Toplam Tutar -->
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
dense
|
||||
<!-- 🧾 Cari Seçimi -->
|
||||
<div class="col-5">
|
||||
<q-select
|
||||
v-model="form.CurrAccCode"
|
||||
:options="filteredCariOptions"
|
||||
label="Cari Seçimi"
|
||||
filled
|
||||
:model-value="Number(orderStore.totalAmount || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2 })"
|
||||
label="Toplam Tutar"
|
||||
readonly
|
||||
dense
|
||||
use-input
|
||||
input-debounce="300"
|
||||
emit-value
|
||||
map-options
|
||||
option-value="Cari_Kod"
|
||||
:option-label="opt => `${opt.Cari_Kod} - ${opt.Cari_Ad}`"
|
||||
@filter="filterCari"
|
||||
@update:model-value="onCariChange"
|
||||
:loading="loadingCari"
|
||||
:disable="isEditMode || isClosedOrder || isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
clearable
|
||||
|
||||
>
|
||||
<template #append>{{ form.pb }}</template>
|
||||
</q-input>
|
||||
|
||||
<template #option="scope">
|
||||
<q-item v-bind="scope.itemProps">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ scope.opt.Cari_Ad }}</q-item-label>
|
||||
<q-item-label caption>{{ scope.opt.Cari_Kod }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
|
||||
<!-- 🔘 KDV Checkbox -->
|
||||
<div class="col-auto flex items-center">
|
||||
<q-checkbox
|
||||
v-model="form.includeVat"
|
||||
label="KDV Dahil"
|
||||
color="primary"
|
||||
@update:model-value="onVatToggle"
|
||||
:disable="isClosedRow||isViewOnly"
|
||||
<!-- 🔢 Sipariş No -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
v-model="form.OrderNumber"
|
||||
label="Sipariş No"
|
||||
filled
|
||||
dense
|
||||
:disable="isEditMode || isClosedOrder || isViewOnly"
|
||||
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- ⚙️ KDV ALANLARI: sadece tikliyken görünür -->
|
||||
<template v-if="form.includeVat">
|
||||
<!-- % oran sadece bilgi -->
|
||||
<div class="col-1">
|
||||
<q-input
|
||||
dense
|
||||
filled
|
||||
:model-value="form.vatRate"
|
||||
label="%"
|
||||
readonly
|
||||
>
|
||||
<template #append>%</template>
|
||||
</q-input>
|
||||
</div>
|
||||
<!-- 📅 Oluşturulma Tarihi -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
:model-value="formatDateInput(form.OrderDate)"
|
||||
label="Oluşturulma Tarihi"
|
||||
type="date"
|
||||
filled
|
||||
dense
|
||||
@update:model-value="v => form.OrderDate = v"
|
||||
:disable="isEditMode || isClosedOrder || isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
|
||||
<!-- 🧮 KDV Tutarı (manuel düzenlenebilir) -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
dense
|
||||
filled
|
||||
v-model="form.vatAmountInput"
|
||||
label="KDV Tutarı"
|
||||
@update:model-value="onVatAmountChange"
|
||||
input-class="text-right"
|
||||
:disable="isClosedRow || isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
>
|
||||
<template #append>{{ form.pb }}</template>
|
||||
</q-input>
|
||||
</div>
|
||||
<!-- 🧾 KDV Dahil Toplam -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
dense
|
||||
filled
|
||||
:model-value="Number(form.totalWithVat || 0).toLocaleString('tr-TR',{minimumFractionDigits:2})"
|
||||
label="KDV Dahil Toplam"
|
||||
readonly
|
||||
>
|
||||
<template #append>{{ form.pb }}</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- 📝 Sipariş Genel Açıklaması (filter bar altında) -->
|
||||
<div v-show="!filterBarCollapsed" class="filter-bar-desc q-mt-sm">
|
||||
<q-input
|
||||
v-model="form.Description"
|
||||
type="textarea"
|
||||
label="Sipariş Genel Açıklaması"
|
||||
filled
|
||||
dense
|
||||
autogrow
|
||||
maxlength="1500"
|
||||
counter
|
||||
placeholder="Siparişe genel açıklama giriniz (örn. teslimat, üretim notu, müşteri isteği...)"
|
||||
:disable="isClosedRow"
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
</div>
|
||||
<!-- 🔹 Save Toolbar -->
|
||||
<div class="save-toolbar">
|
||||
<div class="text-subtitle2 text-weight-bold">Sipariş Formu</div>
|
||||
<div>
|
||||
<q-btn
|
||||
flat
|
||||
color="grey-7"
|
||||
class="q-ml-sm"
|
||||
:label="filterBarCollapsed ? 'FİLTREYİ GENİŞLET' : 'FİLTREYİ DARALT'"
|
||||
:icon="filterBarCollapsed ? 'expand_more' : 'expand_less'"
|
||||
@click="toggleFilterBarCollapsed"
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
color="grey-7"
|
||||
class="q-ml-sm"
|
||||
:label="compactGridHeader ? 'BAŞLIK GENİŞLET' : 'BAŞLIK DARALT'"
|
||||
:icon="compactGridHeader ? 'unfold_more' : 'unfold_less'"
|
||||
@click="compactGridHeader = !compactGridHeader"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isViewOnly && canExportOrder"
|
||||
label="🖨 SİPARİŞİ YAZDIR"
|
||||
color="primary"
|
||||
icon="print"
|
||||
class="q-ml-sm"
|
||||
@click="onPrintOrder"
|
||||
/>
|
||||
<!-- 📅 Tahmini Termin Tarihi (AverageDueDate kilitlenmeyecek) -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
:model-value="formatDateInput(form.AverageDueDate)"
|
||||
label="Tahmini Termin Tarihi"
|
||||
type="date"
|
||||
filled
|
||||
dense
|
||||
@update:model-value="v => form.AverageDueDate = v"
|
||||
:readonly="isViewOnly"
|
||||
:disable="isViewOnly"
|
||||
|
||||
<q-btn
|
||||
v-if="canMutateRows"
|
||||
label="SATIR EKLE"
|
||||
color="secondary"
|
||||
icon="add"
|
||||
class="q-ml-sm"
|
||||
@click="openNewRowEditor"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="canSubmitOrder"
|
||||
:label="isEditMode ? 'TÜMÜNÜ GÜNCELLE' : 'TÜMÜNÜ KAYDET'"
|
||||
color="primary"
|
||||
icon="save"
|
||||
class="q-ml-sm"
|
||||
:loading="orderStore.loading"
|
||||
:disable="!canSubmitOrder"
|
||||
@click="confirmAndSubmit"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 🔹 Grid Header -->
|
||||
<div class="order-grid-header" :class="{ compact: compactGridHeader }">
|
||||
<div class="col-fixed model">MODEL</div>
|
||||
<div class="col-fixed renk">RENK</div>
|
||||
<div class="col-fixed ana">ÜRÜN ANA GRUBU</div>
|
||||
<div class="col-fixed alt">ÜRÜN ALT GRUBU</div>
|
||||
<div class="col-fixed aciklama-col">AÇIKLAMA</div>
|
||||
|
||||
<div class="beden-block">
|
||||
<!-- 🔹 Cari Bilgi Satırı (2. Satır) -->
|
||||
<div
|
||||
v-for="grp in (
|
||||
v-if="cariInfo"
|
||||
v-show="!filterBarCollapsed"
|
||||
class="col-12 row q-col-gutter-md q-mt-xs cari-info-bar"
|
||||
>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
:model-value="cariInfo.Musteri_Temsilcisi || '-'"
|
||||
label="Müşteri Temsilcisi"
|
||||
filled dense readonly
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
:model-value="cariInfo.Musteri_Ana_Grubu || '-'"
|
||||
label="Ana Grup"
|
||||
filled dense readonly
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
:model-value="cariInfo.Piyasa || '-'"
|
||||
label="Piyasa"
|
||||
filled dense readonly
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
:model-value="cariInfo.Ulke || '-'"
|
||||
label="Ülke"
|
||||
filled dense readonly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 💰 TOPLAM TUTAR + KDV -->
|
||||
<div v-show="!filterBarCollapsed" class="col-12 row q-col-gutter-sm q-mt-xs items-center">
|
||||
<!-- 💰 Toplam Tutar -->
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
dense
|
||||
filled
|
||||
:model-value="Number(orderStore.totalAmount || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2 })"
|
||||
label="Toplam Tutar"
|
||||
readonly
|
||||
>
|
||||
<template #append>{{ form.pb }}</template>
|
||||
</q-input>
|
||||
</div>
|
||||
|
||||
<!-- 🔘 KDV Checkbox -->
|
||||
<div class="col-auto flex items-center">
|
||||
<q-checkbox
|
||||
v-model="form.includeVat"
|
||||
label="KDV Dahil"
|
||||
color="primary"
|
||||
@update:model-value="onVatToggle"
|
||||
:disable="isClosedRow||isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- ⚙️ KDV ALANLARI: sadece tikliyken görünür -->
|
||||
<template v-if="form.includeVat">
|
||||
<!-- % oran sadece bilgi -->
|
||||
<div class="col-1">
|
||||
<q-input
|
||||
dense
|
||||
filled
|
||||
:model-value="form.vatRate"
|
||||
label="%"
|
||||
readonly
|
||||
>
|
||||
<template #append>%</template>
|
||||
</q-input>
|
||||
</div>
|
||||
|
||||
<!-- 🧮 KDV Tutarı (manuel düzenlenebilir) -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
dense
|
||||
filled
|
||||
v-model="form.vatAmountInput"
|
||||
label="KDV Tutarı"
|
||||
@update:model-value="onVatAmountChange"
|
||||
input-class="text-right"
|
||||
:disable="isClosedRow || isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
>
|
||||
<template #append>{{ form.pb }}</template>
|
||||
</q-input>
|
||||
</div>
|
||||
<!-- 🧾 KDV Dahil Toplam -->
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
dense
|
||||
filled
|
||||
:model-value="Number(form.totalWithVat || 0).toLocaleString('tr-TR',{minimumFractionDigits:2})"
|
||||
label="KDV Dahil Toplam"
|
||||
readonly
|
||||
>
|
||||
<template #append>{{ form.pb }}</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- 📝 Sipariş Genel Açıklaması (filter bar altında) -->
|
||||
<div v-show="!filterBarCollapsed" class="filter-bar-desc q-mt-sm">
|
||||
<q-input
|
||||
v-model="form.Description"
|
||||
type="textarea"
|
||||
label="Sipariş Genel Açıklaması"
|
||||
filled
|
||||
dense
|
||||
autogrow
|
||||
maxlength="1500"
|
||||
counter
|
||||
placeholder="Siparişe genel açıklama giriniz (örn. teslimat, üretim notu, müşteri isteği...)"
|
||||
:disable="isClosedRow"
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
</div>
|
||||
<!-- 🔹 Save Toolbar -->
|
||||
<div class="save-toolbar">
|
||||
<div class="text-subtitle2 text-weight-bold">Sipariş Formu</div>
|
||||
<div>
|
||||
<q-btn
|
||||
flat
|
||||
color="grey-7"
|
||||
class="q-ml-sm"
|
||||
:label="filterBarCollapsed ? 'FİLTREYİ GENİŞLET' : 'FİLTREYİ DARALT'"
|
||||
:icon="filterBarCollapsed ? 'expand_more' : 'expand_less'"
|
||||
@click="toggleFilterBarCollapsed"
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
color="grey-7"
|
||||
class="q-ml-sm"
|
||||
:label="compactGridHeader ? 'BAŞLIK GENİŞLET' : 'BAŞLIK DARALT'"
|
||||
:icon="compactGridHeader ? 'unfold_more' : 'unfold_less'"
|
||||
@click="compactGridHeader = !compactGridHeader"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isViewOnly && canExportOrder"
|
||||
label="🖨 SİPARİŞİ YAZDIR"
|
||||
color="primary"
|
||||
icon="print"
|
||||
class="q-ml-sm"
|
||||
@click="onPrintOrder"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
v-if="canMutateRows"
|
||||
label="SATIR EKLE"
|
||||
color="secondary"
|
||||
icon="add"
|
||||
class="q-ml-sm"
|
||||
@click="openNewRowEditor"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="canSubmitOrder"
|
||||
:label="isEditMode ? 'TÜMÜNÜ GÜNCELLE' : 'TÜMÜNÜ KAYDET'"
|
||||
color="primary"
|
||||
icon="save"
|
||||
class="q-ml-sm"
|
||||
:loading="orderStore.loading"
|
||||
:disable="!canSubmitOrder"
|
||||
@click="confirmAndSubmit"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 🔹 Grid Header -->
|
||||
<div class="order-grid-header" :class="{ compact: compactGridHeader }">
|
||||
<div class="col-fixed model">MODEL</div>
|
||||
<div class="col-fixed renk">RENK</div>
|
||||
<div class="col-fixed ana">ÜRÜN ANA GRUBU</div>
|
||||
<div class="col-fixed alt">ÜRÜN ALT GRUBU</div>
|
||||
<div class="col-fixed aciklama-col">AÇIKLAMA</div>
|
||||
|
||||
<div class="beden-block">
|
||||
<div
|
||||
v-for="grp in (
|
||||
Object.keys(orderStore?.schemaMap || {}).length
|
||||
? Object.values(orderStore.schemaMap)
|
||||
: Object.values(storeSchemaByKey)
|
||||
)"
|
||||
:key="grp.key"
|
||||
class="grp-row"
|
||||
:class="{ 'hl-pan': grp.key === 'pan' && highlightPantolon }"
|
||||
>
|
||||
:key="grp.key"
|
||||
class="grp-row"
|
||||
:class="{ 'hl-pan': grp.key === 'pan' && highlightPantolon }"
|
||||
>
|
||||
|
||||
<div class="grp-title">{{ grp.title }}</div>
|
||||
<div class="grp-body">
|
||||
<div
|
||||
v-for="v in (grp.values || [])"
|
||||
:key="'b-' + grp.key + '-' + v"
|
||||
class="grp-cell hdr"
|
||||
>
|
||||
{{ v }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="total-row">
|
||||
<div class="total-cell">ADET</div>
|
||||
<div class="total-cell">FİYAT</div>
|
||||
<div class="total-cell">PB</div>
|
||||
<div class="total-cell">TUTAR</div>
|
||||
<div class="total-cell">Tahmini Gönderim Tarihi</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- =======================================================
|
||||
🔹 GRID BODY (Final Stabil) + EDITOR aynı scroll’da
|
||||
======================================================== -->
|
||||
<div class="order-scroll-y" :class="{ 'compact-grid-header': compactGridHeader }"> <!-- ✅ YENİ: Grid + Editor ortak dikey scroll -->
|
||||
<div class="order-grid-body">
|
||||
<template v-for="grp in groupedRows" :key="grp.name">
|
||||
<div :class="['summary-group', grp.open ? 'open' : 'closed']">
|
||||
|
||||
<!-- 🟡 Sub-header -->
|
||||
<div class="order-sub-header" @click="toggleGroup(grp.name)">
|
||||
<div class="sub-left">{{ grp.name }}</div>
|
||||
|
||||
<div class="sub-center">
|
||||
<div class="grp-title">{{ grp.title }}</div>
|
||||
<div class="grp-body">
|
||||
<div
|
||||
v-for="v in (
|
||||
orderStore.schemaMap?.[grp.grpKey]?.values
|
||||
|| storeSchemaByKey?.[grp.grpKey]?.values
|
||||
|| []
|
||||
)"
|
||||
:key="'hdr-' + grp.grpKey + '-' + v"
|
||||
class="beden-cell"
|
||||
v-for="v in (grp.values || [])"
|
||||
:key="'b-' + grp.key + '-' + v"
|
||||
class="grp-cell hdr"
|
||||
>
|
||||
{{ v }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sub-right">
|
||||
|
||||
|
||||
<div class="order-text-caption">
|
||||
Toplam {{ grp.name }} Adet: {{ grp.toplamAdet }}
|
||||
</div>
|
||||
<div class="order-text-caption">
|
||||
Toplam {{ grp.name }} Tutar:
|
||||
{{ Number(grp.toplamTutar || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2 }) }}
|
||||
{{ form.pb || aktifPB }}
|
||||
</div>
|
||||
<q-icon
|
||||
:name="grp.open ? 'expand_less' : 'expand_more'"
|
||||
size="20px"
|
||||
class="cursor-pointer text-grey-8 q-ml-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 🧩 Grup satırları -->
|
||||
<template v-if="grp.open">
|
||||
<div
|
||||
v-for="row in grp.rows"
|
||||
:key="rowKey(row)"
|
||||
class="summary-row"
|
||||
:data-clientkey="row.clientKey"
|
||||
:class="{
|
||||
</div>
|
||||
|
||||
<div class="total-row">
|
||||
<div class="total-cell">ADET</div>
|
||||
<div class="total-cell">FİYAT</div>
|
||||
<div class="total-cell">PB</div>
|
||||
<div class="total-cell">TUTAR</div>
|
||||
<div class="total-cell">Tahmini Gönderim Tarihi</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- =======================================================
|
||||
🔹 GRID BODY (Final Stabil) + EDITOR aynı scroll’da
|
||||
======================================================== -->
|
||||
<div class="order-scroll-y" :class="{ 'compact-grid-header': compactGridHeader }"> <!-- ✅ YENİ: Grid + Editor ortak dikey scroll -->
|
||||
<div class="order-grid-body">
|
||||
<template v-for="grp in groupedRows" :key="grp.name">
|
||||
<div :class="['summary-group', grp.open ? 'open' : 'closed']">
|
||||
|
||||
<!-- 🟡 Sub-header -->
|
||||
<div class="order-sub-header" @click="toggleGroup(grp.name)">
|
||||
<div class="sub-left">{{ grp.name }}</div>
|
||||
|
||||
<div class="sub-center">
|
||||
<div
|
||||
v-for="v in (
|
||||
orderStore.schemaMap?.[grp.grpKey]?.values
|
||||
|| storeSchemaByKey?.[grp.grpKey]?.values
|
||||
|| []
|
||||
)"
|
||||
:key="'hdr-' + grp.grpKey + '-' + v"
|
||||
class="beden-cell"
|
||||
>
|
||||
{{ v }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sub-right">
|
||||
|
||||
|
||||
<div class="order-text-caption">
|
||||
Toplam {{ grp.name }} Adet: {{ grp.toplamAdet }}
|
||||
</div>
|
||||
<div class="order-text-caption">
|
||||
Toplam {{ grp.name }} Tutar:
|
||||
{{ Number(grp.toplamTutar || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2 }) }}
|
||||
{{ form.pb || aktifPB }}
|
||||
</div>
|
||||
<q-icon
|
||||
:name="grp.open ? 'expand_less' : 'expand_more'"
|
||||
size="20px"
|
||||
class="cursor-pointer text-grey-8 q-ml-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 🧩 Grup satırları -->
|
||||
<template v-if="grp.open">
|
||||
<div
|
||||
v-for="row in grp.rows"
|
||||
:key="rowKey(row)"
|
||||
class="summary-row"
|
||||
:data-clientkey="row.clientKey"
|
||||
:class="{
|
||||
active: orderStore.editingKey === rowKey(row),
|
||||
'is-editing': orderStore.editingKey === rowKey(row),
|
||||
'row-closed': row.isClosed,
|
||||
'row-error': row._error
|
||||
}"
|
||||
@click="!row.isClosed && !isViewOnly && editRow(row)"
|
||||
>
|
||||
|
||||
<!-- 🔴 HATA İKONU (SADECE HATALI SATIRDA) -->
|
||||
<q-icon
|
||||
v-if="row._error"
|
||||
name="error"
|
||||
color="negative"
|
||||
size="18px"
|
||||
class="q-mr-sm row-error-icon"
|
||||
@click="!row.isClosed && !isViewOnly && editRow(row)"
|
||||
>
|
||||
<q-tooltip>
|
||||
{{ row._error.message }}
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
|
||||
<!-- Sol kolonlar -->
|
||||
<div class="cell model">{{ row.model }}</div>
|
||||
<div class="cell renk">
|
||||
{{ row.renk }}{{ row.renk2 ? '-' + row.renk2 : '' }}
|
||||
</div>
|
||||
<div class="cell ana">{{ row.urunAnaGrubu }}</div>
|
||||
<div class="cell alt">{{ row.urunAltGrubu }}</div>
|
||||
<div class="cell aciklama">{{ row.aciklama }}</div>
|
||||
<!-- 🔴 HATA İKONU (SADECE HATALI SATIRDA) -->
|
||||
<q-icon
|
||||
v-if="row._error"
|
||||
name="error"
|
||||
color="negative"
|
||||
size="18px"
|
||||
class="q-mr-sm row-error-icon"
|
||||
>
|
||||
<q-tooltip>
|
||||
{{ row._error.message }}
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
|
||||
<!-- Beden kolonları -->
|
||||
<div class="grp-area">
|
||||
<div class="grp-row">
|
||||
<div
|
||||
v-for="v in (
|
||||
<!-- Sol kolonlar -->
|
||||
<div class="cell model">{{ row.model }}</div>
|
||||
<div class="cell renk">
|
||||
{{ row.renk }}{{ row.renk2 ? '-' + row.renk2 : '' }}
|
||||
</div>
|
||||
<div class="cell ana">{{ row.urunAnaGrubu }}</div>
|
||||
<div class="cell alt">{{ row.urunAltGrubu }}</div>
|
||||
<div class="cell aciklama">{{ row.aciklama }}</div>
|
||||
|
||||
<!-- Beden kolonları -->
|
||||
<div class="grp-area">
|
||||
<div class="grp-row">
|
||||
<div
|
||||
v-for="v in (
|
||||
(orderStore.schemaMap?.[row.grpKey]?.values) ||
|
||||
(storeSchemaByKey[row.grpKey]?.values) ||
|
||||
(storeSchemaByKey.tak.values)
|
||||
)"
|
||||
|
||||
:key="'val-' + v"
|
||||
class="cell beden"
|
||||
>
|
||||
{{ resolveBedenValue(row.bedenMap, row.grpKey, v) }}
|
||||
</div>
|
||||
:key="'val-' + v"
|
||||
class="cell beden"
|
||||
>
|
||||
{{ resolveBedenValue(row.bedenMap, row.grpKey, v) }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="i2 in Math.max(0, 16 - (
|
||||
<div
|
||||
v-for="i2 in Math.max(0, 16 - (
|
||||
(orderStore.schemaMap?.[row.grpKey]?.values?.length) ||
|
||||
(storeSchemaByKey[row.grpKey]?.values?.length) ||
|
||||
(storeSchemaByKey.tak.values.length)
|
||||
))"
|
||||
|
||||
:key="'empty-' + i2"
|
||||
class="cell beden ghost"
|
||||
></div>
|
||||
:key="'empty-' + i2"
|
||||
class="cell beden ghost"
|
||||
></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sağ kolonlar -->
|
||||
<div class="cell adet">{{ row.adet }}</div>
|
||||
<div class="cell fiyat">{{ row.fiyat }}</div>
|
||||
<div class="cell pb">{{ row.pb }}</div>
|
||||
<div class="cell tutar">
|
||||
{{ Number(row.tutar || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2 }) }}
|
||||
</div>
|
||||
|
||||
<!-- 🗓 Termin Tarihi -->
|
||||
<div class="cell termin">
|
||||
<div class="termin-label text-center">
|
||||
{{ formatDate(row.terminTarihi) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<!-- =======================================================
|
||||
🔹 SATIR DÜZENLEYİCİ FORM (EDITOR)
|
||||
======================================================== -->
|
||||
<q-dialog
|
||||
v-model="showEditor"
|
||||
class="order-editor-dialog"
|
||||
:maximized="$q.screen.lt.md"
|
||||
full-width
|
||||
transition-show="jump-down"
|
||||
transition-hide="jump-up"
|
||||
persistent
|
||||
>
|
||||
<q-card class="order-editor-card">
|
||||
<q-card-section class="row items-center justify-between">
|
||||
<div class="text-subtitle1 text-weight-bold">
|
||||
{{ isEditing ? 'Satır Düzenle' : 'Yeni Satır' }}
|
||||
</div>
|
||||
<q-btn flat round icon="close" @click="showEditor = false" />
|
||||
</q-card-section>
|
||||
<q-separator />
|
||||
<q-card-section class="editor q-pa-sm">
|
||||
|
||||
<!-- 🔸 1. Satır: Model ve Ürün Bilgileri -->
|
||||
<div class="row q-col-gutter-sm q-mb-sm">
|
||||
<div class="col-3">
|
||||
<!-- 🔹 Model Seçimi -->
|
||||
<q-select
|
||||
v-model="form.model"
|
||||
:options="filteredModelOptions"
|
||||
label="Model"
|
||||
filled dense
|
||||
use-input input-debounce="250"
|
||||
emit-value map-options
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
clearable behavior="menu"
|
||||
hint="Model kodu ile arayabilirsiniz"
|
||||
:loading="loadingModels"
|
||||
:disable=" isClosedRow||isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
@filter="filterModel"
|
||||
@update:model-value="(val) => useComboWatcher('model', onModelChange)(val)"
|
||||
/>
|
||||
|
||||
<!-- 🔹 1. Renk Seçimi -->
|
||||
<div class="q-mt-sm">
|
||||
<q-select
|
||||
ref="renkSelect"
|
||||
v-model="form.renk"
|
||||
:options="renkOptions"
|
||||
label="Renk"
|
||||
filled dense clearable
|
||||
emit-value map-options
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
:disable="isClosedRow||isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
@update:model-value="(val) => useComboWatcher('renk', onColorChange)(val)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 🔹 2. Renk Seçimi -->
|
||||
<div class="q-mt-sm">
|
||||
<q-select
|
||||
ref="renk2Select"
|
||||
v-model="form.renk2"
|
||||
:options="renkOptions2"
|
||||
label="2. Renk"
|
||||
filled dense clearable
|
||||
emit-value map-options
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
:disable="!renkOptions2.length || isEditing || isClosedRow"
|
||||
@update:model-value="(val) => useComboWatcher('renk2', onColor2Change)(val)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sağ kolonlar -->
|
||||
<div class="cell adet">{{ row.adet }}</div>
|
||||
<div class="cell fiyat">{{ row.fiyat }}</div>
|
||||
<div class="cell pb">{{ row.pb }}</div>
|
||||
<div class="cell tutar">
|
||||
{{ Number(row.tutar || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2 }) }}
|
||||
<!-- Ürün teknik alanları -->
|
||||
<div class="col-2">
|
||||
<q-input v-model="form.urunAnaGrubu" label="Ürün Ana Grubu" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.urunAltGrubu" label="Alt Grup" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.fit" label="Fit" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<q-input v-model="form.urunIcerik" label="İçerik" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.drop" label="Drop" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.askiliyan" label="ASKILI/YAN" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.kategori" label="Kategori" filled dense readonly />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 🔸 2. Satır: Seri Seçimi -->
|
||||
<div class="row q-col-gutter-sm q-mt-xs">
|
||||
<div class="col-3">
|
||||
<q-select
|
||||
ref="seriSelect"
|
||||
v-show="Array.isArray(activeSeriesOptions) && activeSeriesOptions.length > 0"
|
||||
v-model="selectedSeriSet"
|
||||
:options="activeSeriesOptions"
|
||||
label="Beden Seti Seç"
|
||||
filled dense
|
||||
emit-value map-options
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 🗓 Termin Tarihi -->
|
||||
<div class="cell termin">
|
||||
<div class="termin-label text-center">
|
||||
{{ formatDate(row.terminTarihi) }}
|
||||
<div class="col-2 q-mt-sm">
|
||||
<q-input
|
||||
v-if="selectedSeriSet"
|
||||
v-model.number="seriMultiplier"
|
||||
type="number"
|
||||
label="Çarpan"
|
||||
min="1"
|
||||
filled dense
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-2 q-mt-sm">
|
||||
<q-btn
|
||||
v-if="selectedSeriSet && canMutateRows"
|
||||
color="primary"
|
||||
icon="add"
|
||||
label="Seri Ekle"
|
||||
@click="applySeriSet"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- =======================================================
|
||||
🔹 BEDEN GİRİŞ ALANI + STOK ETİKETİ GÖRÜNÜMÜ
|
||||
======================================================== -->
|
||||
<div class="row q-mt-sm q-col-gutter-xs beden-grid">
|
||||
<div
|
||||
v-for="(lbl, i) in form.bedenLabels || []"
|
||||
:key="'beden-'+i"
|
||||
class="col-auto beden-wrap"
|
||||
>
|
||||
<div class="beden-label">{{ lbl }}</div>
|
||||
|
||||
<q-input
|
||||
v-model.number="form.bedenler[i]"
|
||||
dense outlined type="number" min="0"
|
||||
style="width:60px"
|
||||
@focus="activeBeden = i"
|
||||
@blur="activeBeden = null"
|
||||
@update:model-value="updateTotals(form)"
|
||||
:class="{ 'beden-active': activeBeden === i }"
|
||||
:disable="isClosedRow||isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="getStockFor(lbl) !== null"
|
||||
class="stok-label text-caption text-center q-mt-xs"
|
||||
:class="stockColorClass(getStockFor(lbl))"
|
||||
>
|
||||
Stok: {{ getStockFor(lbl) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<!-- =======================================================
|
||||
🔹 SATIR DÜZENLEYİCİ FORM (EDITOR)
|
||||
======================================================== -->
|
||||
<q-dialog
|
||||
v-model="showEditor"
|
||||
class="order-editor-dialog"
|
||||
:maximized="$q.screen.lt.md"
|
||||
full-width
|
||||
transition-show="jump-down"
|
||||
transition-hide="jump-up"
|
||||
persistent
|
||||
>
|
||||
<q-card class="order-editor-card">
|
||||
<q-card-section class="row items-center justify-between">
|
||||
<div class="text-subtitle1 text-weight-bold">
|
||||
{{ isEditing ? 'Satır Düzenle' : 'Yeni Satır' }}
|
||||
</div>
|
||||
<q-btn flat round icon="close" @click="showEditor = false" />
|
||||
</q-card-section>
|
||||
<q-separator />
|
||||
<q-card-section class="editor q-pa-sm">
|
||||
<!-- 🔹 Aktif beden için küçük stok etiketi -->
|
||||
<div
|
||||
v-if="form.model && activeBeden !== null && getStockFor(form.bedenLabels[activeBeden]) !== null"
|
||||
class="stok-label-sm"
|
||||
:class="stockColorClass(getStockFor(form.bedenLabels[activeBeden]))"
|
||||
>
|
||||
Stok: {{ getStockFor(form.bedenLabels[activeBeden]) }}
|
||||
</div>
|
||||
|
||||
<!-- 🔸 1. Satır: Model ve Ürün Bilgileri -->
|
||||
<div class="row q-col-gutter-sm q-mb-sm">
|
||||
<div class="col-3">
|
||||
<!-- 🔹 Model Seçimi -->
|
||||
<q-select
|
||||
v-model="form.model"
|
||||
:options="filteredModelOptions"
|
||||
label="Model"
|
||||
filled dense
|
||||
use-input input-debounce="250"
|
||||
emit-value map-options
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
clearable behavior="menu"
|
||||
hint="Model kodu ile arayabilirsiniz"
|
||||
:loading="loadingModels"
|
||||
:disable=" isClosedRow||isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
@filter="filterModel"
|
||||
@update:model-value="(val) => useComboWatcher('model', onModelChange)(val)"
|
||||
/>
|
||||
<!-- =======================================================
|
||||
🔹 ADET / FİYAT / PB / TUTAR
|
||||
======================================================== -->
|
||||
<div class="row q-mt-sm q-col-gutter-sm">
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
v-model.number="form.adet"
|
||||
label="Adet"
|
||||
dense
|
||||
filled
|
||||
readonly
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
v-model.number="form.fiyat"
|
||||
label="Fiyat"
|
||||
dense
|
||||
filled
|
||||
type="number"
|
||||
min="0"
|
||||
@update:model-value="() => updateTotals(form)"
|
||||
:disable="isClosedRow||isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<q-select
|
||||
v-model="form.pb"
|
||||
:options="paraBirimOptions"
|
||||
label="PB"
|
||||
dense
|
||||
filled
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
v-model="form.tutar"
|
||||
label="Tutar"
|
||||
dense
|
||||
filled
|
||||
readonly
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 🔹 1. Renk Seçimi -->
|
||||
<div class="q-mt-sm">
|
||||
<q-select
|
||||
ref="renkSelect"
|
||||
v-model="form.renk"
|
||||
:options="renkOptions"
|
||||
label="Renk"
|
||||
filled dense clearable
|
||||
emit-value map-options
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
:disable="isClosedRow||isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
@update:model-value="(val) => useComboWatcher('renk', onColorChange)(val)"
|
||||
/>
|
||||
</div>
|
||||
<!-- =======================================================
|
||||
🔹 SATIR BAZINDA TAHMİNİ TERMİN TARİHİ
|
||||
======================================================== -->
|
||||
<div class="row q-mt-sm">
|
||||
<div class="col-4">
|
||||
<q-input
|
||||
v-model="form.terminTarihi"
|
||||
type="date"
|
||||
label="Tahmini Termin Tarihi"
|
||||
filled
|
||||
dense
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 🔹 2. Renk Seçimi -->
|
||||
<div class="q-mt-sm">
|
||||
<q-select
|
||||
ref="renk2Select"
|
||||
v-model="form.renk2"
|
||||
:options="renkOptions2"
|
||||
label="2. Renk"
|
||||
filled dense clearable
|
||||
emit-value map-options
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
:disable="!renkOptions2.length || isEditing || isClosedRow"
|
||||
@update:model-value="(val) => useComboWatcher('renk2', onColor2Change)(val)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- =======================================================
|
||||
🔹 AÇIKLAMA ALANI
|
||||
======================================================== -->
|
||||
<div class="row q-mt-sm">
|
||||
<div class="col-12">
|
||||
<q-input
|
||||
v-model="form.aciklama"
|
||||
label="Açıklama"
|
||||
type="textarea"
|
||||
filled
|
||||
dense
|
||||
autogrow
|
||||
maxlength="1500"
|
||||
counter
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- =======================================================
|
||||
🔹 BUTONLAR (Kaydet / Güncelle / Sil / Temizle)
|
||||
======================================================== -->
|
||||
<div class="row justify-between items-center q-mt-md">
|
||||
<div class="row q-gutter-sm">
|
||||
<q-btn
|
||||
v-if="canMutateRows"
|
||||
:color="isEditing ? 'positive' : 'primary'"
|
||||
:label="isEditing ? 'Güncelle' : 'Kaydet'"
|
||||
@click="onSaveOrUpdateRow"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
|
||||
<!-- Ürün teknik alanları -->
|
||||
<div class="col-2">
|
||||
<q-input v-model="form.urunAnaGrubu" label="Ürün Ana Grubu" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.urunAltGrubu" label="Alt Grup" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.fit" label="Fit" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<q-input v-model="form.urunIcerik" label="İçerik" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.drop" label="Drop" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.askiliyan" label="ASKILI/YAN" filled dense readonly />
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-input v-model="form.kategori" label="Kategori" filled dense readonly />
|
||||
</div>
|
||||
</div>
|
||||
/>
|
||||
<q-btn
|
||||
v-if="canMutateRows"
|
||||
color="secondary"
|
||||
label="Kaydet ve Diğer Renge Geç"
|
||||
@click="onSaveAndNextColor"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isEditing && canMutateRows"
|
||||
color="negative"
|
||||
flat
|
||||
label="Satırı Sil"
|
||||
@click="removeSelected"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="canMutateRows"
|
||||
flat
|
||||
color="grey-8"
|
||||
label="Formu Temizle"
|
||||
@click="onResetEditorClick"
|
||||
:disable="isClosedRow||isViewOnly || !canMutateRows"
|
||||
|
||||
<!-- 🔸 2. Satır: Seri Seçimi -->
|
||||
<div class="row q-col-gutter-sm q-mt-xs">
|
||||
<div class="col-3">
|
||||
<q-select
|
||||
ref="seriSelect"
|
||||
v-show="Array.isArray(activeSeriesOptions) && activeSeriesOptions.length > 0"
|
||||
v-model="selectedSeriSet"
|
||||
:options="activeSeriesOptions"
|
||||
label="Beden Seti Seç"
|
||||
filled dense
|
||||
emit-value map-options
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-2 q-mt-sm">
|
||||
<q-input
|
||||
v-if="selectedSeriSet"
|
||||
v-model.number="seriMultiplier"
|
||||
type="number"
|
||||
label="Çarpan"
|
||||
min="1"
|
||||
filled dense
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
<!-- =======================================================
|
||||
🔹 ALT BİLGİLENDİRME ALANI
|
||||
======================================================== -->
|
||||
<div class="q-mt-md text-caption text-grey-7 text-center">
|
||||
<q-icon name="info" size="16px" class="q-mr-xs" />
|
||||
Bu sayfada yapılan siparişler henüz gönderilmemiştir.
|
||||
<br />
|
||||
<span class="text-negative">"Tümünü Kaydet (Toplu Gönder)"</span>
|
||||
butonuna basarak işlemleri kaydedebilirsiniz.
|
||||
</div>
|
||||
|
||||
<div class="col-2 q-mt-sm">
|
||||
<q-btn
|
||||
v-if="selectedSeriSet && canMutateRows"
|
||||
color="primary"
|
||||
icon="add"
|
||||
label="Seri Ekle"
|
||||
@click="applySeriSet"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- =======================================================
|
||||
🔹 BEDEN GİRİŞ ALANI + STOK ETİKETİ GÖRÜNÜMÜ
|
||||
======================================================== -->
|
||||
<div class="row q-mt-sm q-col-gutter-xs beden-grid">
|
||||
<div
|
||||
v-for="(lbl, i) in form.bedenLabels || []"
|
||||
:key="'beden-'+i"
|
||||
class="col-auto beden-wrap"
|
||||
>
|
||||
<div class="beden-label">{{ lbl }}</div>
|
||||
|
||||
<q-input
|
||||
v-model.number="form.bedenler[i]"
|
||||
dense outlined type="number" min="0"
|
||||
style="width:60px"
|
||||
@focus="activeBeden = i"
|
||||
@blur="activeBeden = null"
|
||||
@update:model-value="updateTotals(form)"
|
||||
:class="{ 'beden-active': activeBeden === i }"
|
||||
:disable="isClosedRow||isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="getStockFor(lbl) !== null"
|
||||
class="stok-label text-caption text-center q-mt-xs"
|
||||
:class="stockColorClass(getStockFor(lbl))"
|
||||
>
|
||||
Stok: {{ getStockFor(lbl) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 🔹 Aktif beden için küçük stok etiketi -->
|
||||
<div
|
||||
v-if="form.model && activeBeden !== null && getStockFor(form.bedenLabels[activeBeden]) !== null"
|
||||
class="stok-label-sm"
|
||||
:class="stockColorClass(getStockFor(form.bedenLabels[activeBeden]))"
|
||||
>
|
||||
Stok: {{ getStockFor(form.bedenLabels[activeBeden]) }}
|
||||
</div>
|
||||
|
||||
<!-- =======================================================
|
||||
🔹 ADET / FİYAT / PB / TUTAR
|
||||
======================================================== -->
|
||||
<div class="row q-mt-sm q-col-gutter-sm">
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
v-model.number="form.adet"
|
||||
label="Adet"
|
||||
dense
|
||||
filled
|
||||
readonly
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
v-model.number="form.fiyat"
|
||||
label="Fiyat"
|
||||
dense
|
||||
filled
|
||||
type="number"
|
||||
min="0"
|
||||
@update:model-value="() => updateTotals(form)"
|
||||
:disable="isClosedRow||isViewOnly"
|
||||
:readonly="isViewOnly"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<q-select
|
||||
v-model="form.pb"
|
||||
:options="paraBirimOptions"
|
||||
label="PB"
|
||||
dense
|
||||
filled
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
v-model="form.tutar"
|
||||
label="Tutar"
|
||||
dense
|
||||
filled
|
||||
readonly
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- =======================================================
|
||||
🔹 SATIR BAZINDA TAHMİNİ TERMİN TARİHİ
|
||||
======================================================== -->
|
||||
<div class="row q-mt-sm">
|
||||
<div class="col-4">
|
||||
<q-input
|
||||
v-model="form.terminTarihi"
|
||||
type="date"
|
||||
label="Tahmini Termin Tarihi"
|
||||
filled
|
||||
dense
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- =======================================================
|
||||
🔹 AÇIKLAMA ALANI
|
||||
======================================================== -->
|
||||
<div class="row q-mt-sm">
|
||||
<div class="col-12">
|
||||
<q-input
|
||||
v-model="form.aciklama"
|
||||
label="Açıklama"
|
||||
type="textarea"
|
||||
filled
|
||||
dense
|
||||
autogrow
|
||||
maxlength="1500"
|
||||
counter
|
||||
:disable="isClosedRow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- =======================================================
|
||||
🔹 BUTONLAR (Kaydet / Güncelle / Sil / Temizle)
|
||||
======================================================== -->
|
||||
<div class="row justify-between items-center q-mt-md">
|
||||
<div class="row q-gutter-sm">
|
||||
<q-btn
|
||||
v-if="canMutateRows"
|
||||
:color="isEditing ? 'positive' : 'primary'"
|
||||
:label="isEditing ? 'Güncelle' : 'Kaydet'"
|
||||
@click="onSaveOrUpdateRow"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
|
||||
/>
|
||||
<q-btn
|
||||
v-if="canMutateRows"
|
||||
color="secondary"
|
||||
label="Kaydet ve Diğer Renge Geç"
|
||||
@click="onSaveAndNextColor"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isEditing && canMutateRows"
|
||||
color="negative"
|
||||
flat
|
||||
label="Satırı Sil"
|
||||
@click="removeSelected"
|
||||
:disable="isClosedRow || isViewOnly || !canMutateRows"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="canMutateRows"
|
||||
flat
|
||||
color="grey-8"
|
||||
label="Formu Temizle"
|
||||
@click="onResetEditorClick"
|
||||
:disable="isClosedRow||isViewOnly || !canMutateRows"
|
||||
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- =======================================================
|
||||
🔹 ALT BİLGİLENDİRME ALANI
|
||||
======================================================== -->
|
||||
<div class="q-mt-md text-caption text-grey-7 text-center">
|
||||
<q-icon name="info" size="16px" class="q-mr-xs" />
|
||||
Bu sayfada yapılan siparişler henüz gönderilmemiştir.
|
||||
<br />
|
||||
<span class="text-negative">"Tümünü Kaydet (Toplu Gönder)"</span>
|
||||
butonuna basarak işlemleri kaydedebilirsiniz.
|
||||
</div>
|
||||
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div> <!-- ✅ order-scroll-y -->
|
||||
</template>
|
||||
|
||||
@@ -2674,13 +2674,20 @@ async function onModelChange(modelCode) {
|
||||
- En sonda güvenli fallback: 'tak'
|
||||
======================================================= */
|
||||
const ana = String(form.urunAnaGrubu || '').toLowerCase().trim()
|
||||
const kat = String(form.kategori || '').toLowerCase().trim()
|
||||
const kat = String(form.kategori || form.urunAltGrubu || '').toLowerCase().trim()
|
||||
const yg = String(form.askiliyan || '').toLowerCase().trim()
|
||||
const hasGarsonMeta =
|
||||
ana.includes('garson') ||
|
||||
kat.includes('garson') ||
|
||||
kat.includes('yetiskin/garson') ||
|
||||
yg.includes('garson') ||
|
||||
yg.includes('yetiskin/garson')
|
||||
|
||||
let bedenGrpKey = null
|
||||
|
||||
// ✅ Hard-match (senin ana gruplarına göre genişletebilirsin)
|
||||
if (
|
||||
(kat.includes('garson') || kat.includes('yetiskin/garson')) &&
|
||||
hasGarsonMeta &&
|
||||
(
|
||||
ana.includes('gomlek atayaka') ||
|
||||
ana.includes('gomlek ata yaka') ||
|
||||
@@ -2688,8 +2695,8 @@ async function onModelChange(modelCode) {
|
||||
)
|
||||
) {
|
||||
bedenGrpKey = 'yas'
|
||||
} else if ((ana.includes('garson') || kat.includes('garson') || kat.includes('yetiskin/garson') || ana.includes('yetiskin/garson')) &&
|
||||
(ana.includes('ayakkabı') || ana.includes('ayakkabi') || kat.includes('ayakkabı') || kat.includes('ayakkabi'))) {
|
||||
} else if (hasGarsonMeta &&
|
||||
(ana.includes('ayakkabı') || ana.includes('ayakkabi') || kat.includes('ayakkabı') || kat.includes('ayakkabi'))) {
|
||||
bedenGrpKey = 'ayk_garson'
|
||||
} else if (ana.includes('pantolon') || kat.includes('pantolon')) {
|
||||
bedenGrpKey = 'pan'
|
||||
@@ -2705,7 +2712,12 @@ async function onModelChange(modelCode) {
|
||||
if (!bedenGrpKey) {
|
||||
try {
|
||||
// ⚠️ Boş array verme; ürün bilgisini kullanarak belirle
|
||||
bedenGrpKey = detectBedenGroup(null, form.urunAnaGrubu, form.kategori)
|
||||
bedenGrpKey = detectBedenGroup(
|
||||
null,
|
||||
form.urunAnaGrubu,
|
||||
form.kategori || form.urunAltGrubu,
|
||||
form.askiliyan
|
||||
)
|
||||
} catch (e) {
|
||||
console.warn('⚠️ detectBedenGroup hata:', e)
|
||||
bedenGrpKey = null
|
||||
|
||||
Reference in New Issue
Block a user