Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user