Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -10,90 +10,62 @@ import (
|
||||
)
|
||||
|
||||
// DETAIL (ALT TABLO)
|
||||
func GetStatementDetails(ctx context.Context, accountCode, startDate, endDate string, parislemler []string) ([]models.StatementDetail, error) {
|
||||
inParislem := ""
|
||||
if len(parislemler) > 0 {
|
||||
pp := make([]string, len(parislemler))
|
||||
for i, v := range parislemler {
|
||||
pp[i] = strings.TrimSpace(v)
|
||||
}
|
||||
inParislem = strings.Join(pp, ",")
|
||||
}
|
||||
|
||||
piyasaScope, err := buildPiyasaExistsForCariCode(ctx, "a.CurrAccCode")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`
|
||||
func GetStatementDetails(ctx context.Context, belgeNo string) ([]models.StatementDetail, error) {
|
||||
query := `
|
||||
SELECT
|
||||
CONVERT(varchar(10), a.InvoiceDate, 23) AS Belge_Tarihi,
|
||||
a.InvoiceNumber AS Belge_Ref_Numarasi,
|
||||
COALESCE(MAX(AnaGrupDesc.AttributeDescription), '') AS Urun_Ana_Grubu,
|
||||
COALESCE(MAX(AltGrupDesc.AttributeDescription), '') AS Urun_Alt_Grubu,
|
||||
COALESCE(MAX(GarsonDesc.AttributeDescription), '') AS Yetiskin_Garson,
|
||||
COALESCE(MAX(FitDesc.AttributeDescription), '') AS Fit,
|
||||
COALESCE(MAX(KisaKarDesc.AttributeDescription), '') AS Icerik,
|
||||
a.ItemCode AS Urun_Kodu,
|
||||
a.ColorCode AS Urun_Rengi,
|
||||
SUM(a.Qty1) AS Toplam_Adet,
|
||||
CAST(SUM(a.Qty1 * ABS(a.Doc_Price)) / NULLIF(SUM(a.Qty1),0) AS numeric(18,4)) AS Doviz_Fiyat,
|
||||
COALESCE(MAX(AnaGrupDesc.AttributeDescription), '') AS Urun_Ana_Grubu,
|
||||
COALESCE(MAX(AltGrupDesc.AttributeDescription), '') AS Urun_Alt_Grubu,
|
||||
COALESCE(MAX(GarsonDesc.AttributeDescription), '') AS Yetiskin_Garson,
|
||||
COALESCE(MAX(FitDesc.AttributeDescription), '') AS Fit,
|
||||
COALESCE(MAX(KisaKarDesc.AttributeDescription), '') AS Icerik,
|
||||
a.ItemCode AS Urun_Kodu,
|
||||
a.ColorCode AS Urun_Rengi,
|
||||
SUM(a.Qty1) AS Toplam_Adet,
|
||||
SUM(ABS(a.Doc_Price)) AS Toplam_Fiyat,
|
||||
CAST(SUM(a.Qty1 * ABS(a.Doc_Price)) AS numeric(18,2)) AS Toplam_Tutar
|
||||
FROM AllInvoicesWithAttributes a
|
||||
LEFT JOIN prItemAttribute AnaGrup
|
||||
ON a.ItemCode = AnaGrup.ItemCode AND AnaGrup.AttributeTypeCode = 1
|
||||
ON a.ItemCode = AnaGrup.ItemCode AND AnaGrup.AttributeTypeCode = 1
|
||||
LEFT JOIN cdItemAttributeDesc AnaGrupDesc
|
||||
ON AnaGrup.AttributeTypeCode = AnaGrupDesc.AttributeTypeCode
|
||||
AND AnaGrup.AttributeCode = AnaGrupDesc.AttributeCode
|
||||
AND AnaGrup.ItemTypeCode = AnaGrupDesc.ItemTypeCode
|
||||
ON AnaGrup.AttributeTypeCode = AnaGrupDesc.AttributeTypeCode
|
||||
AND AnaGrup.AttributeCode = AnaGrupDesc.AttributeCode
|
||||
AND AnaGrup.ItemTypeCode = AnaGrupDesc.ItemTypeCode
|
||||
|
||||
LEFT JOIN prItemAttribute AltGrup
|
||||
ON a.ItemCode = AltGrup.ItemCode AND AltGrup.AttributeTypeCode = 2
|
||||
ON a.ItemCode = AltGrup.ItemCode AND AltGrup.AttributeTypeCode = 2
|
||||
LEFT JOIN cdItemAttributeDesc AltGrupDesc
|
||||
ON AltGrup.AttributeTypeCode = AltGrupDesc.AttributeTypeCode
|
||||
AND AltGrup.AttributeCode = AltGrupDesc.AttributeCode
|
||||
AND AltGrup.ItemTypeCode = AltGrupDesc.ItemTypeCode
|
||||
ON AltGrup.AttributeTypeCode = AltGrupDesc.AttributeTypeCode
|
||||
AND AltGrup.AttributeCode = AltGrupDesc.AttributeCode
|
||||
AND AltGrup.ItemTypeCode = AltGrupDesc.ItemTypeCode
|
||||
|
||||
LEFT JOIN prItemAttribute Garson
|
||||
ON a.ItemCode = Garson.ItemCode AND Garson.AttributeTypeCode = 44
|
||||
ON a.ItemCode = Garson.ItemCode AND Garson.AttributeTypeCode = 44
|
||||
LEFT JOIN cdItemAttributeDesc GarsonDesc
|
||||
ON Garson.AttributeTypeCode = GarsonDesc.AttributeTypeCode
|
||||
AND Garson.AttributeCode = GarsonDesc.AttributeCode
|
||||
AND Garson.ItemTypeCode = GarsonDesc.ItemTypeCode
|
||||
ON Garson.AttributeTypeCode = GarsonDesc.AttributeTypeCode
|
||||
AND Garson.AttributeCode = GarsonDesc.AttributeCode
|
||||
AND Garson.ItemTypeCode = GarsonDesc.ItemTypeCode
|
||||
|
||||
LEFT JOIN prItemAttribute FitTbl
|
||||
ON a.ItemCode = FitTbl.ItemCode AND FitTbl.AttributeTypeCode = 38
|
||||
ON a.ItemCode = FitTbl.ItemCode AND FitTbl.AttributeTypeCode = 38
|
||||
LEFT JOIN cdItemAttributeDesc FitDesc
|
||||
ON FitTbl.AttributeTypeCode = FitDesc.AttributeTypeCode
|
||||
AND FitTbl.AttributeCode = FitDesc.AttributeCode
|
||||
AND FitTbl.ItemTypeCode = FitDesc.ItemTypeCode
|
||||
ON FitTbl.AttributeTypeCode = FitDesc.AttributeTypeCode
|
||||
AND FitTbl.AttributeCode = FitDesc.AttributeCode
|
||||
AND FitTbl.ItemTypeCode = FitDesc.ItemTypeCode
|
||||
|
||||
LEFT JOIN prItemAttribute KisaKar
|
||||
ON a.ItemCode = KisaKar.ItemCode AND KisaKar.AttributeTypeCode = 41
|
||||
ON a.ItemCode = KisaKar.ItemCode AND KisaKar.AttributeTypeCode = 41
|
||||
LEFT JOIN cdItemAttributeDesc KisaKarDesc
|
||||
ON KisaKar.AttributeTypeCode = KisaKarDesc.AttributeTypeCode
|
||||
AND KisaKar.AttributeCode = KisaKarDesc.AttributeCode
|
||||
AND KisaKar.ItemTypeCode = KisaKarDesc.ItemTypeCode
|
||||
WHERE REPLACE(a.CurrAccCode, ' ', '') LIKE REPLACE(@Carikod, ' ', '') + '%%'
|
||||
AND a.InvoiceDate BETWEEN @StartDate AND @EndDate
|
||||
AND %s
|
||||
%s
|
||||
ON KisaKar.AttributeTypeCode = KisaKarDesc.AttributeTypeCode
|
||||
AND KisaKar.AttributeCode = KisaKarDesc.AttributeCode
|
||||
AND KisaKar.ItemTypeCode = KisaKarDesc.ItemTypeCode
|
||||
WHERE LTRIM(RTRIM(a.InvoiceNumber)) = LTRIM(RTRIM(@BelgeNo))
|
||||
GROUP BY a.InvoiceDate, a.InvoiceNumber, a.ItemCode, a.ColorCode
|
||||
ORDER BY Belge_Tarihi, Belge_Ref_Numarasi, Urun_Kodu;`,
|
||||
piyasaScope,
|
||||
func() string {
|
||||
if inParislem == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(`AND EXISTS (
|
||||
SELECT 1
|
||||
FROM CurrAccBookATAttributesFilter f
|
||||
WHERE f.CurrAccBookID = a.CurrAccBookID
|
||||
AND f.ATAtt01 IN (%s)
|
||||
)`, inParislem)
|
||||
}(),
|
||||
)
|
||||
ORDER BY Belge_Tarihi, Belge_Ref_Numarasi, Urun_Kodu;`
|
||||
|
||||
rows, err := db.MssqlDB.QueryContext(ctx, query,
|
||||
sql.Named("Carikod", normalizeMasterAccountCode(accountCode)),
|
||||
sql.Named("StartDate", startDate),
|
||||
sql.Named("EndDate", endDate),
|
||||
sql.Named("BelgeNo", strings.TrimSpace(belgeNo)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("detay sorgu hatasi: %v", err)
|
||||
|
||||
@@ -18,21 +18,15 @@ func GetStatementDetailsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
accountCode := vars["accountCode"]
|
||||
if accountCode == "" {
|
||||
accountCode = vars["id"]
|
||||
}
|
||||
if accountCode == "" {
|
||||
http.Error(w, "account code is required", http.StatusBadRequest)
|
||||
_ = mux.Vars(r)
|
||||
|
||||
belgeNo := r.URL.Query().Get("belgeno")
|
||||
if belgeNo == "" {
|
||||
http.Error(w, "belgeno is required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
startDate := r.URL.Query().Get("startdate")
|
||||
endDate := r.URL.Query().Get("enddate")
|
||||
parislemler := r.URL.Query()["parislemler"]
|
||||
|
||||
details, err := queries.GetStatementDetails(r.Context(), accountCode, startDate, endDate, parislemler)
|
||||
details, err := queries.GetStatementDetails(r.Context(), belgeNo)
|
||||
if err != nil {
|
||||
http.Error(w, "Error fetching statement details: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
||||
@@ -240,13 +240,13 @@
|
||||
|
||||
<!-- Detay tablosu -->
|
||||
<q-tr
|
||||
v-if="props.row._type === 'data' && expandedRows[props.row.belge_no]"
|
||||
v-if="props.row._type === 'data' && expandedRows[getRowExpandKey(props.row)]"
|
||||
class="sub-row"
|
||||
>
|
||||
<q-td colspan="100%">
|
||||
<q-table
|
||||
:rows="detailStore.getDetailsByBelge(props.row.belge_no)"
|
||||
:columns="detailColumns(props.row.belge_no)"
|
||||
:rows="detailStore.getDetailsByRowKey(getRowExpandKey(props.row))"
|
||||
:columns="detailColumns(getRowExpandKey(props.row))"
|
||||
row-key="Urun_Kodu"
|
||||
flat
|
||||
dense
|
||||
@@ -387,8 +387,8 @@ function buildColumns(data) {
|
||||
|
||||
const columns = computed(() => buildColumns(statementheaderStore.headers))
|
||||
|
||||
function detailColumns(belgeNo) {
|
||||
const details = detailStore.getDetailsByBelge(belgeNo)
|
||||
function detailColumns(rowOrBelgeNo) {
|
||||
const details = detailStore.getDetailsByRowKey(rowOrBelgeNo)
|
||||
return buildColumns(details)
|
||||
}
|
||||
|
||||
@@ -417,33 +417,57 @@ async function onFilterClick() {
|
||||
excludeopening: excludeOpening.value
|
||||
})
|
||||
|
||||
await detailStore.loadDetails({
|
||||
accountCode: selectedCari.value,
|
||||
startDate: dateFrom.value,
|
||||
endDate: dateTo.value,
|
||||
parislemler: selectedMonType.value
|
||||
})
|
||||
}
|
||||
|
||||
/* Grup satırları için özel rowKey */
|
||||
const rowKeyFn = (row) =>
|
||||
row._type === 'group' ? `grp-${row.para_birimi}` : row.belge_no
|
||||
row._type === 'group' ? `grp-${row.para_birimi}` : getRowExpandKey(row)
|
||||
|
||||
function getRowExpandKey (row) {
|
||||
return [
|
||||
String(row?.belge_no || '').trim(),
|
||||
String(row?.belge_tarihi || '').trim(),
|
||||
String(row?.para_birimi || '').trim(),
|
||||
String(row?.islem_tipi || '').trim(),
|
||||
String(row?.cari_kod || '').trim()
|
||||
].join('|')
|
||||
}
|
||||
|
||||
/* Detay açma sadece expand kontrolü */
|
||||
function toggleRowDetails(row) {
|
||||
async function toggleRowDetails(row) {
|
||||
if (row._type === 'group') return
|
||||
expandedRows.value[row.belge_no] = !expandedRows.value[row.belge_no]
|
||||
const key = getRowExpandKey(row)
|
||||
const next = !expandedRows.value[key]
|
||||
expandedRows.value[key] = next
|
||||
|
||||
if (!next) return
|
||||
if (!row?.belge_no || String(row.belge_no).trim() === 'Baslangic_devir') return
|
||||
if (detailStore.hasDetailsByRowKey(key)) return
|
||||
|
||||
await detailStore.loadDetails({
|
||||
accountCode: selectedCari.value,
|
||||
belgeNo: row.belge_no,
|
||||
rowKey: key
|
||||
})
|
||||
}
|
||||
|
||||
/* Tüm detayları aç/kapat */
|
||||
function toggleAllDetails() {
|
||||
async function toggleAllDetails() {
|
||||
allDetailsOpen.value = !allDetailsOpen.value
|
||||
if (allDetailsOpen.value) {
|
||||
const dataRows = []
|
||||
for (const row of statementheaderStore.headers) {
|
||||
if (row.belge_no) {
|
||||
expandedRows.value[row.belge_no] = true
|
||||
const key = getRowExpandKey(row)
|
||||
expandedRows.value[key] = true
|
||||
dataRows.push(row)
|
||||
}
|
||||
}
|
||||
await detailStore.preloadForRows({
|
||||
accountCode: selectedCari.value,
|
||||
rows: dataRows,
|
||||
getRowKey: getRowExpandKey
|
||||
})
|
||||
} else {
|
||||
expandedRows.value = {}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,16 @@ import api from 'src/services/api'
|
||||
|
||||
export const useStatementdetailStore = defineStore('statementdetail', {
|
||||
state: () => ({
|
||||
details: [],
|
||||
detailsByRow: {},
|
||||
detailsByBelge: {},
|
||||
loading: false,
|
||||
error: null
|
||||
}),
|
||||
|
||||
actions: {
|
||||
async loadDetails ({ accountCode, startDate, endDate, parislemler }) {
|
||||
async loadDetails ({ accountCode, belgeNo, rowKey }) {
|
||||
if (!accountCode) {
|
||||
this.error = 'Geçerli bir cari kod seçilmedi.'
|
||||
this.error = 'Gecerli bir cari kod secilmedi.'
|
||||
return
|
||||
}
|
||||
|
||||
@@ -20,46 +21,74 @@ export const useStatementdetailStore = defineStore('statementdetail', {
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
// ✅ Params (arrayFormat=repeat global)
|
||||
const params = {
|
||||
startdate: startDate,
|
||||
enddate: endDate
|
||||
const normalizedBelgeNo = String(belgeNo || '').trim()
|
||||
const params = { belgeno: normalizedBelgeNo }
|
||||
|
||||
if (this.detailsByBelge[normalizedBelgeNo]) {
|
||||
const keyCached = String(rowKey || '').trim()
|
||||
if (keyCached) {
|
||||
this.detailsByRow[keyCached] = this.detailsByBelge[normalizedBelgeNo]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (Array.isArray(parislemler) && parislemler.length > 0) {
|
||||
params.parislemler = parislemler.filter(
|
||||
p => p !== undefined && p !== null && p !== ''
|
||||
)
|
||||
}
|
||||
|
||||
// 🔐 TOKEN + SERIALIZER + ERROR HANDLING OTOMATİK
|
||||
const res = await api.get(
|
||||
`/statements/${accountCode}/details`,
|
||||
`/statements/${encodeURIComponent(accountCode)}/details`,
|
||||
{ params }
|
||||
)
|
||||
|
||||
this.details = res.data || []
|
||||
|
||||
const key = String(rowKey || '').trim()
|
||||
const rows = Array.isArray(res.data) ? res.data : []
|
||||
if (normalizedBelgeNo) {
|
||||
this.detailsByBelge[normalizedBelgeNo] = rows
|
||||
}
|
||||
if (key) {
|
||||
this.detailsByRow[key] = rows
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('❌ Details yüklenemedi:', err)
|
||||
console.error('Details yuklenemedi:', err)
|
||||
this.error =
|
||||
err?.data?.message ||
|
||||
err?.message ||
|
||||
'Detaylar yüklenemedi'
|
||||
'Detaylar yuklenemedi'
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
getDetailsByBelge (belgeNo) {
|
||||
const needle = String(belgeNo || '').trim()
|
||||
return this.details.filter(
|
||||
d => String(d.belge_ref_numarasi || '').trim() === needle
|
||||
)
|
||||
hasDetailsByRowKey (rowKey) {
|
||||
const key = String(rowKey || '').trim()
|
||||
return Array.isArray(this.detailsByRow[key])
|
||||
},
|
||||
|
||||
getDetailsByRowKey (rowKey) {
|
||||
const key = String(rowKey || '').trim()
|
||||
return this.detailsByRow[key] || []
|
||||
},
|
||||
|
||||
async preloadForRows ({ accountCode, rows, getRowKey }) {
|
||||
const tasks = []
|
||||
|
||||
for (const row of rows || []) {
|
||||
const belgeNo = String(row?.belge_no || '').trim()
|
||||
if (!belgeNo || belgeNo === 'Baslangic_devir') continue
|
||||
|
||||
const rowKey = String(getRowKey(row) || '').trim()
|
||||
if (!rowKey) continue
|
||||
if (this.hasDetailsByRowKey(rowKey)) continue
|
||||
|
||||
tasks.push(
|
||||
this.loadDetails({ accountCode, belgeNo, rowKey })
|
||||
)
|
||||
}
|
||||
|
||||
if (tasks.length === 0) return
|
||||
await Promise.all(tasks)
|
||||
},
|
||||
|
||||
reset () {
|
||||
this.details = []
|
||||
this.detailsByRow = {}
|
||||
this.detailsByBelge = {}
|
||||
this.loading = false
|
||||
this.error = null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user