Merge remote-tracking branch 'origin/master'
This commit is contained in:
91
svc/queries/account_balance_fast.go
Normal file
91
svc/queries/account_balance_fast.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"bssapp-backend/models"
|
||||
"context"
|
||||
)
|
||||
|
||||
func GetCustomerBalanceList(
|
||||
ctx context.Context,
|
||||
params models.CustomerBalanceListParams,
|
||||
) ([]models.CustomerBalanceListRow, error) {
|
||||
|
||||
//------------------------------------------------
|
||||
// 1️⃣ DATA ÇEK
|
||||
//------------------------------------------------
|
||||
|
||||
balances, err := getFastBalances(ctx, params.SelectedDate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
masterMap, err := getCariMasterMap(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
// 2️⃣ MERGE
|
||||
//------------------------------------------------
|
||||
|
||||
resultMap := make(map[string]*models.CustomerBalanceListRow)
|
||||
|
||||
for _, b := range balances {
|
||||
|
||||
key := b.CariKodu + "|" + b.CariDoviz
|
||||
|
||||
r, ok := resultMap[key]
|
||||
if !ok {
|
||||
|
||||
r = &models.CustomerBalanceListRow{
|
||||
CariKodu: b.CariKodu,
|
||||
CariDoviz: b.CariDoviz,
|
||||
}
|
||||
|
||||
// Master
|
||||
if m, ok := masterMap[b.CariKodu]; ok {
|
||||
|
||||
r.CariDetay = m.CariDetay
|
||||
r.Piyasa = m.Piyasa
|
||||
r.Temsilci = m.Temsilci
|
||||
|
||||
r.Ozellik03 = m.Ozellik03
|
||||
r.Ozellik05 = m.Ozellik05
|
||||
r.Ozellik06 = m.Ozellik06
|
||||
r.Ozellik07 = m.Ozellik07
|
||||
r.CariIlkGrup = m.Ozellik08
|
||||
}
|
||||
|
||||
resultMap[key] = r
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
// 3️⃣ TOPLA
|
||||
//------------------------------------------------
|
||||
|
||||
if b.PislemTipi == "1_2" {
|
||||
|
||||
r.Bakiye12 += b.Bakiye
|
||||
r.TLBakiye12 += b.KurBakiye
|
||||
r.USDBakiye12 += b.KurBakiye / b.UsdKur
|
||||
|
||||
} else if b.PislemTipi == "1_3" {
|
||||
|
||||
r.Bakiye13 += b.Bakiye
|
||||
r.TLBakiye13 += b.KurBakiye
|
||||
r.USDBakiye13 += b.KurBakiye / b.UsdKur
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
// 4️⃣ SLICE DÖN
|
||||
//------------------------------------------------
|
||||
|
||||
out := make([]models.CustomerBalanceListRow, 0, len(resultMap))
|
||||
|
||||
for _, v := range resultMap {
|
||||
out = append(out, *v)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
79
svc/queries/account_master.go
Normal file
79
svc/queries/account_master.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"bssapp-backend/db"
|
||||
"context"
|
||||
)
|
||||
|
||||
type CariMasterRow struct {
|
||||
CariKodu string
|
||||
CariDetay string
|
||||
Piyasa string
|
||||
Temsilci string
|
||||
Ozellik03 string
|
||||
Ozellik05 string
|
||||
Ozellik06 string
|
||||
Ozellik07 string
|
||||
Ozellik08 string
|
||||
}
|
||||
|
||||
func getCariMasterMap(
|
||||
ctx context.Context,
|
||||
) (map[string]CariMasterRow, error) {
|
||||
|
||||
const q = `
|
||||
WITH CTE AS (
|
||||
SELECT
|
||||
*,
|
||||
rn = ROW_NUMBER() OVER (
|
||||
PARTITION BY LEFT(CariKodu,8)
|
||||
ORDER BY CariKodu
|
||||
)
|
||||
FROM dbo.MK_CARI_ILETISIM WITH(NOLOCK)
|
||||
)
|
||||
SELECT
|
||||
CariKodu,
|
||||
CariDetay,
|
||||
PIYASA,
|
||||
CARI_TEMSILCI,
|
||||
Ozellik03,
|
||||
Ozellik05,
|
||||
Ozellik06,
|
||||
Ozellik07,
|
||||
Ozellik08
|
||||
FROM CTE
|
||||
WHERE rn=1
|
||||
`
|
||||
|
||||
rows, err := db.MssqlDB.QueryContext(ctx, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make(map[string]CariMasterRow, 4096)
|
||||
|
||||
for rows.Next() {
|
||||
|
||||
var r CariMasterRow
|
||||
|
||||
err := rows.Scan(
|
||||
&r.CariKodu,
|
||||
&r.CariDetay,
|
||||
&r.Piyasa,
|
||||
&r.Temsilci,
|
||||
&r.Ozellik03,
|
||||
&r.Ozellik05,
|
||||
&r.Ozellik06,
|
||||
&r.Ozellik07,
|
||||
&r.Ozellik08,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out[r.CariKodu] = r
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"bssapp-backend/db"
|
||||
"bssapp-backend/internal/authz"
|
||||
"bssapp-backend/models"
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetCustomerBalanceList(ctx context.Context, params models.CustomerBalanceListParams) ([]models.CustomerBalanceListRow, error) {
|
||||
// AuthZ bazli piyasa filtresi
|
||||
piyasaFilter := authz.BuildMSSQLPiyasaFilter(ctx, "D.Ozellik01")
|
||||
if strings.TrimSpace(piyasaFilter) == "" {
|
||||
piyasaFilter = "1=1"
|
||||
}
|
||||
|
||||
// Dinamik WHERE insa et
|
||||
where := make([]string, 0, 16)
|
||||
where = append(where, "D.Islem_Tarihi < DATEADD(DAY, 1, @SecilenTarih)")
|
||||
where = append(where, piyasaFilter)
|
||||
|
||||
if params.CariIlkGrup != "" {
|
||||
where = append(where, "D.Ozellik08 = @CariIlkGrup")
|
||||
}
|
||||
if params.Piyasa != "" {
|
||||
where = append(where, "D.Ozellik01 = @Piyasa")
|
||||
}
|
||||
if params.Temsilci != "" {
|
||||
where = append(where, "COALESCE(NULLIF(D.Ozellik02, ''), D.Ozellik09) = @Temsilci")
|
||||
}
|
||||
if params.RiskDurumu != "" {
|
||||
where = append(where, "D.Ozellik03 = @RiskDurumu")
|
||||
}
|
||||
if params.IslemTipi != "" {
|
||||
where = append(where, "D.PislemTipi = @IslemTipi")
|
||||
}
|
||||
if params.Ulke != "" {
|
||||
where = append(where, "D.Ozellik05 = @Ulke")
|
||||
}
|
||||
whereSQL := strings.Join(where, "\n AND ")
|
||||
cariSearchLike := "%" + strings.TrimSpace(params.CariSearch) + "%"
|
||||
outerWhere := "1=1"
|
||||
if strings.TrimSpace(params.CariSearch) != "" {
|
||||
outerWhere = `(LEFT(B.CariKodu, 8) COLLATE Turkish_100_CI_AI LIKE @CariSearchLike
|
||||
OR B.CariKodu COLLATE Turkish_100_CI_AI LIKE @CariSearchLike
|
||||
OR B.CariDetay COLLATE Turkish_100_CI_AI LIKE @CariSearchLike
|
||||
OR AC.ANA_CARI_ADI COLLATE Turkish_100_CI_AI LIKE @CariSearchLike)`
|
||||
}
|
||||
|
||||
const queryTemplate = `
|
||||
;WITH CTE_ANA_CARI AS (
|
||||
SELECT
|
||||
ANA_CARI_KODU = LEFT(CariKodu, 8),
|
||||
CariDetay,
|
||||
rn = ROW_NUMBER() OVER (
|
||||
PARTITION BY LEFT(CariKodu, 8)
|
||||
ORDER BY CariKodu
|
||||
)
|
||||
FROM dbo.MK_CARI_ILETISIM WITH (NOLOCK)
|
||||
),
|
||||
ANA_CARI AS (
|
||||
SELECT
|
||||
ANA_CARI_KODU,
|
||||
CariDetay AS ANA_CARI_ADI
|
||||
FROM CTE_ANA_CARI
|
||||
WHERE rn = 1
|
||||
),
|
||||
BASE AS (
|
||||
SELECT
|
||||
D.SirketKodu,
|
||||
D.SirketDetay,
|
||||
D.CariKodu,
|
||||
D.CariDetay,
|
||||
D.CariDoviz,
|
||||
D.Ozellik01,
|
||||
D.Ozellik02,
|
||||
D.Ozellik03,
|
||||
D.Ozellik05,
|
||||
D.Ozellik06,
|
||||
D.Ozellik07,
|
||||
D.Ozellik08,
|
||||
D.Ozellik09,
|
||||
D.PislemTipi,
|
||||
D.Bakiye,
|
||||
D.KurBakiye,
|
||||
D.Son_Guncel_Kur
|
||||
FROM dbo.DENEME02DENEME AS D WITH (NOLOCK)
|
||||
WHERE %s
|
||||
)
|
||||
SELECT
|
||||
B.Ozellik08 AS CARI_ILK_GRUP,
|
||||
B.Ozellik01 AS PIYASA,
|
||||
COALESCE(NULLIF(B.Ozellik02, ''), B.Ozellik09) AS Temsilci,
|
||||
LEFT(B.SirketDetay, 10) AS Sirket,
|
||||
LEFT(B.CariKodu, 8) AS ANA_CARI_KODU,
|
||||
AC.ANA_CARI_ADI,
|
||||
B.CariKodu,
|
||||
B.CariDetay,
|
||||
B.Ozellik03,
|
||||
B.Ozellik05,
|
||||
B.Ozellik06,
|
||||
B.Ozellik07,
|
||||
B.CariDoviz,
|
||||
ISNULL(SUM(CASE WHEN B.PislemTipi = '1_2' THEN ISNULL(B.Bakiye, 0) ELSE 0 END), 0) AS Bakiye_1_2,
|
||||
ISNULL(SUM(CASE WHEN B.PislemTipi = '1_2' THEN ISNULL(B.KurBakiye, 0) ELSE 0 END), 0) AS TL_Bakiye_1_2,
|
||||
ISNULL(
|
||||
SUM(CASE WHEN B.PislemTipi = '1_2' THEN ISNULL(B.KurBakiye, 0) ELSE 0 END) / NULLIF(MIN(B.Son_Guncel_Kur), 0),
|
||||
0
|
||||
) AS USD_Bakiye_1_2,
|
||||
ISNULL(SUM(CASE WHEN B.PislemTipi = '1_3' THEN ISNULL(B.Bakiye, 0) ELSE 0 END), 0) AS Bakiye_1_3,
|
||||
ISNULL(SUM(CASE WHEN B.PislemTipi = '1_3' THEN ISNULL(B.KurBakiye, 0) ELSE 0 END), 0) AS TL_Bakiye_1_3,
|
||||
ISNULL(
|
||||
SUM(CASE WHEN B.PislemTipi = '1_3' THEN ISNULL(B.KurBakiye, 0) ELSE 0 END) / NULLIF(MIN(B.Son_Guncel_Kur), 0),
|
||||
0
|
||||
) AS USD_Bakiye_1_3,
|
||||
CAST(NULL AS int) AS Hesap_Alinmayan_Gun,
|
||||
CAST(NULL AS varchar(32)) AS Kalan_Fatura_Ortalama_Vade_Tarihi
|
||||
FROM BASE AS B
|
||||
LEFT JOIN ANA_CARI AS AC
|
||||
ON AC.ANA_CARI_KODU = LEFT(B.CariKodu, 8)
|
||||
WHERE %s
|
||||
GROUP BY
|
||||
B.Ozellik08,
|
||||
B.Ozellik01,
|
||||
COALESCE(NULLIF(B.Ozellik02, ''), B.Ozellik09),
|
||||
LEFT(B.SirketDetay, 10),
|
||||
LEFT(B.CariKodu, 8),
|
||||
AC.ANA_CARI_ADI,
|
||||
B.CariKodu,
|
||||
B.CariDetay,
|
||||
B.Ozellik03,
|
||||
B.Ozellik05,
|
||||
B.Ozellik06,
|
||||
B.Ozellik07,
|
||||
B.CariDoviz
|
||||
ORDER BY
|
||||
LEFT(B.SirketDetay, 10),
|
||||
B.CariKodu
|
||||
OPTION (RECOMPILE);
|
||||
`
|
||||
query := fmt.Sprintf(queryTemplate, whereSQL, outerWhere)
|
||||
|
||||
rows, err := db.MssqlDB.QueryContext(
|
||||
ctx,
|
||||
query,
|
||||
sql.Named("SecilenTarih", params.SelectedDate),
|
||||
sql.Named("CariIlkGrup", params.CariIlkGrup),
|
||||
sql.Named("Piyasa", params.Piyasa),
|
||||
sql.Named("Temsilci", params.Temsilci),
|
||||
sql.Named("RiskDurumu", params.RiskDurumu),
|
||||
sql.Named("IslemTipi", params.IslemTipi),
|
||||
sql.Named("Ulke", params.Ulke),
|
||||
sql.Named("CariSearchLike", cariSearchLike),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("MSSQL query error: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]models.CustomerBalanceListRow, 0, 512)
|
||||
|
||||
for rows.Next() {
|
||||
var r models.CustomerBalanceListRow
|
||||
if err := rows.Scan(
|
||||
&r.CariIlkGrup,
|
||||
&r.Piyasa,
|
||||
&r.Temsilci,
|
||||
&r.Sirket,
|
||||
&r.AnaCariKodu,
|
||||
&r.AnaCariAdi,
|
||||
&r.CariKodu,
|
||||
&r.CariDetay,
|
||||
&r.Ozellik03,
|
||||
&r.Ozellik05,
|
||||
&r.Ozellik06,
|
||||
&r.Ozellik07,
|
||||
&r.CariDoviz,
|
||||
&r.Bakiye12,
|
||||
&r.TLBakiye12,
|
||||
&r.USDBakiye12,
|
||||
&r.Bakiye13,
|
||||
&r.TLBakiye13,
|
||||
&r.USDBakiye13,
|
||||
&r.HesapAlinmayanGun,
|
||||
&r.KalanFaturaOrtalamaVadeTarihi,
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("row scan error: %w", err)
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("rows iteration error: %w", err)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
69
svc/queries/fast_balance.go
Normal file
69
svc/queries/fast_balance.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"bssapp-backend/db"
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type FastBalanceRow struct {
|
||||
CariKodu string
|
||||
CariDoviz string
|
||||
PislemTipi string
|
||||
SirketKodu int
|
||||
YerelBakiye float64
|
||||
Bakiye float64
|
||||
IslemTarihi string
|
||||
IslemKur float64
|
||||
TLBakiye float64
|
||||
TLYerel float64
|
||||
GuncelKur float64
|
||||
KurBakiye float64
|
||||
UsdKur float64
|
||||
}
|
||||
|
||||
func getFastBalances(
|
||||
ctx context.Context,
|
||||
date string,
|
||||
) ([]FastBalanceRow, error) {
|
||||
|
||||
rows, err := db.MssqlDB.QueryContext(
|
||||
ctx,
|
||||
`EXEC dbo.SP_CARI_BAKIYE_API_FAST @Tarih`,
|
||||
sql.Named("Tarih", date),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]FastBalanceRow, 0, 4096)
|
||||
|
||||
for rows.Next() {
|
||||
|
||||
var r FastBalanceRow
|
||||
|
||||
err := rows.Scan(
|
||||
&r.CariKodu,
|
||||
&r.CariDoviz,
|
||||
&r.PislemTipi,
|
||||
&r.SirketKodu,
|
||||
&r.YerelBakiye,
|
||||
&r.Bakiye,
|
||||
&r.IslemTarihi,
|
||||
&r.IslemKur,
|
||||
&r.TLBakiye,
|
||||
&r.TLYerel,
|
||||
&r.GuncelKur,
|
||||
&r.KurBakiye,
|
||||
&r.UsdKur,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, r)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
@@ -12,9 +12,7 @@ import (
|
||||
func GetStatements(params models.StatementParams) ([]models.StatementHeader, error) {
|
||||
|
||||
// AccountCode normalize: "ZLA0127" → "ZLA 0127"
|
||||
if len(params.AccountCode) == 7 && strings.ContainsAny(params.AccountCode, "0123456789") {
|
||||
params.AccountCode = params.AccountCode[:3] + " " + params.AccountCode[3:]
|
||||
}
|
||||
params.AccountCode = normalizeMasterAccountCode(params.AccountCode)
|
||||
if strings.TrimSpace(params.LangCode) == "" {
|
||||
params.LangCode = "TR"
|
||||
}
|
||||
@@ -58,7 +56,7 @@ HasMovement AS (
|
||||
INNER JOIN CurrAccBookATAttributesFilter f
|
||||
ON f.CurrAccBookID = b.CurrAccBookID
|
||||
AND f.ATAtt01 IN (%s)
|
||||
WHERE b.CurrAccCode LIKE '%%' + @Carikod + '%%'
|
||||
WHERE LEFT(REPLACE(b.CurrAccCode, ' ', ''), 7) = REPLACE(@Carikod, ' ', '')
|
||||
AND b.DocumentDate BETWEEN @startdate AND @enddate
|
||||
) THEN 1 ELSE 0 END AS HasMov
|
||||
),
|
||||
@@ -80,7 +78,7 @@ Opening AS (
|
||||
LEFT JOIN trCurrAccBookCurrency c
|
||||
ON c.CurrAccBookID = b.CurrAccBookID
|
||||
AND c.CurrencyCode = b.DocCurrencyCode
|
||||
WHERE b.CurrAccCode LIKE '%%' + @Carikod + '%%'
|
||||
WHERE LEFT(REPLACE(b.CurrAccCode, ' ', ''), 7) = REPLACE(@Carikod, ' ', '')
|
||||
AND (
|
||||
(hm.HasMov = 1 AND b.DocumentDate < @startdate) -- hareket varsa: klasik devir
|
||||
OR (hm.HasMov = 0 AND b.DocumentDate <= @enddate) -- hareket yoksa: enddate itibariyle bakiye
|
||||
@@ -95,15 +93,16 @@ Opening AS (
|
||||
========================================================= */
|
||||
Movements AS (
|
||||
SELECT
|
||||
@Carikod AS Cari_Kod,
|
||||
@Carikod AS Ana_Cari_Kod,
|
||||
b.CurrAccCode AS Cari_Kod,
|
||||
|
||||
COALESCE(
|
||||
(SELECT TOP 1 cd.CurrAccDescription
|
||||
FROM CurrDesc cd
|
||||
WHERE cd.CurrAccCode = @Carikod),
|
||||
WHERE REPLACE(cd.CurrAccCode, ' ', '') = REPLACE(b.CurrAccCode, ' ', '')),
|
||||
(SELECT TOP 1 cd.CurrAccDescription
|
||||
FROM CurrDesc cd
|
||||
WHERE cd.CurrAccCode LIKE '%%' + @Carikod + '%%'
|
||||
WHERE LEFT(REPLACE(cd.CurrAccCode, ' ', ''), 7) = REPLACE(@Carikod, ' ', '')
|
||||
ORDER BY cd.CurrAccCode)
|
||||
) AS Cari_Isim,
|
||||
|
||||
@@ -135,7 +134,7 @@ Movements AS (
|
||||
ON c.CurrAccBookID = b.CurrAccBookID
|
||||
AND c.CurrencyCode = b.DocCurrencyCode
|
||||
|
||||
WHERE b.CurrAccCode LIKE '%%' + @Carikod + '%%'
|
||||
WHERE LEFT(REPLACE(b.CurrAccCode, ' ', ''), 7) = REPLACE(@Carikod, ' ', '')
|
||||
AND b.DocumentDate BETWEEN @startdate AND @enddate
|
||||
)
|
||||
|
||||
@@ -158,7 +157,7 @@ SELECT
|
||||
|
||||
FROM Movements m
|
||||
LEFT JOIN Opening o
|
||||
ON o.Cari_Kod = m.Cari_Kod
|
||||
ON o.Cari_Kod = m.Ana_Cari_Kod
|
||||
AND o.Para_Birimi = m.Para_Birimi
|
||||
|
||||
UNION ALL
|
||||
@@ -173,10 +172,10 @@ SELECT
|
||||
COALESCE(
|
||||
(SELECT TOP 1 cd.CurrAccDescription
|
||||
FROM CurrDesc cd
|
||||
WHERE cd.CurrAccCode = @Carikod),
|
||||
WHERE REPLACE(cd.CurrAccCode, ' ', '') = REPLACE(o.Cari_Kod, ' ', '')),
|
||||
(SELECT TOP 1 cd.CurrAccDescription
|
||||
FROM CurrDesc cd
|
||||
WHERE cd.CurrAccCode LIKE '%%' + @Carikod + '%%'
|
||||
WHERE LEFT(REPLACE(cd.CurrAccCode, ' ', ''), 7) = REPLACE(@Carikod, ' ', '')
|
||||
ORDER BY cd.CurrAccCode)
|
||||
) AS Cari_Isim,
|
||||
|
||||
@@ -241,3 +240,18 @@ ORDER BY
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func normalizeMasterAccountCode(code string) string {
|
||||
code = strings.ToUpper(strings.TrimSpace(code))
|
||||
if code == "" {
|
||||
return code
|
||||
}
|
||||
|
||||
noSpace := strings.ReplaceAll(code, " ", "")
|
||||
if len(noSpace) < 7 {
|
||||
return code
|
||||
}
|
||||
|
||||
main := noSpace[:7]
|
||||
return main[:3] + " " + main[3:]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user