Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-03-09 13:19:14 +03:00
parent 6df18ed14d
commit 0d303f0c0f
12 changed files with 382 additions and 280 deletions

View File

@@ -1,27 +0,0 @@
/* Indexes for order validate performance */
IF NOT EXISTS (
SELECT 1
FROM sys.indexes
WHERE name = 'IX_trOrderLine_OrderHeader_ItemCode'
AND object_id = OBJECT_ID('dbo.trOrderLine')
)
BEGIN
CREATE NONCLUSTERED INDEX IX_trOrderLine_OrderHeader_ItemCode
ON dbo.trOrderLine (OrderHeaderID, ItemCode)
INCLUDE (ItemTypeCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code, LineDescription, SortOrder, OrderLineID);
END
GO
IF NOT EXISTS (
SELECT 1
FROM sys.indexes
WHERE name = 'IX_prItemVariant_Combo'
AND object_id = OBJECT_ID('dbo.prItemVariant')
)
BEGIN
CREATE NONCLUSTERED INDEX IX_prItemVariant_Combo
ON dbo.prItemVariant (ItemTypeCode, ItemCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code)
INCLUDE (PLU);
END
GO

View File

@@ -1,18 +0,0 @@
USE [BAGGI_V3]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER PROCEDURE [dbo].[SP_BUILD_STATEMENT_AGING_PIPELINE]
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
EXEC dbo.SP_BUILD_CARI_VADE_GUN_STAGING;
EXEC dbo.SP_BUILD_CARI_BAKIYE_CACHE;
END
GO

View File

@@ -101,15 +101,19 @@ func GetAccounts(ctx context.Context) ([]models.Account, error) {
return nil, err
}
if len(acc.AccountCode) >= 4 {
acc.DisplayCode =
strings.TrimSpace(acc.AccountCode[:3] + " " + acc.AccountCode[3:])
} else {
acc.DisplayCode = acc.AccountCode
}
acc.DisplayCode = formatAccountDisplayCode(acc.AccountCode)
accounts = append(accounts, acc)
}
return accounts, rows.Err()
}
func formatAccountDisplayCode(code string) string {
trimmed := strings.TrimSpace(code)
runes := []rune(trimmed)
if len(runes) <= 3 {
return trimmed
}
return strings.TrimSpace(string(runes[:3]) + " " + string(runes[3:]))
}

View File

@@ -15,15 +15,16 @@ import (
)
type mkCariBakiyeLine struct {
CurrAccTypeCode int
CariKodu string
CariDoviz string
SirketKodu int
PislemTipi string
YerelBakiye float64
Bakiye float64
VadeGun float64
VadeBelgeGun float64
CurrAccTypeCode int
CariKodu string
CariDoviz string
SirketKodu int
PislemTipi string
ParasalIslemTipi string
YerelBakiye float64
Bakiye float64
VadeGun float64
VadeBelgeGun float64
}
type cariMeta struct {
@@ -181,13 +182,13 @@ func GetCustomerBalanceList(ctx context.Context, params models.CustomerBalanceLi
}
usd := toUSD(ln.Bakiye, curr, usdTry, rateMap)
switch strings.TrimSpace(ln.PislemTipi) {
case "1_2":
add12, add13 := resolveBalanceBuckets(ln)
if add12 {
row.Bakiye12 += ln.Bakiye
row.TLBakiye12 += ln.YerelBakiye
row.USDBakiye12 += usd
case "1_3":
}
if add13 {
row.Bakiye13 += ln.Bakiye
row.TLBakiye13 += ln.YerelBakiye
row.USDBakiye13 += usd
@@ -319,13 +320,14 @@ func loadBalanceLines(ctx context.Context, selectedDate, cariSearch string) ([]m
return nil, err
}
query := fmt.Sprintf(`
queryTemplate := `
SELECT
CurrAccTypeCode,
CariKodu,
CariDoviz,
SirketKodu,
PislemTipi,
%s
YerelBakiye,
Bakiye,
CAST(0 AS DECIMAL(18,4)) AS Vade_Gun,
@@ -333,13 +335,33 @@ func loadBalanceLines(ctx context.Context, selectedDate, cariSearch string) ([]m
FROM dbo.MK_CARI_BAKIYE_LIST(@SonTarih)
WHERE (@CariSearch = '' OR CariKodu LIKE '%%' + @CariSearch + '%%')
AND %s
`, piyasaScope)
`
rows, err := db.MssqlDB.QueryContext(ctx, query,
sql.Named("SonTarih", selectedDate),
sql.Named("CariSearch", strings.TrimSpace(cariSearch)),
selectParasalCandidates := make([]string, 0, 7)
if expr := strings.TrimSpace(resolveParasalIslemSelectExpr(ctx, "SELECT * FROM dbo.MK_CARI_BAKIYE_LIST('2000-01-01')")); expr != "" {
selectParasalCandidates = append(selectParasalCandidates, expr)
}
selectParasalCandidates = append(selectParasalCandidates,
"CAST(ATAtt01 AS varchar(16)) AS ParasalIslemTipi,",
"CAST(ParasalIslemTipi AS varchar(16)) AS ParasalIslemTipi,",
"CAST(ParislemTipi AS varchar(16)) AS ParasalIslemTipi,",
"CAST(ParIslemTipi AS varchar(16)) AS ParasalIslemTipi,",
"CAST('' AS varchar(16)) AS ParasalIslemTipi,",
)
if err != nil {
var rows *sql.Rows
for i, sel := range selectParasalCandidates {
query := fmt.Sprintf(queryTemplate, sel, piyasaScope)
rows, err = db.MssqlDB.QueryContext(ctx, query,
sql.Named("SonTarih", selectedDate),
sql.Named("CariSearch", strings.TrimSpace(cariSearch)),
)
if err == nil {
break
}
if i < len(selectParasalCandidates)-1 && isInvalidColumnError(err) {
continue
}
return nil, fmt.Errorf("MK_CARI_BAKIYE_LIST query error: %w", err)
}
defer rows.Close()
@@ -353,6 +375,7 @@ func loadBalanceLines(ctx context.Context, selectedDate, cariSearch string) ([]m
&r.CariDoviz,
&r.SirketKodu,
&r.PislemTipi,
&r.ParasalIslemTipi,
&r.YerelBakiye,
&r.Bakiye,
&r.VadeGun,
@@ -648,7 +671,7 @@ func buildFilters(params models.CustomerBalanceListParams) balanceFilters {
piyasa: parseCSVSet(params.Piyasa),
temsilci: parseCSVSet(params.Temsilci),
riskDurumu: parseCSVSet(params.RiskDurumu),
islemTipi: parseCSVSet(params.IslemTipi),
islemTipi: parseIslemTipiSet(params.IslemTipi),
ulke: parseCSVSet(params.Ulke),
il: parseCSVSet(params.Il),
ilce: parseCSVSet(params.Ilce),
@@ -707,6 +730,28 @@ func parseCSVSet(v string) map[string]struct{} {
return out
}
func parseIslemTipiSet(v string) map[string]struct{} {
raw := parseCSVSet(v)
if len(raw) == 0 {
return raw
}
out := make(map[string]struct{}, 2)
for token := range raw {
switch strings.ToLower(strings.TrimSpace(token)) {
case "1_2", "prbr_1_2", "usd_1_2", "try_1_2", "tl_1_2", "usd_bakiye_1_2", "tl_bakiye_1_2":
out["1_2"] = struct{}{}
case "1_3", "prbr_1_3", "usd_1_3", "try_1_3", "tl_1_3", "usd_bakiye_1_3", "tl_bakiye_1_3":
out["1_3"] = struct{}{}
}
}
if len(out) == 0 {
return raw
}
return out
}
func getAuthorizedPiyasaCodes(ctx context.Context) ([]string, error) {
claims, ok := auth.GetClaimsFromContext(ctx)
if !ok || claims == nil {
@@ -794,3 +839,181 @@ func firstNonEmpty(v ...string) string {
}
return ""
}
func isInvalidColumnError(err error) bool {
if err == nil {
return false
}
msg := strings.ToLower(err.Error())
return strings.Contains(msg, "invalid column name")
}
func shouldSkipBalanceLine(ln mkCariBakiyeLine) bool {
add12, add13 := resolveBalanceBuckets(ln)
p := strings.TrimSpace(ln.PislemTipi)
if p == "1_2" {
return !add12
}
if p == "1_3" {
return !add13
}
return false
}
func resolveBalanceBuckets(ln mkCariBakiyeLine) (add12 bool, add13 bool) {
p := strings.TrimSpace(ln.PislemTipi)
t := normalizeParasalIslemTipi(ln.ParasalIslemTipi)
switch t {
case "1":
return true, true
case "2", "1_2":
return true, false
case "3", "1_3":
return false, true
}
// Parasal tip yoksa eski davranis: PislemTipi'ne gore ayir.
if p == "1_2" {
return true, false
}
if p == "1_3" {
return false, true
}
return false, false
}
func normalizeParasalIslemTipi(v string) string {
s := strings.TrimSpace(v)
if s == "" {
return ""
}
lower := strings.ToLower(s)
compact := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(lower, " ", ""), "-", "_"), "/", "_")
if strings.Contains(compact, "1_2") {
return "1_2"
}
if strings.Contains(compact, "1_3") {
return "1_3"
}
// "1,2" / "1,3" gibi liste formatlarini dogrudan yakala.
tokenized := strings.NewReplacer(" ", "", ";", ",", "|", ",", "/", ",", "-", ",", "_", ",").Replace(lower)
parts := strings.Split(tokenized, ",")
has1 := false
has2 := false
has3 := false
for _, p := range parts {
t := strings.TrimSpace(p)
switch t {
case "1":
has1 = true
case "2":
has2 = true
case "3":
has3 = true
}
}
if has1 && has2 {
return "1_2"
}
if has1 && has3 {
return "1_3"
}
if has2 && !has1 && !has3 {
return "2"
}
if has3 && !has1 && !has2 {
return "3"
}
if has1 && !has2 && !has3 {
return "1"
}
// "2.00", "2,00", " 2 " gibi varyasyonlari tek tipe indir.
s = strings.ReplaceAll(s, ",", ".")
if n, err := strconv.ParseFloat(s, 64); err == nil {
return strconv.Itoa(int(n))
}
// Metinsel geldiyse ilk rakam bloğunu al.
start := -1
end := -1
for i, r := range s {
if r >= '0' && r <= '9' {
if start == -1 {
start = i
}
end = i
continue
}
if start != -1 {
break
}
}
if start == -1 || end < start {
return s
}
return s[start : end+1]
}
func resolveParasalIslemSelectExpr(ctx context.Context, sampleQuery string) string {
sampleQuery = strings.TrimSpace(sampleQuery)
if sampleQuery == "" {
return ""
}
metaQuery := `
SELECT name
FROM sys.dm_exec_describe_first_result_set(@tsql, NULL, 0)
WHERE error_number IS NULL
AND name IS NOT NULL
`
rows, err := db.MssqlDB.QueryContext(ctx, metaQuery, sql.Named("tsql", sampleQuery))
if err != nil {
return ""
}
defer rows.Close()
type candidate struct {
key string
expr string
}
priority := []candidate{
{key: "ata tt01", expr: "CAST(%s AS varchar(16)) AS ParasalIslemTipi,"},
{key: "atatt01", expr: "CAST(%s AS varchar(16)) AS ParasalIslemTipi,"},
{key: "parasalislemtipi", expr: "CAST(%s AS varchar(16)) AS ParasalIslemTipi,"},
{key: "parislemtipi", expr: "CAST(%s AS varchar(16)) AS ParasalIslemTipi,"},
{key: "parislemtur", expr: "CAST(%s AS varchar(16)) AS ParasalIslemTipi,"},
}
available := make(map[string]string)
for rows.Next() {
var col sql.NullString
if err := rows.Scan(&col); err != nil {
return ""
}
name := strings.TrimSpace(col.String)
if name == "" {
continue
}
normalized := strings.ToLower(strings.ReplaceAll(strings.ReplaceAll(name, "_", ""), " ", ""))
available[normalized] = name
}
if err := rows.Err(); err != nil {
return ""
}
for _, c := range priority {
key := strings.ToLower(strings.ReplaceAll(strings.ReplaceAll(c.key, "_", ""), " ", ""))
if col, ok := available[key]; ok {
return fmt.Sprintf(c.expr, quoteSQLIdent(col))
}
}
return ""
}
func quoteSQLIdent(ident string) string {
return "[" + strings.ReplaceAll(strings.TrimSpace(ident), "]", "]]") + "]"
}

View File

@@ -137,13 +137,13 @@ func GetStatementAgingBalanceList(ctx context.Context, params models.CustomerBal
usd := toUSD(ln.Bakiye, curr, usdTry, rateMap)
tl := toTRY(ln.Bakiye, curr, rateMap)
switch strings.TrimSpace(ln.PislemTipi) {
case "1_2":
add12, add13 := resolveBalanceBuckets(ln)
if add12 {
row.Bakiye12 += ln.Bakiye
row.TLBakiye12 += tl
row.USDBakiye12 += usd
case "1_3":
}
if add13 {
row.Bakiye13 += ln.Bakiye
row.TLBakiye13 += tl
row.USDBakiye13 += usd
@@ -187,13 +187,14 @@ func loadAgingBalanceLines(ctx context.Context, cariSearch string) ([]mkCariBaki
return nil, err
}
query := fmt.Sprintf(`
queryTemplate := `
SELECT
CurrAccTypeCode,
CariKodu = LTRIM(RTRIM(CariKodu)),
CariDoviz = LTRIM(RTRIM(CariDoviz)),
SirketKodu,
PislemTipi,
%s
YerelBakiye = CAST(0 AS DECIMAL(18,2)),
Bakiye,
Vade_Gun,
@@ -202,10 +203,30 @@ func loadAgingBalanceLines(ctx context.Context, cariSearch string) ([]mkCariBaki
WHERE (@CariSearch = '' OR LTRIM(RTRIM(CariKodu)) LIKE '%%' + @CariSearch + '%%')
AND %s
ORDER BY CariKodu, CariDoviz, PislemTipi
`, piyasaScope)
`
rows, err := db.MssqlDB.QueryContext(ctx, query, sql.Named("CariSearch", strings.TrimSpace(cariSearch)))
if err != nil {
selectParasalCandidates := make([]string, 0, 7)
if expr := strings.TrimSpace(resolveParasalIslemSelectExpr(ctx, "SELECT * FROM dbo.CARI_BAKIYE_GUN_CACHE")); expr != "" {
selectParasalCandidates = append(selectParasalCandidates, expr)
}
selectParasalCandidates = append(selectParasalCandidates,
"CAST(ATAtt01 AS varchar(16)) AS ParasalIslemTipi,",
"CAST(ParasalIslemTipi AS varchar(16)) AS ParasalIslemTipi,",
"CAST(ParislemTipi AS varchar(16)) AS ParasalIslemTipi,",
"CAST(ParIslemTipi AS varchar(16)) AS ParasalIslemTipi,",
"CAST('' AS varchar(16)) AS ParasalIslemTipi,",
)
var rows *sql.Rows
for i, sel := range selectParasalCandidates {
query := fmt.Sprintf(queryTemplate, sel, piyasaScope)
rows, err = db.MssqlDB.QueryContext(ctx, query, sql.Named("CariSearch", strings.TrimSpace(cariSearch)))
if err == nil {
break
}
if i < len(selectParasalCandidates)-1 && isInvalidColumnError(err) {
continue
}
return nil, fmt.Errorf("CARI_BAKIYE_GUN_CACHE query error: %w", err)
}
defer rows.Close()
@@ -219,6 +240,7 @@ func loadAgingBalanceLines(ctx context.Context, cariSearch string) ([]mkCariBaki
&r.CariDoviz,
&r.SirketKodu,
&r.PislemTipi,
&r.ParasalIslemTipi,
&r.YerelBakiye,
&r.Bakiye,
&r.VadeGun,

View File

@@ -23,7 +23,10 @@ SELECT
a.ItemCode AS Urun_Kodu,
a.ColorCode AS Urun_Rengi,
SUM(a.Qty1) AS Toplam_Adet,
SUM(ABS(a.Doc_Price)) AS Toplam_Fiyat,
CAST(
SUM(a.Qty1 * ABS(a.Doc_Price)) / NULLIF(SUM(a.Qty1), 0)
AS numeric(18,2)
) AS Toplam_Fiyat,
CAST(SUM(a.Qty1 * ABS(a.Doc_Price)) AS numeric(18,2)) AS Toplam_Tutar
FROM AllInvoicesWithAttributes a
LEFT JOIN prItemAttribute AnaGrup

View File

@@ -23,25 +23,34 @@ type ProductImageItem struct {
ContentURL string `json:"content_url"`
}
//
// LIST PRODUCT IMAGES
//
// GET /api/product-images?code=...&color=...
func GetProductImagesHandler(pg *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
reqID := strings.TrimSpace(r.Header.Get("X-Request-ID"))
if reqID == "" {
reqID = uuid.NewString()
}
w.Header().Set("X-Request-ID", reqID)
code := strings.TrimSpace(r.URL.Query().Get("code"))
color := strings.TrimSpace(r.URL.Query().Get("color"))
if code == "" {
slog.Warn("product_images.list.bad_request",
"req_id", reqID,
"path", r.URL.Path,
"query", r.URL.RawQuery,
"reason", "missing_code",
)
http.Error(w, "Eksik parametre: code gerekli", http.StatusBadRequest)
return
}
@@ -50,38 +59,59 @@ func GetProductImagesHandler(pg *sql.DB) http.HandlerFunc {
SELECT
b.id,
b.file_name,
COALESCE(b.file_size, 0) AS file_size,
COALESCE(b.storage_path, '') AS storage_path
COALESCE(b.file_size,0) AS file_size,
COALESCE(b.storage_path,'') AS storage_path
FROM dfblob b
JOIN mmitem i
ON i.id = b.src_id
WHERE b.typ = 'img'
AND b.src_table = 'mmitem'
AND UPPER(i.code) = UPPER($1)
AND ($2 = '' OR b.file_name ILIKE '%' || '-' || $2 || '-%')
ORDER BY COALESCE(b.sort_order, 999999), b.zlins_dttm DESC, b.id DESC
AND (
$2 = ''
OR b.file_name ILIKE '%' || '-' || $2 || '-%'
OR b.file_name ILIKE '%' || '-' || $2 || '_%'
)
ORDER BY
COALESCE(b.sort_order,999999),
b.zlins_dttm DESC,
b.id DESC
`
rows, err := pg.Query(query, code, color)
if err != nil {
slog.Error("product_images.list.query_failed",
"req_id", reqID,
"code", code,
"color", color,
"err", err.Error(),
)
http.Error(w, "Gorsel sorgu hatasi: "+err.Error(), http.StatusInternalServerError)
return
}
defer rows.Close()
items := make([]ProductImageItem, 0, 16)
for rows.Next() {
var it ProductImageItem
if err := rows.Scan(&it.ID, &it.FileName, &it.FileSize, &it.Storage); err != nil {
if err := rows.Scan(
&it.ID,
&it.FileName,
&it.FileSize,
&it.Storage,
); err != nil {
continue
}
it.ContentURL = fmt.Sprintf("/api/product-images/%d/content", it.ID)
items = append(items, it)
}
@@ -97,24 +127,35 @@ ORDER BY COALESCE(b.sort_order, 999999), b.zlins_dttm DESC, b.id DESC
}
}
//
// GET IMAGE CONTENT
//
// GET /api/product-images/{id}/content
func GetProductImageContentHandler(pg *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
reqID := strings.TrimSpace(r.Header.Get("X-Request-ID"))
if reqID == "" {
reqID = uuid.NewString()
}
w.Header().Set("X-Request-ID", reqID)
idStr := mux.Vars(r)["id"]
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil || id <= 0 {
slog.Warn("product_images.content.bad_request",
"req_id", reqID,
"id_raw", idStr,
"path", r.URL.Path,
"reason", "invalid_id",
)
http.Error(w, "Gecersiz gorsel id", http.StatusBadRequest)
return
}
@@ -128,83 +169,89 @@ func GetProductImageContentHandler(pg *sql.DB) http.HandlerFunc {
err = pg.QueryRow(`
SELECT
COALESCE(file_name, ''),
COALESCE(storage_path, ''),
COALESCE(stored_in_db, false),
COALESCE(file_name,''),
COALESCE(storage_path,''),
COALESCE(stored_in_db,false),
bin
FROM dfblob
WHERE id = $1
AND typ = 'img'
`, id).Scan(&fileName, &storagePath, &storedInDB, &binData)
if err != nil {
if err == sql.ErrNoRows {
slog.Warn("product_images.content.not_found_row",
"req_id", reqID,
"id", id,
)
http.NotFound(w, r)
return
}
slog.Error("product_images.content.query_failed",
"req_id", reqID,
"id", id,
"err", err.Error(),
)
http.Error(w, "Gorsel okunamadi: "+err.Error(), http.StatusInternalServerError)
return
}
// DB içinde binary saklıysa
if storedInDB && len(binData) > 0 {
slog.Info("product_images.content.served_from_db",
"req_id", reqID,
"id", id,
"file_name", fileName,
"bytes", len(binData),
)
w.Header().Set("Content-Type", http.DetectContentType(binData))
w.Header().Set("Cache-Control", "public, max-age=3600")
_, _ = w.Write(binData)
return
}
resolved, tried := resolveStoragePath(storagePath)
if resolved == "" {
slog.Warn("product_images.content.file_not_found",
"req_id", reqID,
"id", id,
"stored_in_db", storedInDB,
"file_name", fileName,
"storage_path", storagePath,
"tried", tried,
)
http.NotFound(w, r)
return
}
slog.Info("product_images.content.served_from_file",
"req_id", reqID,
"id", id,
"file_name", fileName,
"storage_path", storagePath,
"resolved_path", resolved,
)
w.Header().Set("Cache-Control", "public, max-age=3600")
http.ServeFile(w, r, resolved)
}
}
//
// FILE PATH RESOLVER
//
func resolveStoragePath(storagePath string) (string, []string) {
raw := strings.TrimSpace(storagePath)
if raw == "" {
return "", nil
}
// URL/query temizligi ve platforma uygun normalize
if i := strings.Index(raw, "?"); i >= 0 {
raw = raw[:i]
}
raw = strings.ReplaceAll(raw, "\\", "/")
if scheme := strings.Index(raw, "://"); scheme >= 0 {
rest := raw[scheme+3:]
if i := strings.Index(rest, "/"); i >= 0 {
@@ -215,47 +262,36 @@ func resolveStoragePath(storagePath string) (string, []string) {
raw = strings.TrimPrefix(raw, "./")
raw = strings.TrimPrefix(raw, "/")
raw = strings.TrimPrefix(raw, "uploads/")
raw = filepath.ToSlash(filepath.Clean(raw))
relUploads := filepath.FromSlash(filepath.Join("uploads", raw))
rawT300 := raw
relUploadsT300 := relUploads
if strings.Contains(filepath.ToSlash(relUploads), "uploads/image/") &&
!strings.Contains(filepath.ToSlash(relUploads), "uploads/image/t300/") {
rawT300 = strings.Replace(filepath.ToSlash(raw), "image/", "image/t300/", 1)
relUploadsT300 = filepath.FromSlash(
strings.Replace(filepath.ToSlash(relUploads), "uploads/image/", "uploads/image/t300/", 1),
)
}
candidates := []string{
filepath.Clean(storagePath),
filepath.FromSlash(filepath.Clean(strings.TrimPrefix(storagePath, "/"))),
filepath.FromSlash(filepath.Clean(raw)),
relUploads,
relUploadsT300,
filepath.Join(".", relUploads),
filepath.Join(".", relUploadsT300),
filepath.Join("..", relUploads),
filepath.Join("..", relUploadsT300),
filepath.Join("..", "..", relUploads),
filepath.Join("..", "..", relUploadsT300),
}
if root := strings.TrimSpace(os.Getenv("BLOB_ROOT")); root != "" {
candidates = append(candidates,
filepath.Join(root, raw),
filepath.Join(root, filepath.FromSlash(rawT300)),
filepath.Join(root, relUploads),
filepath.Join(root, relUploadsT300),
filepath.Join(root, "uploads", raw),
filepath.Join(root, "uploads", filepath.FromSlash(rawT300)),
)
}
for _, p := range candidates {
if p == "" {
continue
}
if st, err := os.Stat(p); err == nil && !st.IsDir() {
return p, candidates
}

View File

@@ -1,125 +0,0 @@
/* eslint-disable */
/**
* THIS FILE IS GENERATED AUTOMATICALLY.
* 1. DO NOT edit this file directly as it won't do anything.
* 2. EDIT the original quasar.config file INSTEAD.
* 3. DO NOT git commit this file. It should be ignored.
*
* This file is still here because there was an error in
* the original quasar.config file and this allows you to
* investigate the Node.js stack error.
*
* After you fix the original file, this file will be
* deleted automatically.
**/
// quasar.config.js
import { defineConfig } from "@quasar/app-webpack/wrappers";
var quasar_config_default = defineConfig(() => {
const apiBaseUrl = (process.env.VITE_API_BASE_URL || "/api").trim();
return {
/* =====================================================
APP INFO
===================================================== */
productName: "Baggi BSS",
productDescription: "Baggi Tekstil Business Support System",
/* =====================================================
BOOT FILES
===================================================== */
boot: ["dayjs"],
/* =====================================================
GLOBAL CSS
===================================================== */
css: ["app.css"],
/* =====================================================
ICONS / FONTS
===================================================== */
extras: [
"roboto-font",
"material-icons"
],
/* =====================================================
BUILD (PRODUCTION)
===================================================== */
build: {
vueRouterMode: "hash",
env: {
VITE_API_BASE_URL: apiBaseUrl
},
esbuildTarget: {
browser: ["es2022", "firefox115", "chrome115", "safari14"],
node: "node20"
},
// Cache & performance
gzip: true,
preloadChunks: true
},
/* =====================================================
DEV SERVER (LOCAL)
===================================================== */
devServer: {
server: { type: "http" },
port: 9e3,
open: true,
// DEV proxy (CORS'suz)
proxy: [
{
context: ["/api"],
target: "http://localhost:8080",
changeOrigin: true,
secure: false
}
]
},
/* =====================================================
QUASAR FRAMEWORK
===================================================== */
framework: {
config: {
notify: {
position: "top",
timeout: 2500
}
},
lang: "tr",
plugins: [
"Loading",
"Dialog",
"Notify"
]
},
animations: [],
/* =====================================================
SSR / PWA (DISABLED)
===================================================== */
ssr: {
prodPort: 3e3,
middlewares: ["render"],
pwa: false
},
pwa: {
workboxMode: "GenerateSW"
},
/* =====================================================
MOBILE / DESKTOP
===================================================== */
capacitor: {
hideSplashscreen: true
},
electron: {
preloadScripts: ["electron-preload"],
inspectPort: 5858,
bundler: "packager",
builder: {
appId: "baggisowtfaresystem"
}
},
bex: {
extraScripts: []
}
};
});
export {
quasar_config_default as default
};

View File

@@ -635,12 +635,8 @@ const canReadFinance = canRead('finance')
const canExportFinance = canExport('finance')
const islemTipiOptions = [
{ label: '1_2 Bakiye Pr.Br', value: 'prbr_1_2' },
{ label: '1_3 Bakiye Pr.Br', value: 'prbr_1_3' },
{ label: '1_2 USD Bakiye', value: 'usd_1_2' },
{ label: '1_2 TRY Bakiye', value: 'try_1_2' },
{ label: '1_3 USD Bakiye', value: 'usd_1_3' },
{ label: '1_3 TRY Bakiye', value: 'try_1_3' }
{ label: '1_2', value: '1_2' },
{ label: '1_3', value: '1_3' }
]
const staticMoneyFields = ['usd_bakiye_1_2', 'tl_bakiye_1_2', 'usd_bakiye_1_3', 'tl_bakiye_1_3']
@@ -688,11 +684,7 @@ const metricDefs = {
try_1_3: { name: 'tl_bakiye_1_3', label: '1_3 TRY_BAKIYE', field: 'tl_bakiye_1_3', align: 'center', sortable: true, sort: (a, b) => toNumericSortValue(a) - toNumericSortValue(b) }
}
const selectedMetricKeys = computed(() => {
const selected = store.filters.islemTipi || []
if (!selected.length) return [...Object.keys(metricDefs)]
return selected.filter((k) => k in metricDefs)
})
const selectedMetricKeys = computed(() => [...Object.keys(metricDefs)])
const summaryColumns = computed(() => ([
{ name: 'expand', label: '', field: 'expand', align: 'center', sortable: false },

View File

@@ -538,12 +538,8 @@ const canReadFinance = canRead('finance')
const canExportFinance = canExport('finance')
const islemTipiOptions = [
{ label: '1_2 Bakiye Pr.Br', value: 'prbr_1_2' },
{ label: '1_3 Bakiye Pr.Br', value: 'prbr_1_3' },
{ label: '1_2 USD Bakiye', value: 'usd_1_2' },
{ label: '1_2 TRY Bakiye', value: 'try_1_2' },
{ label: '1_3 USD Bakiye', value: 'usd_1_3' },
{ label: '1_3 TRY Bakiye', value: 'try_1_3' }
{ label: '1_2', value: '1_2' },
{ label: '1_3', value: '1_3' }
]
const staticMoneyFields = ['usd_bakiye_1_2', 'tl_bakiye_1_2', 'usd_bakiye_1_3', 'tl_bakiye_1_3']
@@ -590,11 +586,7 @@ const metricDefs = {
try_1_3: { name: 'tl_bakiye_1_3', label: '1_3 TRY_BAKIYE', field: 'tl_bakiye_1_3', align: 'center', sortable: true, sort: (a, b) => toNumericSortValue(a) - toNumericSortValue(b) }
}
const selectedMetricKeys = computed(() => {
const selected = store.filters.islemTipi || []
if (!selected.length) return Object.keys(metricDefs)
return selected.filter((k) => k in metricDefs)
})
const selectedMetricKeys = computed(() => Object.keys(metricDefs))
const summaryColumns = computed(() => ([
{ name: 'expand', label: '', field: 'expand', align: 'center', sortable: false },

View File

@@ -78,12 +78,8 @@ export const useAccountAgingBalanceStore = defineStore('accountAgingBalance', {
const islemTipiOk =
!state.filters.islemTipi.length ||
state.filters.islemTipi.some((t) => {
if (t === 'prbr_1_2') return bak12 !== 0
if (t === 'prbr_1_3') return bak13 !== 0
if (t === 'usd_1_2') return usd12 !== 0
if (t === 'try_1_2') return try12 !== 0
if (t === 'usd_1_3') return usd13 !== 0
if (t === 'try_1_3') return try13 !== 0
if (t === '1_2') return bak12 !== 0 || usd12 !== 0 || try12 !== 0
if (t === '1_3') return bak13 !== 0 || usd13 !== 0 || try13 !== 0
return false
})

View File

@@ -92,12 +92,8 @@ export const useCustomerBalanceListStore = defineStore('customerBalanceList', {
const islemTipiOk =
!state.filters.islemTipi.length ||
state.filters.islemTipi.some((t) => {
if (t === 'prbr_1_2') return bak12 !== 0
if (t === 'prbr_1_3') return bak13 !== 0
if (t === 'usd_1_2') return usd12 !== 0
if (t === 'try_1_2') return try12 !== 0
if (t === 'usd_1_3') return usd13 !== 0
if (t === 'try_1_3') return try13 !== 0
if (t === '1_2') return bak12 !== 0 || usd12 !== 0 || try12 !== 0
if (t === '1_3') return bak13 !== 0 || usd13 !== 0 || try13 !== 0
return false
})
@@ -194,7 +190,15 @@ export const useCustomerBalanceListStore = defineStore('customerBalanceList', {
const { data } = await api.get('/finance/customer-balances', {
params: {
selected_date: this.filters.selectedDate,
cari_search: String(this.filters.cariSearch || '').trim()
cari_search: String(this.filters.cariSearch || '').trim(),
cari_ilk_grup: (this.filters.cariIlkGrup || []).join(','),
piyasa: (this.filters.piyasa || []).join(','),
temsilci: (this.filters.temsilci || []).join(','),
risk_durumu: (this.filters.riskDurumu || []).join(','),
islem_tipi: (this.filters.islemTipi || []).join(','),
ulke: (this.filters.ulke || []).join(','),
il: (this.filters.il || []).join(','),
ilce: (this.filters.ilce || []).join(',')
}
})
this.rows = Array.isArray(data) ? data : []