303 lines
7.8 KiB
Go
303 lines
7.8 KiB
Go
package routes
|
|
|
|
import (
|
|
"bssapp-backend/auth"
|
|
"bssapp-backend/models"
|
|
"bssapp-backend/queries"
|
|
"bytes"
|
|
"database/sql"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/jung-kurt/gofpdf"
|
|
)
|
|
|
|
type agingScreenPDFRow struct {
|
|
Cari8 string
|
|
CariDetay string
|
|
FaturaCari string
|
|
OdemeCari string
|
|
FaturaRef string
|
|
OdemeRef string
|
|
FaturaTarihi string
|
|
OdemeTarihi string
|
|
OdemeDocDate string
|
|
EslesenTutar float64
|
|
UsdTutar float64
|
|
CurrencyTryRate float64
|
|
GunSayisi float64
|
|
GunSayisiDocDate float64
|
|
Aciklama string
|
|
DocCurrencyCode string
|
|
}
|
|
|
|
func ExportStatementAgingScreenPDFHandler(_ *sql.DB) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
claims, ok := auth.GetClaimsFromContext(r.Context())
|
|
if !ok || claims == nil {
|
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
selectedDate := strings.TrimSpace(r.URL.Query().Get("enddate"))
|
|
if selectedDate == "" {
|
|
selectedDate = strings.TrimSpace(r.URL.Query().Get("selected_date"))
|
|
}
|
|
if selectedDate == "" {
|
|
selectedDate = time.Now().Format("2006-01-02")
|
|
}
|
|
|
|
params := models.StatementAgingParams{
|
|
AccountCode: strings.TrimSpace(r.URL.Query().Get("accountcode")),
|
|
EndDate: selectedDate,
|
|
Parislemler: r.URL.Query()["parislemler"],
|
|
}
|
|
|
|
if err := queries.RebuildStatementAgingCache(r.Context()); err != nil {
|
|
http.Error(w, "Error rebuilding aging cache: "+err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
rawRows, err := queries.GetStatementAging(params)
|
|
if err != nil {
|
|
http.Error(w, "Error fetching aging statement: "+err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
rows := make([]agingScreenPDFRow, 0, len(rawRows))
|
|
for _, r := range rawRows {
|
|
rows = append(rows, agingScreenPDFRow{
|
|
Cari8: pickString(r, "Cari8", "cari8"),
|
|
CariDetay: pickString(r, "CariDetay", "cari_detay"),
|
|
FaturaCari: pickString(r, "FaturaCari", "fatura_cari"),
|
|
OdemeCari: pickString(r, "OdemeCari", "odeme_cari"),
|
|
FaturaRef: pickString(r, "FaturaRef", "fatura_ref"),
|
|
OdemeRef: pickString(r, "OdemeRef", "odeme_ref"),
|
|
FaturaTarihi: pickString(r, "FaturaTarihi", "fatura_tarihi"),
|
|
OdemeTarihi: pickString(r, "OdemeTarihi", "odeme_tarihi"),
|
|
OdemeDocDate: pickString(r, "OdemeDocDate", "odeme_doc_date"),
|
|
EslesenTutar: pickFloat(r, "EslesenTutar", "eslesen_tutar"),
|
|
UsdTutar: pickFloat(r, "UsdTutar", "usd_tutar"),
|
|
CurrencyTryRate: pickFloat(r, "CurrencyTryRate", "currency_try_rate"),
|
|
GunSayisi: pickFloat(r, "GunSayisi", "gun_sayisi"),
|
|
GunSayisiDocDate: pickFloat(r, "GunSayisi_DocDate", "gun_sayisi_docdate"),
|
|
Aciklama: pickString(r, "Aciklama", "aciklama"),
|
|
DocCurrencyCode: pickString(r, "DocCurrencyCode", "doc_currency_code"),
|
|
})
|
|
}
|
|
|
|
pdf := gofpdf.New("L", "mm", "A3", "")
|
|
pdf.SetMargins(8, 8, 8)
|
|
pdf.SetAutoPageBreak(false, 10)
|
|
if err := registerDejavuFonts(pdf, "dejavu"); err != nil {
|
|
http.Error(w, "pdf font error: "+err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
drawStatementAgingScreenPDF(pdf, selectedDate, params.AccountCode, rows)
|
|
|
|
if err := pdf.Error(); err != nil {
|
|
http.Error(w, "pdf render error: "+err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if err := pdf.Output(&buf); err != nil {
|
|
http.Error(w, "pdf output error: "+err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/pdf")
|
|
w.Header().Set("Content-Disposition", `inline; filename="account-aging-screen.pdf"`)
|
|
_, _ = w.Write(buf.Bytes())
|
|
}
|
|
}
|
|
|
|
func drawStatementAgingScreenPDF(pdf *gofpdf.Fpdf, selectedDate, accountCode string, rows []agingScreenPDFRow) {
|
|
pageW, _ := pdf.GetPageSize()
|
|
marginL, marginT, marginR, marginB := 8.0, 8.0, 8.0, 10.0
|
|
tableW := pageW - marginL - marginR
|
|
|
|
cols := []string{
|
|
"Ana Cari", "Ana Cari Detay", "Fatura Cari", "Odeme Cari", "Fatura Ref", "Odeme Ref",
|
|
"Fatura Tarihi", "Odeme Vade", "Odeme DocDate", "Eslesen Tutar", "USD Tutar", "Kur",
|
|
"Gun", "Gun (DocDate)", "Aciklama", "Doviz",
|
|
}
|
|
widths := normalizeWidths([]float64{
|
|
18, 34, 18, 18, 22, 22,
|
|
16, 16, 18, 19, 16, 12,
|
|
10, 13, 28, 11,
|
|
}, tableW)
|
|
|
|
header := func() {
|
|
pdf.AddPage()
|
|
pdf.SetFont("dejavu", "B", 14)
|
|
pdf.SetTextColor(149, 113, 22)
|
|
pdf.SetXY(marginL, marginT)
|
|
pdf.CellFormat(150, 6, "Cari Yaslandirmali Ekstre", "", 0, "L", false, 0, "")
|
|
|
|
pdf.SetFont("dejavu", "", 8.5)
|
|
pdf.SetTextColor(30, 30, 30)
|
|
pdf.SetXY(pageW-marginR-90, marginT+0.5)
|
|
pdf.CellFormat(90, 4.8, "Son Tarih: "+selectedDate, "", 0, "R", false, 0, "")
|
|
if strings.TrimSpace(accountCode) != "" {
|
|
pdf.SetXY(pageW-marginR-90, marginT+5)
|
|
pdf.CellFormat(90, 4.8, "Cari: "+accountCode, "", 0, "R", false, 0, "")
|
|
}
|
|
|
|
pdf.SetDrawColor(149, 113, 22)
|
|
pdf.Line(marginL, marginT+10.5, pageW-marginR, marginT+10.5)
|
|
pdf.SetDrawColor(200, 200, 200)
|
|
pdf.SetY(marginT + 13)
|
|
|
|
pdf.SetFont("dejavu", "B", 7.2)
|
|
pdf.SetTextColor(255, 255, 255)
|
|
pdf.SetFillColor(149, 113, 22)
|
|
y := pdf.GetY()
|
|
x := marginL
|
|
for i, c := range cols {
|
|
pdf.Rect(x, y, widths[i], 6.2, "DF")
|
|
pdf.SetXY(x+0.8, y+1)
|
|
pdf.CellFormat(widths[i]-1.6, 4.2, c, "", 0, "C", false, 0, "")
|
|
x += widths[i]
|
|
}
|
|
pdf.SetY(y + 6.2)
|
|
}
|
|
|
|
needPage := func(needH float64) bool {
|
|
return pdf.GetY()+needH+marginB > 297.0
|
|
}
|
|
|
|
header()
|
|
pdf.SetFont("dejavu", "", 6.8)
|
|
pdf.SetTextColor(25, 25, 25)
|
|
|
|
for _, r := range rows {
|
|
if needPage(5.5) {
|
|
header()
|
|
pdf.SetFont("dejavu", "", 6.8)
|
|
pdf.SetTextColor(25, 25, 25)
|
|
}
|
|
|
|
line := []string{
|
|
r.Cari8,
|
|
r.CariDetay,
|
|
r.FaturaCari,
|
|
r.OdemeCari,
|
|
r.FaturaRef,
|
|
r.OdemeRef,
|
|
r.FaturaTarihi,
|
|
r.OdemeTarihi,
|
|
r.OdemeDocDate,
|
|
formatMoneyPDF(r.EslesenTutar),
|
|
formatMoneyPDF(r.UsdTutar),
|
|
formatMoneyPDF(r.CurrencyTryRate),
|
|
fmt.Sprintf("%.0f", r.GunSayisi),
|
|
fmt.Sprintf("%.0f", r.GunSayisiDocDate),
|
|
r.Aciklama,
|
|
r.DocCurrencyCode,
|
|
}
|
|
|
|
y := pdf.GetY()
|
|
x := marginL
|
|
for i, v := range line {
|
|
pdf.Rect(x, y, widths[i], 5.5, "")
|
|
align := "L"
|
|
if i >= 9 && i <= 11 {
|
|
align = "R"
|
|
}
|
|
if i == 12 || i == 13 {
|
|
align = "C"
|
|
}
|
|
pdf.SetXY(x+0.8, y+0.8)
|
|
pdf.CellFormat(widths[i]-1.6, 3.8, v, "", 0, align, false, 0, "")
|
|
x += widths[i]
|
|
}
|
|
pdf.SetY(y + 5.5)
|
|
}
|
|
}
|
|
|
|
func pickString(m map[string]interface{}, keys ...string) string {
|
|
for _, k := range keys {
|
|
if v, ok := m[k]; ok {
|
|
return strings.TrimSpace(toStringValue(v))
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func pickFloat(m map[string]interface{}, keys ...string) float64 {
|
|
for _, k := range keys {
|
|
if v, ok := m[k]; ok {
|
|
return toFloat64Value(v)
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func toStringValue(v interface{}) string {
|
|
switch x := v.(type) {
|
|
case nil:
|
|
return ""
|
|
case string:
|
|
return x
|
|
case []byte:
|
|
return string(x)
|
|
default:
|
|
return fmt.Sprint(x)
|
|
}
|
|
}
|
|
|
|
func toFloat64Value(v interface{}) float64 {
|
|
switch x := v.(type) {
|
|
case nil:
|
|
return 0
|
|
case float64:
|
|
return x
|
|
case float32:
|
|
return float64(x)
|
|
case int:
|
|
return float64(x)
|
|
case int64:
|
|
return float64(x)
|
|
case int32:
|
|
return float64(x)
|
|
case string:
|
|
return parseFloatValue(x)
|
|
case []byte:
|
|
return parseFloatValue(string(x))
|
|
default:
|
|
return parseFloatValue(fmt.Sprint(x))
|
|
}
|
|
}
|
|
|
|
func parseFloatValue(s string) float64 {
|
|
s = strings.TrimSpace(s)
|
|
if s == "" {
|
|
return 0
|
|
}
|
|
|
|
hasComma := strings.Contains(s, ",")
|
|
hasDot := strings.Contains(s, ".")
|
|
if hasComma && hasDot {
|
|
if strings.LastIndex(s, ",") > strings.LastIndex(s, ".") {
|
|
s = strings.ReplaceAll(s, ".", "")
|
|
s = strings.Replace(s, ",", ".", 1)
|
|
} else {
|
|
s = strings.ReplaceAll(s, ",", "")
|
|
}
|
|
} else if hasComma {
|
|
s = strings.ReplaceAll(s, ".", "")
|
|
s = strings.Replace(s, ",", ".", 1)
|
|
}
|
|
|
|
n, err := strconv.ParseFloat(s, 64)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return n
|
|
}
|