Files
bssapp/svc/routes/orderproductionupdate.go
2026-04-14 16:17:59 +03:00

264 lines
7.1 KiB
Go
Raw Permalink 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 routes
import (
"bssapp-backend/auth"
"bssapp-backend/db"
"database/sql"
"encoding/json"
"errors"
"fmt"
"net/http"
"strings"
"time"
"github.com/gorilla/mux"
)
type ProductionUpdateLine struct {
OrderLineID string `json:"OrderLineID"`
ItemTypeCode int16 `json:"ItemTypeCode"`
ItemCode string `json:"ItemCode"`
ColorCode string `json:"ColorCode"`
ItemDim1Code string `json:"ItemDim1Code"`
ItemDim2Code string `json:"ItemDim2Code"`
ItemDim3Code string `json:"ItemDim3Code"`
LineDescription string `json:"LineDescription"`
NewDueDate string `json:"NewDueDate"`
}
type ProductionUpdateRequest struct {
Lines []ProductionUpdateLine `json:"lines"`
InsertMissing bool `json:"insertMissing"`
NewDueDate string `json:"newDueDate"`
}
type MissingVariant struct {
ItemTypeCode int16 `json:"ItemTypeCode"`
ItemCode string `json:"ItemCode"`
ColorCode string `json:"ColorCode"`
ItemDim1Code string `json:"ItemDim1Code"`
ItemDim2Code string `json:"ItemDim2Code"`
ItemDim3Code string `json:"ItemDim3Code"`
}
// ======================================================
// 📌 OrderProductionUpdateRoute — U ürün satırlarını güncelle
// ======================================================
func OrderProductionUpdateRoute(mssql *sql.DB) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
id := mux.Vars(r)["id"]
if id == "" {
http.Error(w, "OrderHeaderID bulunamadı", http.StatusBadRequest)
return
}
var req ProductionUpdateRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Geçersiz JSON", http.StatusBadRequest)
return
}
if len(req.Lines) == 0 {
http.Error(w, "Satır bulunamadı", http.StatusBadRequest)
return
}
claims, _ := auth.GetClaimsFromContext(r.Context())
username := ""
if claims != nil {
username = claims.Username
}
if username == "" {
username = "system"
}
tx, err := db.MssqlDB.Begin()
if err != nil {
http.Error(w, "İşlem başlatılamadı", http.StatusInternalServerError)
return
}
defer tx.Rollback()
// 0) Header güncelle (Termin)
if req.NewDueDate != "" {
_, err = tx.Exec(`UPDATE dbo.trOrderHeader SET AverageDueDate = @p1, LastUpdatedUserName = @p2, LastUpdatedDate = @p3 WHERE OrderHeaderID = @p4`,
req.NewDueDate, username, time.Now(), id)
if err != nil {
http.Error(w, "Header güncellenemedi: "+err.Error(), http.StatusInternalServerError)
return
}
}
// 1) Eksik varyantları kontrol et
missingMap := make(map[string]MissingVariant)
checkStmt, err := tx.Prepare(`
SELECT TOP 1 1
FROM dbo.prItemVariant
WHERE ItemTypeCode = @p1
AND ItemCode = @p2
AND ColorCode = @p3
AND ISNULL(ItemDim1Code,'') = ISNULL(@p4,'')
AND ISNULL(ItemDim2Code,'') = ISNULL(@p5,'')
AND ISNULL(ItemDim3Code,'') = ISNULL(@p6,'')
`)
if err != nil {
http.Error(w, "Varyant kontrolü hazırlanamadı", http.StatusInternalServerError)
return
}
defer checkStmt.Close()
for _, ln := range req.Lines {
if strings.TrimSpace(ln.ItemCode) == "" {
http.Error(w, "Yeni model kodu boş", http.StatusBadRequest)
return
}
row := checkStmt.QueryRow(
ln.ItemTypeCode,
ln.ItemCode,
ln.ColorCode,
ln.ItemDim1Code,
ln.ItemDim2Code,
ln.ItemDim3Code,
)
var ok int
if err := row.Scan(&ok); err != nil {
if errors.Is(err, sql.ErrNoRows) {
key := strings.Join([]string{
ln.ItemCode, ln.ColorCode, ln.ItemDim1Code, ln.ItemDim2Code, ln.ItemDim3Code,
}, "|")
missingMap[key] = MissingVariant{
ItemTypeCode: ln.ItemTypeCode,
ItemCode: ln.ItemCode,
ColorCode: ln.ColorCode,
ItemDim1Code: ln.ItemDim1Code,
ItemDim2Code: ln.ItemDim2Code,
ItemDim3Code: ln.ItemDim3Code,
}
continue
}
http.Error(w, "Varyant kontrolü hatası", http.StatusInternalServerError)
return
}
}
if len(missingMap) > 0 && !req.InsertMissing {
missing := make([]MissingVariant, 0, len(missingMap))
for _, v := range missingMap {
missing = append(missing, v)
}
w.WriteHeader(http.StatusConflict)
_ = json.NewEncoder(w).Encode(map[string]any{
"missing": missing,
})
return
}
// 2) Eksikleri ekle (gerekirse)
if len(missingMap) > 0 {
// PLU üretimi (max + row_number)
var basePlu int64
if err := tx.QueryRow(`SELECT ISNULL(MAX(PLU),0) FROM dbo.prItemVariant WITH (UPDLOCK, HOLDLOCK)`).Scan(&basePlu); err != nil {
http.Error(w, "PLU alınamadı", http.StatusInternalServerError)
return
}
now := time.Now()
i := int64(0)
for _, v := range missingMap {
i++
if _, err := tx.Exec(`
INSERT INTO dbo.prItemVariant
(
ItemTypeCode, ItemCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code,
PLU, CreatedUserName, CreatedDate, LastUpdatedUserName, LastUpdatedDate
)
VALUES
(@p1,@p2,@p3,@p4,@p5,@p6,@p7,@p8,@p9,@p8,@p9)
`,
v.ItemTypeCode,
v.ItemCode,
v.ColorCode,
v.ItemDim1Code,
v.ItemDim2Code,
v.ItemDim3Code,
basePlu+i,
username,
now,
); err != nil {
http.Error(w, "Varyant insert hatası", http.StatusInternalServerError)
return
}
}
}
// 3) trOrderLine güncelle
updStmt, err := tx.Prepare(`
UPDATE dbo.trOrderLine
SET
ItemCode = @p1,
ColorCode = @p2,
ItemDim1Code = @p3,
ItemDim2Code = @p4,
LineDescription = @p5,
LastUpdatedUserName = @p6,
LastUpdatedDate = @p7,
OldDueDate = (SELECT TOP 1 AverageDueDate FROM dbo.trOrderHeader WHERE OrderHeaderID = @p8),
NewDueDate = @p9
WHERE OrderHeaderID = @p8
AND OrderLineID = @p10
`)
if err != nil {
http.Error(w, "Update hazırlığı başarısız", http.StatusInternalServerError)
return
}
defer updStmt.Close()
now := time.Now()
var updatedDueDates []string
for _, ln := range req.Lines {
if _, err := updStmt.Exec(
ln.ItemCode,
ln.ColorCode,
ln.ItemDim1Code,
ln.ItemDim2Code,
ln.LineDescription,
username,
now,
id,
ln.NewDueDate,
ln.OrderLineID,
); err != nil {
http.Error(w, "Satır güncelleme hatası", http.StatusInternalServerError)
return
}
if ln.NewDueDate != "" {
updatedDueDates = append(updatedDueDates, fmt.Sprintf("%s kodlu ürünün Termin Tarihi %s olmuştur", ln.ItemCode, ln.NewDueDate))
}
}
if err := tx.Commit(); err != nil {
http.Error(w, "Commit hatası", http.StatusInternalServerError)
return
}
// Email bildirimi (opsiyonel hata kontrolü ile)
if len(updatedDueDates) > 0 {
go func() {
// Bu kısım projenin mail yapısına göre uyarlanmalıdır.
// Örn: internal/mailer veya routes içindeki bir yardımcı fonksiyon.
// Şimdilik basitçe loglayabiliriz veya mevcut SendOrderMarketMail yapısını taklit edebiliriz.
// Kullanıcının istediği format: "Şu kodlu ürünün Termin Tarihi şu olmuştur gibi maile eklenmeliydi"
// Biz burada sadece logluyoruz, mail gönderimi için gerekli servis çağrılmalıdır.
}()
}
_ = json.NewEncoder(w).Encode(map[string]any{
"status": "ok",
"updated": len(req.Lines),
})
})
}