Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-03-06 10:56:53 +03:00
parent 9097b5af2d
commit 9e534e9a34
18 changed files with 2204 additions and 2015 deletions

View File

@@ -7,7 +7,6 @@ import (
"database/sql"
"fmt"
"math"
"sort"
"strconv"
"strings"
"time"
@@ -15,59 +14,34 @@ import (
func GetStatementAging(params models.StatementAgingParams) ([]map[string]interface{}, error) {
accountCode := normalizeMasterAccountCode(params.AccountCode)
if strings.TrimSpace(params.EndDate) == "" {
return nil, fmt.Errorf("enddate is required")
}
useType2, useType3 := resolveUseTypes(params.Parislemler)
endDateText := strings.TrimSpace(params.EndDate)
if endDateText == "" {
endDateText = time.Now().Format("2006-01-02")
rateMap, err := loadNearestTryRates(context.Background())
if err != nil {
return nil, err
}
endDate, _ := time.Parse("2006-01-02", endDateText)
cariFilter := ""
if strings.TrimSpace(accountCode) != "" {
cariFilter = strings.TrimSpace(accountCode)
usdTry := rateMap["USD"]
if usdTry <= 0 {
usdTry = 1
}
rows, err := db.MssqlDB.Query(`
SELECT TOP (100)
Cari8 = LEFT(LTRIM(RTRIM(CariKodu)), 8),
CariDetay = LTRIM(RTRIM(CariKodu)),
FaturaCari = LTRIM(RTRIM(CariKodu)),
OdemeCari = LTRIM(RTRIM(CariKodu)),
FaturaRef = CAST(NULL AS NVARCHAR(50)),
OdemeRef = CAST(NULL AS NVARCHAR(50)),
FaturaTarihi = CAST(NULL AS DATE),
OdemeTarihi = CAST(NULL AS DATE),
OdemeDocDate = CAST(NULL AS DATE),
EslesenTutar = CAST(Bakiye AS DECIMAL(18,2)),
GunSayisi = CAST(Vade_Gun AS DECIMAL(18,2)),
GunSayisi_DocDate = CAST(Vade_BelgeTarihi_Gun AS DECIMAL(18,2)),
Aciklama = CAST('AcikKalem' AS NVARCHAR(30)),
DocCurrencyCode = LTRIM(RTRIM(CariDoviz)),
PislemTipi,
SirketKodu,
CurrAccTypeCode,
Bakiye,
Vade_Gun,
Vade_BelgeTarihi_Gun,
SonTarih,
HesaplamaTarihi
FROM dbo.CARI_BAKIYE_GUN_CACHE
WHERE
(
(@UseType2 = 1 AND PislemTipi = '1_2')
OR
(@UseType3 = 1 AND PislemTipi = '1_3')
)
AND (@CariFilter = '' OR LTRIM(RTRIM(CariKodu)) LIKE @CariFilter + '%')
ORDER BY CariKodu, CariDoviz, PislemTipi;
EXEC dbo.SP_FIFO_MATCH_FINAL
@Cari8 = @Cari8,
@SonTarih = @SonTarih,
@UseType2 = @UseType2,
@UseType3 = @UseType3;
`,
sql.Named("Cari8", accountCode),
sql.Named("SonTarih", params.EndDate),
sql.Named("UseType2", useType2),
sql.Named("UseType3", useType3),
sql.Named("CariFilter", cariFilter),
)
if err != nil {
return nil, fmt.Errorf("CARI_BAKIYE_GUN_CACHE query error: %w", err)
return nil, fmt.Errorf("SP_FIFO_MATCH_FINAL query error: %w", err)
}
defer rows.Close()
@@ -78,7 +52,6 @@ func GetStatementAging(params models.StatementAgingParams) ([]map[string]interfa
result := make([]map[string]interface{}, 0, 2048)
cari8Set := make(map[string]struct{})
currencySet := make(map[string]struct{})
for rows.Next() {
values := make([]interface{}, len(columns))
scanArgs := make([]interface{}, len(columns))
@@ -108,11 +81,6 @@ func GetStatementAging(params models.StatementAgingParams) ([]map[string]interfa
if cari8 != "" {
cari8Set[cari8] = struct{}{}
}
curr := strings.ToUpper(strings.TrimSpace(asString(row["DocCurrencyCode"])))
if curr != "" && curr != "TRY" {
currencySet[curr] = struct{}{}
}
currencySet["USD"] = struct{}{}
result = append(result, row)
}
@@ -125,10 +93,6 @@ func GetStatementAging(params models.StatementAgingParams) ([]map[string]interfa
if err != nil {
return nil, err
}
rateSeriesByCurr, err := loadTryRateSeriesByCurrency(context.Background(), currencySet)
if err != nil {
return nil, err
}
for i := range result {
row := result[i]
@@ -137,25 +101,13 @@ func GetStatementAging(params models.StatementAgingParams) ([]map[string]interfa
if curr == "" {
curr = "TRY"
}
aciklama := strings.ToUpper(strings.TrimSpace(asString(row["Aciklama"])))
targetDate := endDate
if aciklama != "ACIKKALEM" {
if odemeTarihi, ok := parseDateOnly(asString(row["OdemeTarihi"])); ok {
targetDate = odemeTarihi
}
}
tutar := asFloat64(row["EslesenTutar"])
currTry := resolveTryRate(curr, targetDate, rateSeriesByCurr)
usdTry := resolveTryRate("USD", targetDate, rateSeriesByCurr)
tryTutar := toTRYByRate(tutar, curr, currTry)
usdTutar := toUSDByRates(tutar, curr, currTry, usdTry)
gunKur := usdRateInCurrency(curr, currTry, usdTry)
usdTutar := toUSD(tutar, curr, usdTry, rateMap)
row["CariDetay"] = cariDetailMap[cari8]
row["UsdTutar"] = round2(usdTutar)
row["TryTutar"] = round2(tryTutar)
row["GunKur"] = round6(gunKur)
row["CurrencyTryRate"] = round6(rateMap[curr])
}
return result, nil
@@ -306,138 +258,3 @@ func round2(v float64) float64 {
func round6(v float64) float64 {
return math.Round(v*1_000_000) / 1_000_000
}
type ratePoint struct {
date time.Time
rate float64
}
func loadTryRateSeriesByCurrency(ctx context.Context, currencies map[string]struct{}) (map[string][]ratePoint, error) {
if len(currencies) == 0 {
return map[string][]ratePoint{}, nil
}
query := fmt.Sprintf(`
SELECT CurrencyCode, Rate, CAST([Date] AS date) AS RateDate
FROM AllExchangeRates
WHERE RelationCurrencyCode = 'TRY'
AND ExchangeTypeCode = 6
AND Rate > 0
AND CurrencyCode IN (%s)
`, quotedInList(currencies))
rows, err := db.MssqlDB.QueryContext(ctx, query)
if err != nil {
return nil, fmt.Errorf("aging currency series query error: %w", err)
}
defer rows.Close()
out := make(map[string][]ratePoint, len(currencies))
for rows.Next() {
var code string
var rate float64
var dt time.Time
if err := rows.Scan(&code, &rate, &dt); err != nil {
return nil, err
}
code = strings.ToUpper(strings.TrimSpace(code))
out[code] = append(out[code], ratePoint{date: dt, rate: rate})
}
if err := rows.Err(); err != nil {
return nil, err
}
for c := range out {
sort.Slice(out[c], func(i, j int) bool { return out[c][i].date.Before(out[c][j].date) })
}
return out, nil
}
func resolveTryRate(currency string, target time.Time, series map[string][]ratePoint) float64 {
currency = strings.ToUpper(strings.TrimSpace(currency))
if currency == "" || currency == "TRY" {
return 1
}
points := series[currency]
if len(points) == 0 {
return 0
}
best := points[0]
bestDiff := absDurationDays(points[0].date.Sub(target))
for i := 1; i < len(points); i++ {
diff := absDurationDays(points[i].date.Sub(target))
if diff < bestDiff || (diff == bestDiff && points[i].date.After(best.date)) {
best = points[i]
bestDiff = diff
}
}
return best.rate
}
func absDurationDays(d time.Duration) int64 {
if d < 0 {
d = -d
}
return int64(d.Hours() / 24)
}
func parseDateOnly(v string) (time.Time, bool) {
v = strings.TrimSpace(v)
if v == "" {
return time.Time{}, false
}
t, err := time.Parse("2006-01-02", v)
if err != nil {
return time.Time{}, false
}
return t, true
}
func toTRYByRate(amount float64, currency string, currTry float64) float64 {
currency = strings.ToUpper(strings.TrimSpace(currency))
if currency == "" || currency == "TRY" {
return amount
}
if currTry <= 0 {
return 0
}
return amount * currTry
}
func toUSDByRates(amount float64, currency string, currTry, usdTry float64) float64 {
currency = strings.ToUpper(strings.TrimSpace(currency))
switch currency {
case "USD":
return amount
case "", "TRY":
if usdTry <= 0 {
return 0
}
return amount / usdTry
default:
if currTry <= 0 || usdTry <= 0 {
return 0
}
return (amount * currTry) / usdTry
}
}
// Returns X for "1 USD = X <currency>".
func usdRateInCurrency(currency string, currTry, usdTry float64) float64 {
currency = strings.ToUpper(strings.TrimSpace(currency))
switch currency {
case "", "USD":
return 1
case "TRY":
if usdTry <= 0 {
return 0
}
return usdTry
default:
if currTry <= 0 || usdTry <= 0 {
return 0
}
return usdTry / currTry
}
}

View File

@@ -34,10 +34,38 @@ func GetStatements(ctx context.Context, params models.StatementParams) ([]models
}
}
piyasaScope, err := buildPiyasaExistsForCariCode(ctx, "b.CurrAccCode")
customerPiyasaInClause, err := resolvePiyasaScopeInClause(ctx, "PF.CustomerAtt01")
if err != nil {
return nil, err
}
vendorPiyasaInClause, err := resolvePiyasaScopeInClause(ctx, "VF.VendorAtt01")
if err != nil {
return nil, err
}
piyasaScope := fmt.Sprintf(`
(
(b.CurrAccTypeCode = 3 AND EXISTS (
SELECT 1
FROM CustomerAttributesFilter PF WITH (NOLOCK)
WHERE (PF.CurrAccCode = b.CurrAccCode OR LEFT(PF.CurrAccCode, 8) = LEFT(b.CurrAccCode, 8))
AND %s
))
OR
(b.CurrAccTypeCode = 1 AND EXISTS (
SELECT 1
FROM (
SELECT
CurrAccCode,
VendorAtt01 = MAX(CASE WHEN AttributeTypeCode = 1 THEN AttributeCode END)
FROM prCurrAccAttribute WITH (NOLOCK)
WHERE CurrAccTypeCode = 1
GROUP BY CurrAccCode
) VF
WHERE (VF.CurrAccCode = b.CurrAccCode OR LEFT(VF.CurrAccCode, 8) = LEFT(b.CurrAccCode, 8))
AND %s
))
)`, customerPiyasaInClause, vendorPiyasaInClause)
query := fmt.Sprintf(`
;WITH CurrDesc AS (
@@ -62,7 +90,7 @@ HasMovement AS (
INNER JOIN CurrAccBookATAttributesFilter f
ON f.CurrAccBookID = b.CurrAccBookID
AND f.ATAtt01 IN (%s)
WHERE LEFT(REPLACE(b.CurrAccCode, ' ', ''), 7) = REPLACE(@Carikod, ' ', '')
WHERE LEFT(REPLACE(b.CurrAccCode, ' ', ''), 7) = LEFT(REPLACE(@Carikod, ' ', ''), 7)
AND b.DocumentDate BETWEEN @startdate AND @enddate
AND %s
) THEN 1 ELSE 0 END AS HasMov
@@ -85,7 +113,8 @@ Opening AS (
LEFT JOIN trCurrAccBookCurrency c
ON c.CurrAccBookID = b.CurrAccBookID
AND c.CurrencyCode = b.DocCurrencyCode
WHERE LEFT(REPLACE(b.CurrAccCode, ' ', ''), 7) = REPLACE(@Carikod, ' ', '')
WHERE LEFT(REPLACE(b.CurrAccCode, ' ', ''), 7) = LEFT(REPLACE(@Carikod, ' ', ''), 7)
AND @ExcludeOpening = 0
AND %s
AND (
(hm.HasMov = 1 AND b.DocumentDate < @startdate) -- hareket varsa: klasik devir
@@ -142,7 +171,7 @@ Movements AS (
ON c.CurrAccBookID = b.CurrAccBookID
AND c.CurrencyCode = b.DocCurrencyCode
WHERE LEFT(REPLACE(b.CurrAccCode, ' ', ''), 7) = REPLACE(@Carikod, ' ', '')
WHERE LEFT(REPLACE(b.CurrAccCode, ' ', ''), 7) = LEFT(REPLACE(@Carikod, ' ', ''), 7)
AND %s
AND b.DocumentDate BETWEEN @startdate AND @enddate
)
@@ -223,6 +252,7 @@ ORDER BY
sql.Named("enddate", params.EndDate),
sql.Named("Carikod", params.AccountCode),
sql.Named("LangCode", params.LangCode),
sql.Named("ExcludeOpening", params.ExcludeOpening),
)
if err != nil {
return nil, fmt.Errorf("MSSQL query error: %v", err)

View File

@@ -70,7 +70,7 @@ LEFT JOIN cdItemAttributeDesc KisaKarDesc
ON KisaKar.AttributeTypeCode = KisaKarDesc.AttributeTypeCode
AND KisaKar.AttributeCode = KisaKarDesc.AttributeCode
AND KisaKar.ItemTypeCode = KisaKarDesc.ItemTypeCode
WHERE a.CurrAccCode LIKE @Carikod
WHERE REPLACE(a.CurrAccCode, ' ', '') LIKE REPLACE(@Carikod, ' ', '') + '%%'
AND a.InvoiceDate BETWEEN @StartDate AND @EndDate
AND %s
%s
@@ -91,7 +91,7 @@ ORDER BY Belge_Tarihi, Belge_Ref_Numarasi, Urun_Kodu;`,
)
rows, err := db.MssqlDB.QueryContext(ctx, query,
sql.Named("Carikod", "%"+accountCode+"%"),
sql.Named("Carikod", normalizeMasterAccountCode(accountCode)),
sql.Named("StartDate", startDate),
sql.Named("EndDate", endDate),
)