Files
bssapp/svc/queries/statements_pdf.go
2026-02-11 17:46:22 +03:00

306 lines
9.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// queries/statements_pdf.go
package queries
import (
"bssapp-backend/db"
"bssapp-backend/models"
"database/sql"
"fmt"
"log"
"strings"
)
// küçük yardımcı: boşlukları temizle, her değeri ayrı tırnakla sar
func buildQuotedList(vals []string) string {
var pp []string
for _, v := range vals {
v = strings.TrimSpace(v)
if v != "" {
pp = append(pp, fmt.Sprintf("'%s'", v)) // '1','2' gibi
}
}
if len(pp) == 0 {
return ""
}
return strings.Join(pp, ",")
}
/* ============================ HEADER (Ana Tablo) ============================ */
func GetStatementsPDF(accountCode, startDate, endDate string, parislemler []string) ([]models.StatementHeader, []string, error) {
// Account normalize
if len(accountCode) == 7 && strings.ContainsAny(accountCode, "0123456789") {
accountCode = accountCode[:3] + " " + accountCode[3:]
}
// IN list parse et
inList := buildQuotedList(parislemler)
parislemCond := "''"
if inList != "" {
parislemCond = inList
}
query := fmt.Sprintf(`
;WITH Opening AS (
SELECT
b.CurrAccCode AS Cari_Kod,
b.DocCurrencyCode AS Para_Birimi,
SUM(c.Debit - c.Credit) AS Devir_Bakiyesi
FROM trCurrAccBook b
LEFT JOIN trCurrAccBookCurrency c
ON c.CurrAccBookID = b.CurrAccBookID
AND c.CurrencyCode = b.DocCurrencyCode
WHERE b.CurrAccCode LIKE @Carikod
AND b.DocumentDate < @StartDate
AND EXISTS (
SELECT 1
FROM CurrAccBookATAttributesFilter f2
WHERE f2.CurrAccBookID = b.CurrAccBookID
AND f2.ATAtt01 IN (%s)
)
GROUP BY b.CurrAccCode, b.DocCurrencyCode
),
Movements AS (
SELECT
b.CurrAccCode AS Cari_Kod,
d.CurrAccDescription AS Cari_Isim,
CONVERT(varchar(10), b.DocumentDate, 23) AS Belge_Tarihi,
CONVERT(varchar(10), b.DueDate, 23) AS Vade_Tarihi,
b.RefNumber AS Belge_No,
b.BaseApplicationCode AS Islem_Tipi,
b.LineDescription AS Aciklama,
b.DocCurrencyCode AS Para_Birimi,
c.Debit AS Borc,
c.Credit AS Alacak,
SUM(c.Debit - c.Credit)
OVER (PARTITION BY b.CurrAccCode, c.CurrencyCode
ORDER BY b.DocumentDate, b.CurrAccBookID) AS Hareket_Bakiyesi,
f.ATAtt01 AS Parislemler
FROM trCurrAccBook b
LEFT JOIN cdCurrAccDesc d
ON b.CurrAccCode = d.CurrAccCode AND d.LangCode = 'TR'
LEFT JOIN trCurrAccBookCurrency c
ON b.CurrAccBookID = c.CurrAccBookID
AND b.DocCurrencyCode = c.CurrencyCode
LEFT JOIN CurrAccBookATAttributesFilter f
ON b.CurrAccBookID = f.CurrAccBookID
WHERE b.CurrAccCode LIKE @Carikod
AND b.DocumentDate BETWEEN @StartDate AND @EndDate
AND EXISTS (
SELECT 1
FROM CurrAccBookATAttributesFilter f2
WHERE f2.CurrAccBookID = b.CurrAccBookID
AND f2.ATAtt01 IN (%s)
)
)`, parislemCond, parislemCond)
query += fmt.Sprintf(`
SELECT
m.Cari_Kod,
m.Cari_Isim,
m.Belge_Tarihi,
m.Vade_Tarihi,
m.Belge_No,
m.Islem_Tipi,
m.Aciklama,
m.Para_Birimi,
m.Borc,
m.Alacak,
ISNULL(o.Devir_Bakiyesi,0) + m.Hareket_Bakiyesi AS Bakiye,
m.Parislemler
FROM Movements m
LEFT JOIN Opening o
ON o.Cari_Kod = m.Cari_Kod
AND o.Para_Birimi = m.Para_Birimi
UNION ALL
-- Devir satırı
SELECT
@Carikod AS Cari_Kod,
MAX(d.CurrAccDescription) AS Cari_Isim,
CONVERT(varchar(10), @StartDate, 23) AS Belge_Tarihi,
CONVERT(varchar(10), @StartDate, 23) AS Vade_Tarihi,
'Baslangic_devir' AS Belge_No,
'Devir' AS Islem_Tipi,
'Devir Bakiyesi' AS Aciklama,
b.DocCurrencyCode AS Para_Birimi,
SUM(c.Debit) AS Borc,
SUM(c.Credit) AS Alacak,
SUM(c.Debit) - SUM(c.Credit) AS Bakiye,
(
SELECT STRING_AGG(x.ATAtt01, ',')
FROM (
SELECT DISTINCT f2.ATAtt01
FROM CurrAccBookATAttributesFilter f2
INNER JOIN trCurrAccBook bb
ON f2.CurrAccBookID = bb.CurrAccBookID
WHERE bb.CurrAccCode LIKE @Carikod
AND bb.DocumentDate < @StartDate
AND f2.ATAtt01 IN (%s)
) x
) AS Parislemler
FROM trCurrAccBook b
LEFT JOIN cdCurrAccDesc d
ON b.CurrAccCode = d.CurrAccCode AND d.LangCode = 'TR'
LEFT JOIN trCurrAccBookCurrency c
ON b.CurrAccBookID = c.CurrAccBookID
AND b.DocCurrencyCode = c.CurrencyCode
WHERE b.CurrAccCode LIKE @Carikod
AND b.DocumentDate < @StartDate
GROUP BY b.DocCurrencyCode
ORDER BY Para_Birimi, Belge_Tarihi;`, parislemCond)
rows, err := db.MssqlDB.Query(query,
sql.Named("Carikod", "%"+accountCode+"%"),
sql.Named("StartDate", startDate),
sql.Named("EndDate", endDate),
)
if err != nil {
log.Printf("❌ Header sorgu hatası: %v", err)
return nil, nil, fmt.Errorf("header sorgu hatası: %v", err)
}
defer rows.Close()
var headers []models.StatementHeader
var belgeNos []string
for rows.Next() {
var h models.StatementHeader
if err := rows.Scan(
&h.CariKod, &h.CariIsim,
&h.BelgeTarihi, &h.VadeTarihi,
&h.BelgeNo, &h.IslemTipi,
&h.Aciklama, &h.ParaBirimi,
&h.Borc, &h.Alacak,
&h.Bakiye, &h.Parislemler,
); err != nil {
log.Printf("❌ Header scan hatası: %v", err)
return nil, nil, err
}
headers = append(headers, h)
if h.BelgeNo != "" {
belgeNos = append(belgeNos, h.BelgeNo)
}
}
log.Printf("✅ Header verileri alındı: %d kayıt, %d belge no", len(headers), len(belgeNos))
return headers, belgeNos, nil
}
/* ============================ DETAIL (Alt Tablo) ============================ */
func GetDetailsMapPDF(belgeNos []string, startDate, endDate string) (map[string][]models.StatementDetail, error) {
result := make(map[string][]models.StatementDetail)
if len(belgeNos) == 0 {
log.Println("⚠️ GetDetailsMapPDF: belge listesi boş")
return result, nil
}
qs := make([]string, 0, len(belgeNos))
for _, no := range belgeNos {
safe := strings.ReplaceAll(no, "'", "''")
qs = append(qs, fmt.Sprintf("'%s'", safe))
}
inBelge := strings.Join(qs, ",")
query := fmt.Sprintf(`
;WITH BookMap AS (
SELECT b.RefNumber AS InvoiceNumber, b.CurrAccBookID
FROM trCurrAccBook b
WHERE b.RefNumber IN (%s)
)
SELECT
CONVERT(varchar(10), a.InvoiceDate, 23) AS Belge_Tarihi,
a.InvoiceNumber AS Belge_Ref_Numarasi,
MAX(ISNULL(AnaGrupDesc.AttributeDescription, '')) AS Urun_Ana_Grubu,
MAX(ISNULL(AltGrupDesc.AttributeDescription, '')) AS Urun_Alt_Grubu,
MAX(ISNULL(GarsonDesc.AttributeDescription, '')) AS Yetiskin_Garson,
MAX(ISNULL(FitDesc.AttributeDescription, '')) AS Fit,
MAX(ISNULL(KisaKarDesc.AttributeDescription, '')) AS Icerik,
a.ItemCode, a.ColorCode,
SUM(a.Qty1), SUM(ABS(a.Doc_Price)),
CAST(SUM(a.Qty1 * ABS(a.Doc_Price)) AS numeric(18,2))
FROM AllInvoicesWithAttributes a
JOIN BookMap bm
ON bm.InvoiceNumber = a.InvoiceNumber
-- Ana Grup
LEFT JOIN prItemAttribute AnaGrup
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
-- Alt Grup
LEFT JOIN prItemAttribute AltGrup
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
-- Garson
LEFT JOIN prItemAttribute Garson
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
-- Fit
LEFT JOIN prItemAttribute FitTbl
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
-- Kısa Karışım
LEFT JOIN prItemAttribute KisaKar
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 a.InvoiceDate BETWEEN @StartDate AND @EndDate
GROUP BY a.InvoiceDate, a.InvoiceNumber, a.ItemCode, a.ColorCode
ORDER BY a.InvoiceNumber, a.ItemCode, a.ColorCode;`, inBelge)
rows, err := db.MssqlDB.Query(query,
sql.Named("StartDate", startDate),
sql.Named("EndDate", endDate),
)
if err != nil {
log.Printf("❌ Detay sorgu hatası: %v", err)
return nil, fmt.Errorf("detay sorgu hatası: %v", err)
}
defer rows.Close()
for rows.Next() {
var d models.StatementDetail
if err := rows.Scan(
&d.BelgeTarihi,
&d.BelgeRefNumarasi,
&d.UrunAnaGrubu,
&d.UrunAltGrubu,
&d.YetiskinGarson,
&d.Fit,
&d.Icerik,
&d.UrunKodu,
&d.UrunRengi,
&d.ToplamAdet,
&d.ToplamFiyat,
&d.ToplamTutar,
); err != nil {
log.Printf("❌ Detay scan hatası: %v", err)
return nil, err
}
result[d.BelgeRefNumarasi] = append(result[d.BelgeRefNumarasi], d)
}
log.Printf("✅ Detay verileri alındı: %d belge için detay var", len(result))
return result, nil
}