Fix product performance grouped JSON build
This commit is contained in:
@@ -1170,6 +1170,11 @@ func InitRoutes(pgDB *sql.DB, mssql *sql.DB, ml *mailer.GraphMailer) *mux.Router
|
|||||||
"costing", "view",
|
"costing", "view",
|
||||||
wrapV3(http.HandlerFunc(routes.GetProductionHasCostHistoryHandler)),
|
wrapV3(http.HandlerFunc(routes.GetProductionHasCostHistoryHandler)),
|
||||||
)
|
)
|
||||||
|
bindV3(r, pgDB,
|
||||||
|
"/api/pricing/production-product-costing/firm-cost-history", "GET",
|
||||||
|
"costing", "view",
|
||||||
|
wrapV3(http.HandlerFunc(routes.GetProductionFirmCostHistoryHandler)),
|
||||||
|
)
|
||||||
bindV3(r, pgDB,
|
bindV3(r, pgDB,
|
||||||
"/api/pricing/production-product-costing/has-cost-detail-groups", "GET",
|
"/api/pricing/production-product-costing/has-cost-detail-groups", "GET",
|
||||||
"costing", "view",
|
"costing", "view",
|
||||||
|
|||||||
@@ -62,6 +62,16 @@ type ProductionHasCostHistoryRow struct {
|
|||||||
SAciklama string `json:"sAciklama"`
|
SAciklama string `json:"sAciklama"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProductionFirmCostHistoryRow struct {
|
||||||
|
NOnMLNo int `json:"nOnMLNo"`
|
||||||
|
UrunKodu string `json:"UrunKodu"`
|
||||||
|
UrunAdi string `json:"UrunAdi"`
|
||||||
|
Tarihi string `json:"Tarihi"`
|
||||||
|
TPCount int `json:"tpCount"`
|
||||||
|
DTCount int `json:"dtCount"`
|
||||||
|
TotalRows int `json:"totalRows"`
|
||||||
|
}
|
||||||
|
|
||||||
type ProductionType struct {
|
type ProductionType struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Aciklama string `json:"aciklama"`
|
Aciklama string `json:"aciklama"`
|
||||||
|
|||||||
@@ -1049,6 +1049,62 @@ ORDER BY
|
|||||||
return uretimDB.QueryContext(ctx, sqlText, productCode)
|
return uretimDB.QueryContext(ctx, sqlText, productCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetProductionFirmCostHistory(
|
||||||
|
ctx context.Context,
|
||||||
|
uretimDB *sql.DB,
|
||||||
|
nFirmaID int,
|
||||||
|
excludeOnMLNo int,
|
||||||
|
limit int,
|
||||||
|
) ([]models.ProductionFirmCostHistoryRow, error) {
|
||||||
|
if nFirmaID <= 0 {
|
||||||
|
return []models.ProductionFirmCostHistoryRow{}, nil
|
||||||
|
}
|
||||||
|
if limit <= 0 {
|
||||||
|
limit = 100
|
||||||
|
}
|
||||||
|
if limit > 300 {
|
||||||
|
limit = 300
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := uretimDB.QueryContext(ctx, `
|
||||||
|
SELECT TOP (@p3)
|
||||||
|
M.nOnMLNo,
|
||||||
|
LTRIM(RTRIM(ISNULL(M.UrunKodu, ''))) AS UrunKodu,
|
||||||
|
ISNULL(M.UrunAdi, '') AS UrunAdi,
|
||||||
|
CONVERT(VARCHAR(10), COALESCE(M.Tarihi, M.dteKayitTarihi), 23) AS Tarihi,
|
||||||
|
SUM(CASE WHEN G.Grup = 'TP' THEN 1 ELSE 0 END) AS TPCount,
|
||||||
|
SUM(CASE WHEN G.Grup = 'DT' THEN 1 ELSE 0 END) AS DTCount,
|
||||||
|
COUNT(*) AS TotalRows
|
||||||
|
FROM dbo.spUrtOnMLMas M
|
||||||
|
INNER JOIN dbo.spUrtOnMLMasDet D
|
||||||
|
ON D.nOnMLNo = M.nOnMLNo
|
||||||
|
LEFT JOIN dbo.spUrtOnMLHammaddeTuru H
|
||||||
|
ON H.nHammaddeTuruNo = D.nHammaddeTuruNo
|
||||||
|
CROSS APPLY (
|
||||||
|
SELECT UPPER(ISNULL(NULLIF(LTRIM(RTRIM(D.sAciklama3)), ''), LTRIM(RTRIM(ISNULL(H.sAciklama3, ''))))) AS Grup
|
||||||
|
) G
|
||||||
|
WHERE ISNULL(M.nFirmaID, 0) = @p1
|
||||||
|
AND (ISNULL(@p2, 0) <= 0 OR M.nOnMLNo <> @p2)
|
||||||
|
AND G.Grup IN ('TP', 'DT')
|
||||||
|
GROUP BY M.nOnMLNo, M.UrunKodu, M.UrunAdi, M.Tarihi, M.dteKayitTarihi
|
||||||
|
ORDER BY COALESCE(M.Tarihi, M.dteKayitTarihi) DESC, M.nOnMLNo DESC
|
||||||
|
`, nFirmaID, excludeOnMLNo, limit)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
out := make([]models.ProductionFirmCostHistoryRow, 0, limit)
|
||||||
|
for rows.Next() {
|
||||||
|
var item models.ProductionFirmCostHistoryRow
|
||||||
|
if err := rows.Scan(&item.NOnMLNo, &item.UrunKodu, &item.UrunAdi, &item.Tarihi, &item.TPCount, &item.DTCount, &item.TotalRows); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out = append(out, item)
|
||||||
|
}
|
||||||
|
return out, rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
func GetProductionHasCostDetailRowsByOnMLNo(
|
func GetProductionHasCostDetailRowsByOnMLNo(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
uretimDB *sql.DB,
|
uretimDB *sql.DB,
|
||||||
|
|||||||
@@ -330,6 +330,32 @@ func GetProductionHasCostHistoryHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
_ = json.NewEncoder(w).Encode(list)
|
_ = json.NewEncoder(w).Encode(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET /api/pricing/production-product-costing/firm-cost-history
|
||||||
|
func GetProductionFirmCostHistoryHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
uretimDB := db.GetUretimDB()
|
||||||
|
if uretimDB == nil {
|
||||||
|
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nFirmaID, _ := strconv.Atoi(strings.TrimSpace(r.URL.Query().Get("n_firma_id")))
|
||||||
|
excludeOnMLNo, _ := strconv.Atoi(strings.TrimSpace(r.URL.Query().Get("exclude_onml_no")))
|
||||||
|
limit := parsePositiveIntOrDefault(r.URL.Query().Get("limit"), 100)
|
||||||
|
if nFirmaID <= 0 {
|
||||||
|
http.Error(w, "n_firma_id zorunlu ve pozitif sayi olmali", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := queries.GetProductionFirmCostHistory(r.Context(), uretimDB, nFirmaID, excludeOnMLNo, limit)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ProductionFirmCostHistory] query error: %v", err)
|
||||||
|
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ = json.NewEncoder(w).Encode(rows)
|
||||||
|
}
|
||||||
|
|
||||||
// GET /api/pricing/production-product-costing/has-cost-detail-groups
|
// GET /api/pricing/production-product-costing/has-cost-detail-groups
|
||||||
func GetProductionHasCostDetailGroupsHandler(w http.ResponseWriter, r *http.Request) {
|
func GetProductionHasCostDetailGroupsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
|||||||
@@ -134,6 +134,17 @@
|
|||||||
>
|
>
|
||||||
<q-tooltip v-if="!canDeleteCosting">Once maliyet olusturulunca aktif olur</q-tooltip>
|
<q-tooltip v-if="!canDeleteCosting">Once maliyet olusturulunca aktif olur</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
<q-btn
|
||||||
|
label="Malzemeleri Onceki Maliyetlerden Kopyala"
|
||||||
|
icon="content_copy"
|
||||||
|
dense
|
||||||
|
color="deep-purple-7"
|
||||||
|
outline
|
||||||
|
class="pcd-toolbar-btn"
|
||||||
|
:loading="firmCostHistoryLoading"
|
||||||
|
:disable="!detailHeader || detailLoading || saveLoading || bulkPriceLoading"
|
||||||
|
@click="openFirmCostHistoryDialog"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -690,6 +701,68 @@
|
|||||||
</div>
|
</div>
|
||||||
</q-page>
|
</q-page>
|
||||||
|
|
||||||
|
<q-dialog v-model="firmCostHistoryDialogOpen">
|
||||||
|
<q-card style="width: min(1600px, 98vw); max-width: 1600px;">
|
||||||
|
<q-card-section class="row items-center justify-between q-pb-sm">
|
||||||
|
<div>
|
||||||
|
<div class="text-subtitle1 text-weight-bold">Malzemeleri Onceki Maliyetlerden Kopyala</div>
|
||||||
|
<div class="text-caption text-grey-7">
|
||||||
|
HasCost listesinden bir maliyet secin. Yalnizca bos olan TP/DT gruplari aktarilir.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<q-btn flat round dense icon="close" v-close-popup />
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator />
|
||||||
|
<q-card-section class="q-pa-md">
|
||||||
|
<q-banner v-if="firmCostHistoryError" class="bg-red text-white q-mb-md">
|
||||||
|
Hata: {{ firmCostHistoryError }}
|
||||||
|
</q-banner>
|
||||||
|
<q-input
|
||||||
|
v-model="firmCostHistoryFilter"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
clearable
|
||||||
|
debounce="250"
|
||||||
|
label="Maliyet no, is emri, urun kodu veya urun adi ara"
|
||||||
|
class="q-mb-md"
|
||||||
|
>
|
||||||
|
<template #prepend><q-icon name="search" /></template>
|
||||||
|
</q-input>
|
||||||
|
<q-table
|
||||||
|
v-model:selected="firmCostHistorySelected"
|
||||||
|
:rows="firmCostHistoryRows"
|
||||||
|
:columns="firmCostHistoryColumns"
|
||||||
|
:loading="firmCostHistoryLoading"
|
||||||
|
:filter="firmCostHistoryFilter"
|
||||||
|
row-key="nOnMLNo"
|
||||||
|
selection="single"
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
bordered
|
||||||
|
no-data-label="Kopyalanabilecek maliyet kaydi bulunamadi"
|
||||||
|
:rows-per-page-options="[10, 25, 50, 0]"
|
||||||
|
>
|
||||||
|
</q-table>
|
||||||
|
<div class="text-caption text-grey-7 q-mt-sm">
|
||||||
|
Mevcut TP veya DT satirlari korunur. Sadece hic satiri olmayan TP/DT grubu, secilen maliyetten tum satir ozellikleriyle doldurulur.
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator />
|
||||||
|
<q-card-actions align="right" class="q-pa-sm">
|
||||||
|
<q-btn flat label="Iptal" color="grey-7" v-close-popup />
|
||||||
|
<q-btn
|
||||||
|
unelevated
|
||||||
|
color="deep-purple-7"
|
||||||
|
icon="content_copy"
|
||||||
|
label="Bos TP/DT Gruplarini Doldur"
|
||||||
|
:loading="firmCostCopyLoading"
|
||||||
|
:disable="firmCostHistorySelected.length !== 1"
|
||||||
|
@click="copyTPDTFromSelectedCost"
|
||||||
|
/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
|
||||||
<q-dialog v-model="rowEditorDialogOpen" persistent @show="resetRowEditorDialogPosition" @hide="stopRowEditorDialogDrag">
|
<q-dialog v-model="rowEditorDialogOpen" persistent @show="resetRowEditorDialogPosition" @hide="stopRowEditorDialogDrag">
|
||||||
<q-card class="pcd-row-editor-dialog" :style="rowEditorDialogStyle">
|
<q-card class="pcd-row-editor-dialog" :style="rowEditorDialogStyle">
|
||||||
<q-card-section
|
<q-card-section
|
||||||
@@ -1142,6 +1215,13 @@ const priceDeviationRows = ref([])
|
|||||||
const priceDeviationResolver = ref(null)
|
const priceDeviationResolver = ref(null)
|
||||||
const fabricCopyDialogOpen = ref(false)
|
const fabricCopyDialogOpen = ref(false)
|
||||||
const fabricCopySelectedKey = ref('')
|
const fabricCopySelectedKey = ref('')
|
||||||
|
const firmCostHistoryDialogOpen = ref(false)
|
||||||
|
const firmCostHistoryLoading = ref(false)
|
||||||
|
const firmCostCopyLoading = ref(false)
|
||||||
|
const firmCostHistoryError = ref('')
|
||||||
|
const firmCostHistoryRows = ref([])
|
||||||
|
const firmCostHistorySelected = ref([])
|
||||||
|
const firmCostHistoryFilter = ref('')
|
||||||
|
|
||||||
// Draggable "Satir Duzenle" dialog (mouse drag by header).
|
// Draggable "Satir Duzenle" dialog (mouse drag by header).
|
||||||
const rowEditorDialogPos = ref({ x: 0, y: 0 })
|
const rowEditorDialogPos = ref({ x: 0, y: 0 })
|
||||||
@@ -1388,6 +1468,21 @@ const priceCurrencyOptions = [
|
|||||||
{ label: 'EUR', value: 'EUR' },
|
{ label: 'EUR', value: 'EUR' },
|
||||||
{ label: 'GBP', value: 'GBP' }
|
{ label: 'GBP', value: 'GBP' }
|
||||||
]
|
]
|
||||||
|
const firmCostHistoryColumns = [
|
||||||
|
{ name: 'UretimSekli', label: 'Uretim Sekli', field: 'UretimSekli', align: 'left', sortable: true },
|
||||||
|
{ name: 'nUrtSiparisNo', label: 'Is Emri No', field: 'nUrtSiparisNo', align: 'left', sortable: true },
|
||||||
|
{ name: 'nOnMLNo', label: 'Maliyet No', field: 'nOnMLNo', align: 'right', sortable: true },
|
||||||
|
{ name: 'UrunKodu', label: 'Urun Kodu', field: 'UrunKodu', align: 'left', sortable: true },
|
||||||
|
{ name: 'UrunAdi', label: 'Urun Adi', field: 'UrunAdi', align: 'left', sortable: true },
|
||||||
|
{ name: 'Tarihi', label: 'Maliyet Tarihi', field: 'Tarihi', align: 'center', sortable: true, format: value => formatDateTR(value) },
|
||||||
|
{ name: 'lTutarTL', label: 'Tutar TL', field: 'lTutarTL', align: 'right', sortable: true, format: value => formatMoney(value) },
|
||||||
|
{ name: 'lTutarUSD', label: 'Tutar USD', field: 'lTutarUSD', align: 'right', sortable: true, format: value => formatMoney(value) },
|
||||||
|
{ name: 'IscilikTutari', label: 'Iscilik Tutari', field: 'IscilikTutari', align: 'right', sortable: true, format: value => formatMoney(value) },
|
||||||
|
{ name: 'IscilikPrBr', label: 'Iscilik Pr.Br', field: 'IscilikPrBr', align: 'center', sortable: true },
|
||||||
|
{ name: 'IscilikUSDTutari', label: 'Iscilik USD', field: 'IscilikUSDTutari', align: 'right', sortable: true, format: value => formatMoney(value) },
|
||||||
|
{ name: 'nUrtReceteID', label: 'Recete No', field: 'nUrtReceteID', align: 'right', sortable: true },
|
||||||
|
{ name: 'MaliyetDurumu', label: 'Maliyet Durumu', field: 'MaliyetDurumu', align: 'left', sortable: true }
|
||||||
|
]
|
||||||
const flatDetailRows = computed(() => detailGroups.value.flatMap(grp => Array.isArray(grp?.items) ? grp.items : []))
|
const flatDetailRows = computed(() => detailGroups.value.flatMap(grp => Array.isArray(grp?.items) ? grp.items : []))
|
||||||
const priceDeviationAllSelected = computed(() => {
|
const priceDeviationAllSelected = computed(() => {
|
||||||
const list = Array.isArray(priceDeviationRows.value) ? priceDeviationRows.value : []
|
const list = Array.isArray(priceDeviationRows.value) ? priceDeviationRows.value : []
|
||||||
@@ -4935,6 +5030,116 @@ async function confirmBrPriceDeviationIfNeeded () {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isTPDTGroupName (value) {
|
||||||
|
const group = normalizeGroupName(value)
|
||||||
|
return group === 'TP' || group === 'DT'
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openFirmCostHistoryDialog () {
|
||||||
|
firmCostHistoryDialogOpen.value = true
|
||||||
|
firmCostHistoryLoading.value = true
|
||||||
|
firmCostHistoryError.value = ''
|
||||||
|
firmCostHistoryRows.value = []
|
||||||
|
firmCostHistorySelected.value = []
|
||||||
|
firmCostHistoryFilter.value = ''
|
||||||
|
try {
|
||||||
|
const data = await get('/pricing/production-product-costing/has-cost-products', {
|
||||||
|
search: '',
|
||||||
|
offset: 0,
|
||||||
|
limit: 1000,
|
||||||
|
trace_id: traceId.value
|
||||||
|
})
|
||||||
|
const currentNo = parseInt(String(onMLNo.value || detailHeader.value?.nOnMLNo || '0'), 10) || 0
|
||||||
|
firmCostHistoryRows.value = (Array.isArray(data) ? data : [])
|
||||||
|
.filter(row => (parseInt(String(row?.nOnMLNo || '0'), 10) || 0) !== currentNo)
|
||||||
|
} catch (err) {
|
||||||
|
firmCostHistoryError.value = await extractApiErrorDetail(err)
|
||||||
|
} finally {
|
||||||
|
firmCostHistoryLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmFirmCostCopy (source) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
$q.dialog({
|
||||||
|
title: 'TP/DT Malzemelerini Kopyala',
|
||||||
|
message: `${source?.UrunKodu || '-'} / Maliyet No ${source?.nOnMLNo || '-'} kaydindan yalnizca bos olan TP/DT gruplari tum ozellikleriyle doldurulacak. Devam edilsin mi?`,
|
||||||
|
cancel: { label: 'Vazgec', flat: true },
|
||||||
|
ok: { label: 'Kopyala', color: 'deep-purple-7' },
|
||||||
|
persistent: true
|
||||||
|
}).onOk(() => resolve(true)).onCancel(() => resolve(false)).onDismiss(() => resolve(false))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyTPDTFromSelectedCost () {
|
||||||
|
const source = firmCostHistorySelected.value[0]
|
||||||
|
const sourceOnMLNo = parseInt(String(source?.nOnMLNo || '0'), 10) || 0
|
||||||
|
if (!sourceOnMLNo) return
|
||||||
|
if (!(await confirmFirmCostCopy(source))) return
|
||||||
|
|
||||||
|
firmCostCopyLoading.value = true
|
||||||
|
firmCostHistoryError.value = ''
|
||||||
|
try {
|
||||||
|
const sourceData = await get('/pricing/production-product-costing/has-cost-detail-groups', {
|
||||||
|
n_onml_no: sourceOnMLNo,
|
||||||
|
trace_id: traceId.value
|
||||||
|
})
|
||||||
|
const sourceGroups = normalizeDetailGroups(sourceData).filter(group => isTPDTGroupName(group?.sAciklama3))
|
||||||
|
const populatedGroups = new Set(
|
||||||
|
flatDetailRows.value
|
||||||
|
.filter(row => isTPDTGroupName(row?.sAciklama3))
|
||||||
|
.map(row => normalizeGroupName(row?.sAciklama3))
|
||||||
|
)
|
||||||
|
const groupsToCopy = sourceGroups.filter(group => !populatedGroups.has(normalizeGroupName(group?.sAciklama3)))
|
||||||
|
const sourceRows = groupsToCopy.flatMap(group => (
|
||||||
|
(Array.isArray(group?.items) ? group.items : []).map(row => ({ group, row }))
|
||||||
|
))
|
||||||
|
if (sourceRows.length === 0) {
|
||||||
|
firmCostHistoryError.value = populatedGroups.has('TP') && populatedGroups.has('DT')
|
||||||
|
? 'Mevcut maliyette TP ve DT gruplari zaten dolu. Hicbir satir degistirilmedi.'
|
||||||
|
: 'Secilen maliyette bos gruplari dolduracak TP/DT satiri bulunamadi.'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceRows.forEach(({ group, row }) => {
|
||||||
|
newRowSequence.value += 1
|
||||||
|
const copiedRow = recalculateDetailRow({
|
||||||
|
...row,
|
||||||
|
__rowKey: `firm-history-copy-${sourceOnMLNo}-${newRowSequence.value}`,
|
||||||
|
isNew: true,
|
||||||
|
nOnMLNo: detailHeader.value?.nOnMLNo || onMLNo.value || '',
|
||||||
|
nOnMLDetNo: getNextDetailNo(),
|
||||||
|
sAciklama3: normalizeGroupName(group?.sAciklama3 || row?.sAciklama3),
|
||||||
|
requiredPlaceholder: false,
|
||||||
|
draftChanged: true,
|
||||||
|
__copiedFromOnMLNo: sourceOnMLNo
|
||||||
|
}, {
|
||||||
|
preserveInputs: true,
|
||||||
|
priceType: 'COPY',
|
||||||
|
updateState: 'firm-history-copy',
|
||||||
|
markChanged: true
|
||||||
|
})
|
||||||
|
applyEditorRowToGroups(copiedRow)
|
||||||
|
})
|
||||||
|
|
||||||
|
recalculateAllDetailRows()
|
||||||
|
syncAllGroupsOpen()
|
||||||
|
schedulePersistLocalDraft()
|
||||||
|
triggerUIUpdate()
|
||||||
|
firmCostHistoryDialogOpen.value = false
|
||||||
|
$q.notify({
|
||||||
|
type: 'positive',
|
||||||
|
message: `${groupsToCopy.map(group => normalizeGroupName(group?.sAciklama3)).join(' ve ')} gruplarindaki ${sourceRows.length} satir ${source?.UrunKodu || ''} maliyetinden tum ozellikleriyle eklendi. Kaydet butonu ile onaylayabilirsiniz.`,
|
||||||
|
position: 'top-right',
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
firmCostHistoryError.value = await extractApiErrorDetail(err)
|
||||||
|
} finally {
|
||||||
|
firmCostCopyLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function deleteCosting () {
|
async function deleteCosting () {
|
||||||
if (!detailHeader.value) return
|
if (!detailHeader.value) return
|
||||||
const n = parseInt(String(detailHeader.value?.nOnMLNo || detailHeader.value?.NOnMLNo || onMLNo.value || '0'), 10) || 0
|
const n = parseInt(String(detailHeader.value?.nOnMLNo || detailHeader.value?.NOnMLNo || onMLNo.value || '0'), 10) || 0
|
||||||
|
|||||||
Reference in New Issue
Block a user