Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-06-04 14:33:10 +03:00
parent 00626152c2
commit 7b1588d69d
11 changed files with 2065 additions and 78 deletions

View File

@@ -8,6 +8,7 @@ import (
"bssapp-backend/queries"
"bytes"
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
@@ -19,6 +20,28 @@ import (
"github.com/jung-kurt/gofpdf"
)
type statementPDFHeaderRow struct {
CariKod string `json:"cari_kod"`
CariIsim string `json:"cari_isim"`
BelgeTarihi string `json:"belge_tarihi"`
VadeTarihi string `json:"vade_tarihi"`
BelgeNo string `json:"belge_no"`
IslemTipi string `json:"islem_tipi"`
Aciklama string `json:"aciklama"`
ParaBirimi string `json:"para_birimi"`
Borc float64 `json:"borc"`
Alacak float64 `json:"alacak"`
Bakiye float64 `json:"bakiye"`
}
type statementPDFPayload struct {
AccountCode string `json:"account_code"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
LangCode string `json:"lang_code"`
Rows []statementPDFHeaderRow `json:"rows"`
}
/* ============================ SABİTLER ============================ */
// A4 Landscape (mm)
@@ -468,11 +491,25 @@ func ExportPDFHandler(mssql *sql.DB) http.HandlerFunc {
log.Printf("▶️ ExportPDFHandler: account=%s start=%s end=%s parislemler=%v",
accountCode, startDate, endDate, parislemler)
// 1) Header verileri
headers, belgeNos, err := queries.GetStatementsPDF(r.Context(), accountCode, startDate, endDate, langCode, parislemler)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
var (
headers []models.StatementHeader
belgeNos []string
err error
)
if strings.EqualFold(r.Method, http.MethodPost) {
accountCode, startDate, endDate, langCode, headers, err = parseStatementPDFPayload(r, langCode)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
belgeNos = queriesCollectBelgeNos(headers)
} else {
headers, belgeNos, err = queries.GetStatementsPDF(r.Context(), accountCode, startDate, endDate, langCode, parislemler)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
log.Printf("✅ Header verileri alındı: %d kayıt, %d belge no", len(headers), len(belgeNos))
@@ -506,10 +543,7 @@ func ExportPDFHandler(mssql *sql.DB) http.HandlerFunc {
for _, k := range order {
sort.SliceStable(groups[k].rows, func(i, j int) bool {
ri, rj := groups[k].rows[i], groups[k].rows[j]
if ri.BelgeTarihi == rj.BelgeTarihi {
return ri.BelgeNo < rj.BelgeNo
}
return ri.BelgeTarihi < rj.BelgeTarihi
return parseStatementHeaderDate(ri.BelgeTarihi).Before(parseStatementHeaderDate(rj.BelgeTarihi))
})
if n := len(groups[k].rows); n > 0 {
groups[k].sonBakiye = groups[k].rows[n-1].Bakiye
@@ -648,6 +682,64 @@ func ExportPDFHandler(mssql *sql.DB) http.HandlerFunc {
}
}
func parseStatementPDFPayload(r *http.Request, fallbackLang string) (string, string, string, string, []models.StatementHeader, error) {
var payload statementPDFPayload
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
return "", "", "", "", nil, fmt.Errorf("invalid statement pdf payload: %w", err)
}
langCode := i18n.ResolveLangCode(payload.LangCode, fallbackLang)
headers := make([]models.StatementHeader, 0, len(payload.Rows))
for _, row := range payload.Rows {
headers = append(headers, models.StatementHeader{
CariKod: row.CariKod,
CariIsim: row.CariIsim,
BelgeTarihi: row.BelgeTarihi,
VadeTarihi: row.VadeTarihi,
BelgeNo: row.BelgeNo,
IslemTipi: row.IslemTipi,
Aciklama: row.Aciklama,
ParaBirimi: row.ParaBirimi,
Borc: row.Borc,
Alacak: row.Alacak,
Bakiye: row.Bakiye,
})
}
return payload.AccountCode, payload.StartDate, payload.EndDate, langCode, headers, nil
}
func parseStatementHeaderDate(value string) time.Time {
value = strings.TrimSpace(value)
if value == "" {
return time.Time{}
}
if t, err := time.Parse("2006-01-02", value); err == nil {
return t
}
if t, err := time.Parse(time.RFC3339, value); err == nil {
return t
}
return time.Time{}
}
func queriesCollectBelgeNos(headers []models.StatementHeader) []string {
seen := make(map[string]struct{}, len(headers))
out := make([]string, 0, len(headers))
for _, h := range headers {
no := strings.TrimSpace(h.BelgeNo)
if no == "" || no == "Baslangic_devir" {
continue
}
if _, ok := seen[no]; ok {
continue
}
seen[no] = struct{}{}
out = append(out, no)
}
return out
}
/*
NOTLAR:
- Header artık dinamik yüksekliğe sahip (drawPageHeader -> contentTopY döner).