Files
bssapp/svc/queries/order_bulk_close.go

345 lines
8.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package queries
import (
"bssapp-backend/auth"
"bssapp-backend/internal/authz"
"context"
"database/sql"
"fmt"
"strings"
)
func resolvePiyasaWhere(ctx context.Context, pg *sql.DB) (string, error) {
claims, ok := auth.GetClaimsFromContext(ctx)
if !ok || claims == nil {
return "", fmt.Errorf("unauthorized: claims not found")
}
if claims.IsAdmin() {
return "1=1", nil
}
codes, err := authz.GetUserPiyasaCodes(pg, int(claims.ID))
if err != nil {
return "", fmt.Errorf("piyasa codes load error: %w", err)
}
if len(codes) == 0 {
return "1=0", nil
}
return authz.BuildINClause("UPPER(f2.CustomerAtt01)", codes), nil
}
func GetOrderListCloseReady(
ctx context.Context,
mssql *sql.DB,
pg *sql.DB,
search string,
) (*sql.Rows, error) {
piyasaWhere, err := resolvePiyasaWhere(ctx, pg)
if err != nil {
return nil, err
}
baseQuery := fmt.Sprintf(`
SELECT
CAST(h.OrderHeaderID AS NVARCHAR(50)) AS OrderHeaderID,
ISNULL(h.OrderNumber, '') AS OrderNumber,
CONVERT(varchar, h.OrderDate, 23) AS OrderDate,
ISNULL(h.CurrAccCode, '') AS CurrAccCode,
ISNULL(ca.CurrAccDescription, '') AS CurrAccDescription,
ISNULL(mt.AttributeDescription, '') AS MusteriTemsilcisi,
ISNULL(py.AttributeDescription, '') AS Piyasa,
CONVERT(varchar, h.CreditableConfirmedDate,23) AS CreditableConfirmedDate,
ISNULL(h.DocCurrencyCode,'TRY') AS DocCurrencyCode,
ISNULL(l.TotalAmount,0) AS TotalAmount,
CASE
WHEN h.DocCurrencyCode = 'USD'
THEN ISNULL(l.TotalAmount,0)
WHEN h.DocCurrencyCode = 'TRY'
AND usd.Rate > 0
THEN ISNULL(l.TotalAmount,0) / usd.Rate
WHEN h.DocCurrencyCode IN ('EUR','GBP')
AND cur.Rate > 0
AND usd.Rate > 0
THEN (ISNULL(l.TotalAmount,0) * cur.Rate) / usd.Rate
ELSE 0
END AS TotalAmountUSD,
ISNULL(l.PackedAmount,0) AS PackedAmount,
CASE
WHEN h.DocCurrencyCode = 'USD'
THEN ISNULL(l.PackedAmount,0)
WHEN h.DocCurrencyCode = 'TRY'
AND usd.Rate > 0
THEN ISNULL(l.PackedTRY,0) / usd.Rate
WHEN cur.Rate > 0
AND usd.Rate > 0
THEN (ISNULL(l.PackedAmount,0) * cur.Rate) / usd.Rate
ELSE 0
END AS PackedUSD,
CASE
WHEN ISNULL(l.TotalAmount,0) > 0
THEN (ISNULL(l.PackedAmount,0) * 100.0) / NULLIF(l.TotalAmount,0)
ELSE 0
END AS PackedRatePct,
ISNULL(h.IsCreditableConfirmed,0) AS IsCreditableConfirmed,
ISNULL(h.Description,'') AS Description,
usd.Rate AS ExchangeRateUSD
FROM dbo.trOrderHeader h
JOIN (
SELECT
l.OrderHeaderID,
SUM(ISNULL(c.NetAmount,0)) AS TotalAmount,
SUM(
CASE
WHEN ISNULL(c.CurrencyCode,'') = 'TRY'
THEN ISNULL(c.NetAmount,0)
ELSE 0
END
) AS TotalTRY,
SUM(
CASE
WHEN ISNULL(l.IsClosed,0) = 1
THEN ISNULL(c.NetAmount,0)
ELSE 0
END
) AS PackedAmount,
SUM(
CASE
WHEN ISNULL(l.IsClosed,0) = 1
AND ISNULL(c.CurrencyCode,'') = 'TRY'
THEN ISNULL(c.NetAmount,0)
ELSE 0
END
) AS PackedTRY
FROM dbo.trOrderLine l
JOIN dbo.trOrderHeader h2
ON h2.OrderHeaderID = l.OrderHeaderID
LEFT JOIN dbo.trOrderLineCurrency c
ON c.OrderLineID = l.OrderLineID
AND c.CurrencyCode = ISNULL(h2.DocCurrencyCode,'TRY')
GROUP BY l.OrderHeaderID
) l
ON l.OrderHeaderID = h.OrderHeaderID
LEFT JOIN dbo.cdCurrAccDesc ca
ON ca.CurrAccCode = h.CurrAccCode
AND ca.LangCode = 'TR'
LEFT JOIN dbo.CustomerAttributesFilter f
ON f.CurrAccCode = h.CurrAccCode
LEFT JOIN dbo.cdCurrAccAttributeDesc mt
ON mt.CurrAccTypeCode = 3
AND mt.AttributeTypeCode = 2
AND mt.AttributeCode = f.CustomerAtt02
AND mt.LangCode = 'TR'
LEFT JOIN dbo.cdCurrAccAttributeDesc py
ON py.CurrAccTypeCode = 3
AND py.AttributeTypeCode = 1
AND py.AttributeCode = f.CustomerAtt01
AND py.LangCode = 'TR'
OUTER APPLY (
SELECT TOP 1 Rate
FROM dbo.AllExchangeRates
WHERE CurrencyCode = 'USD'
AND RelationCurrencyCode = 'TRY'
AND ExchangeTypeCode = 6
AND Rate > 0
AND Date <= CAST(GETDATE() AS date)
ORDER BY Date DESC
) usd
OUTER APPLY (
SELECT TOP 1 Rate
FROM dbo.AllExchangeRates
WHERE CurrencyCode = h.DocCurrencyCode
AND RelationCurrencyCode = 'TRY'
AND ExchangeTypeCode = 6
AND Rate > 0
AND Date <= CAST(GETDATE() AS date)
ORDER BY Date DESC
) cur
WHERE
ISNULL(h.IsCancelOrder,0) = 0
AND h.OrderTypeCode = 1
AND h.ProcessCode = 'WS'
AND h.IsClosed = 0
AND ISNULL(l.TotalAmount,0) > 0
AND (ISNULL(l.PackedAmount,0) * 100.0) / NULLIF(l.TotalAmount,0) >= 100
AND EXISTS (
SELECT 1
FROM dbo.CustomerAttributesFilter f2
WHERE f2.CurrAccCode = h.CurrAccCode
AND %s
)
`, piyasaWhere)
if search != "" {
baseQuery += `
AND EXISTS (
SELECT 1
FROM dbo.trOrderHeader h2
LEFT JOIN dbo.cdCurrAccDesc ca2
ON ca2.CurrAccCode = h2.CurrAccCode
AND ca2.LangCode = 'TR'
WHERE h2.OrderHeaderID = h.OrderHeaderID
AND (
LOWER(REPLACE(REPLACE(h2.OrderNumber,'İ','I'),'ı','i'))
COLLATE Latin1_General_CI_AI LIKE LOWER(@p1)
OR LOWER(REPLACE(REPLACE(h2.CurrAccCode,'İ','I'),'ı','i'))
COLLATE Latin1_General_CI_AI LIKE LOWER(@p1)
OR LOWER(REPLACE(REPLACE(ca2.CurrAccDescription,'İ','I'),'ı','i'))
COLLATE Latin1_General_CI_AI LIKE LOWER(@p1)
OR LOWER(REPLACE(REPLACE(h2.Description,'İ','I'),'ı','i'))
COLLATE Latin1_General_CI_AI LIKE LOWER(@p1)
)
)
`
}
baseQuery += `
ORDER BY h.CreatedDate DESC
`
if search != "" {
searchLike := fmt.Sprintf("%%%s%%", search)
return mssql.Query(baseQuery, searchLike)
}
return mssql.Query(baseQuery)
}
func BulkCloseOrders(
ctx context.Context,
mssql *sql.DB,
pg *sql.DB,
orderNumbers []string,
updatedBy string,
) (int64, error) {
piyasaWhere, err := resolvePiyasaWhere(ctx, pg)
if err != nil {
return 0, err
}
clean := make([]string, 0, len(orderNumbers))
seen := make(map[string]struct{})
for _, n := range orderNumbers {
n = strings.TrimSpace(n)
if n == "" {
continue
}
key := strings.ToUpper(n)
if _, ok := seen[key]; ok {
continue
}
seen[key] = struct{}{}
clean = append(clean, n)
}
if len(clean) == 0 {
return 0, fmt.Errorf("order_numbers is empty")
}
if strings.TrimSpace(updatedBy) == "" {
updatedBy = "SYSTEM"
}
placeholders := make([]string, len(clean))
args := make([]any, 0, len(clean)+1)
args = append(args, updatedBy) // @p1
for i, no := range clean {
placeholders[i] = fmt.Sprintf("@p%d", i+2)
args = append(args, no)
}
tx, err := mssql.BeginTx(ctx, nil)
if err != nil {
return 0, fmt.Errorf("begin tx failed: %w", err)
}
defer tx.Rollback()
q := fmt.Sprintf(`
UPDATE h
SET
h.IsClosed = 1,
h.LastUpdatedDate = GETDATE(),
h.LastUpdatedUserName = @p1
FROM dbo.trOrderHeader h
WHERE
h.IsClosed = 0
AND h.OrderNumber IN (%s)
AND EXISTS (
SELECT 1
FROM dbo.CustomerAttributesFilter f2
WHERE f2.CurrAccCode = h.CurrAccCode
AND %s
)
AND EXISTS (
SELECT 1
FROM (
SELECT
l.OrderHeaderID,
SUM(ISNULL(c.NetAmount,0)) AS TotalAmount,
SUM(
CASE
WHEN ISNULL(l.IsClosed,0) = 1
THEN ISNULL(c.NetAmount,0)
ELSE 0
END
) AS PackedAmount
FROM dbo.trOrderLine l
JOIN dbo.trOrderHeader h2
ON h2.OrderHeaderID = l.OrderHeaderID
LEFT JOIN dbo.trOrderLineCurrency c
ON c.OrderLineID = l.OrderLineID
AND c.CurrencyCode = ISNULL(h2.DocCurrencyCode,'TRY')
GROUP BY l.OrderHeaderID
) t
WHERE t.OrderHeaderID = h.OrderHeaderID
AND t.TotalAmount > 0
AND (t.PackedAmount * 100.0) / NULLIF(t.TotalAmount,0) >= 100
);
`, strings.Join(placeholders, ","), piyasaWhere)
res, err := tx.ExecContext(ctx, q, args...)
if err != nil {
return 0, fmt.Errorf("bulk close update failed: %w", err)
}
affected, err := res.RowsAffected()
if err != nil {
return 0, fmt.Errorf("rows affected read failed: %w", err)
}
if err := tx.Commit(); err != nil {
return 0, fmt.Errorf("commit failed: %w", err)
}
return affected, nil
}