Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-03-17 14:11:08 +03:00
parent 569e22e4f8
commit 83a55373ea
2 changed files with 125 additions and 16 deletions

View File

@@ -90,6 +90,9 @@ func ExportStatementAgingScreenPDFHandler(_ *sql.DB) http.HandlerFunc {
})
}
sortBy := strings.TrimSpace(r.URL.Query().Get("sort_by"))
sortDesc := parseBoolQuery(r.URL.Query().Get("sort_desc"))
pdf := gofpdf.New("L", "mm", "A3", "")
pdf.SetMargins(8, 8, 8)
pdf.SetAutoPageBreak(false, 10)
@@ -98,7 +101,7 @@ func ExportStatementAgingScreenPDFHandler(_ *sql.DB) http.HandlerFunc {
return
}
drawStatementAgingScreenPDF(pdf, selectedDate, params.AccountCode, rows)
drawStatementAgingScreenPDF(pdf, selectedDate, params.AccountCode, rows, sortBy, sortDesc)
if err := pdf.Error(); err != nil {
http.Error(w, "pdf render error: "+err.Error(), http.StatusInternalServerError)
@@ -150,8 +153,8 @@ type agingScreenCurrencyPDF struct {
WeightedGunDocSum float64
}
func drawStatementAgingScreenPDF(pdf *gofpdf.Fpdf, selectedDate, accountCode string, rows []agingScreenPDFRow) {
masters, currenciesByMaster, detailsByCurrency := buildStatementAgingScreenPDFData(rows)
func drawStatementAgingScreenPDF(pdf *gofpdf.Fpdf, selectedDate, accountCode string, rows []agingScreenPDFRow, sortBy string, sortDesc bool) {
masters, currenciesByMaster, detailsByCurrency := buildStatementAgingScreenPDFData(rows, sortBy, sortDesc)
pageW, pageH := pdf.GetPageSize()
marginL, marginT, marginR, marginB := 8.0, 8.0, 8.0, 10.0
@@ -369,7 +372,7 @@ func statementAgingAvg(sum, base float64, fallback ...float64) float64 {
return 0
}
func buildStatementAgingScreenPDFData(rows []agingScreenPDFRow) ([]agingScreenMasterPDF, map[string][]agingScreenCurrencyPDF, map[string][]agingScreenPDFRow) {
func buildStatementAgingScreenPDFData(rows []agingScreenPDFRow, sortBy string, sortDesc bool) ([]agingScreenMasterPDF, map[string][]agingScreenCurrencyPDF, map[string][]agingScreenPDFRow) {
masterMap := map[string]*agingScreenMasterPDF{}
currencyMap := map[string]*agingScreenCurrencyPDF{}
detailsByCurrency := map[string][]agingScreenPDFRow{}
@@ -454,19 +457,13 @@ func buildStatementAgingScreenPDFData(rows []agingScreenPDFRow) ([]agingScreenMa
detailsByCurrency[currencyKey] = append(detailsByCurrency[currencyKey], row)
}
masterKeys := make([]string, 0, len(masterMap))
for k := range masterMap {
masterKeys = append(masterKeys, k)
masters := make([]agingScreenMasterPDF, 0, len(masterMap))
currenciesByMaster := make(map[string][]agingScreenCurrencyPDF, len(masterMap))
for _, m := range masterMap {
masters = append(masters, *m)
}
sort.SliceStable(masterKeys, func(i, j int) bool {
return strings.ToUpper(masterKeys[i]) < strings.ToUpper(masterKeys[j])
})
masters := make([]agingScreenMasterPDF, 0, len(masterKeys))
currenciesByMaster := make(map[string][]agingScreenCurrencyPDF, len(masterKeys))
for _, mk := range masterKeys {
masters = append(masters, *masterMap[mk])
}
sortAgingScreenMastersForPDF(masters, sortBy, sortDesc)
for _, c := range currencyMap {
currenciesByMaster[c.MasterKey] = append(currenciesByMaster[c.MasterKey], *c)
@@ -481,6 +478,18 @@ func buildStatementAgingScreenPDFData(rows []agingScreenPDFRow) ([]agingScreenMa
sort.SliceStable(detailsByCurrency[k], func(i, j int) bool {
a := detailsByCurrency[k][i]
b := detailsByCurrency[k][j]
aOpen := strings.EqualFold(strings.TrimSpace(a.Aciklama), "ACIKKALEM")
bOpen := strings.EqualFold(strings.TrimSpace(b.Aciklama), "ACIKKALEM")
if aOpen != bOpen {
return aOpen
}
aDate := parseAgingSortDate(a.OdemeDocDate, a.OdemeTarihi, a.FaturaTarihi)
bDate := parseAgingSortDate(b.OdemeDocDate, b.OdemeTarihi, b.FaturaTarihi)
if aDate != bDate {
return aDate.After(bDate)
}
if strings.TrimSpace(a.FaturaCari) == strings.TrimSpace(b.FaturaCari) {
if strings.TrimSpace(a.OdemeCari) == strings.TrimSpace(b.OdemeCari) {
if strings.TrimSpace(a.FaturaRef) == strings.TrimSpace(b.FaturaRef) {
@@ -497,6 +506,97 @@ func buildStatementAgingScreenPDFData(rows []agingScreenPDFRow) ([]agingScreenMa
return masters, currenciesByMaster, detailsByCurrency
}
func sortAgingScreenMastersForPDF(masters []agingScreenMasterPDF, sortBy string, descending bool) {
if len(masters) <= 1 {
return
}
key := strings.TrimSpace(sortBy)
if key == "" {
key = "cari8"
}
textCmp := func(a, b string) int {
return strings.Compare(strings.ToUpper(strings.TrimSpace(a)), strings.ToUpper(strings.TrimSpace(b)))
}
numCmp := func(a, b float64) int {
if a < b {
return -1
}
if a > b {
return 1
}
return 0
}
intCmp := func(a, b int) int {
if a < b {
return -1
}
if a > b {
return 1
}
return 0
}
sort.SliceStable(masters, func(i, j int) bool {
a := masters[i]
b := masters[j]
cmp := 0
switch key {
case "cari8":
cmp = textCmp(a.Cari8, b.Cari8)
case "cari_detay":
cmp = textCmp(a.CariDetay, b.CariDetay)
case "satir_sayisi":
cmp = intCmp(a.SatirSayisi, b.SatirSayisi)
case "toplam_usd":
cmp = numCmp(a.ToplamUSD, b.ToplamUSD)
case "normal_usd":
cmp = numCmp(a.NormalUSD, b.NormalUSD)
case "acik_kalem_usd":
cmp = numCmp(a.AcikKalemUSD, b.AcikKalemUSD)
case "ortalama_gun":
cmp = numCmp(statementAgingAvg(a.WeightedGunSum, a.WeightedBase), statementAgingAvg(b.WeightedGunSum, b.WeightedBase))
case "ortalama_gun_docdate":
cmp = numCmp(statementAgingAvg(a.WeightedGunDocSum, a.WeightedBase), statementAgingAvg(b.WeightedGunDocSum, b.WeightedBase))
case "kur":
cmp = numCmp(statementAgingAvg(a.KurWeightedSum, a.KurWeightedBase, a.KurFallback), statementAgingAvg(b.KurWeightedSum, b.KurWeightedBase, b.KurFallback))
default:
cmp = textCmp(a.Cari8, b.Cari8)
}
if cmp == 0 {
cmp = textCmp(a.Cari8, b.Cari8)
}
if descending {
return cmp > 0
}
return cmp < 0
})
}
func parseAgingSortDate(values ...string) time.Time {
layouts := []string{
time.RFC3339,
"2006-01-02",
"2006-01-02 15:04:05",
"02.01.2006",
"02.01.2006 15:04:05",
}
for _, raw := range values {
s := strings.TrimSpace(raw)
if s == "" {
continue
}
for _, l := range layouts {
if t, err := time.Parse(l, s); err == nil {
return t
}
}
}
return time.Time{}
}
func pickString(m map[string]interface{}, keys ...string) string {
for _, k := range keys {
if v, ok := m[k]; ok {