Merge remote-tracking branch 'origin/master'
This commit is contained in:
10
svc/main.go
10
svc/main.go
@@ -576,6 +576,11 @@ func InitRoutes(pgDB *sql.DB, mssql *sql.DB, ml *mailer.GraphMailer) *mux.Router
|
|||||||
"order", "view",
|
"order", "view",
|
||||||
wrapV3(http.HandlerFunc(routes.GetProductColorsHandler)),
|
wrapV3(http.HandlerFunc(routes.GetProductColorsHandler)),
|
||||||
)
|
)
|
||||||
|
bindV3(r, pgDB,
|
||||||
|
"/api/product-newcolors", "GET",
|
||||||
|
"order", "view",
|
||||||
|
wrapV3(http.HandlerFunc(routes.GetProductNewColorsHandler)),
|
||||||
|
)
|
||||||
|
|
||||||
bindV3(r, pgDB,
|
bindV3(r, pgDB,
|
||||||
"/api/product-colorsize", "GET",
|
"/api/product-colorsize", "GET",
|
||||||
@@ -588,6 +593,11 @@ func InitRoutes(pgDB *sql.DB, mssql *sql.DB, ml *mailer.GraphMailer) *mux.Router
|
|||||||
"order", "view",
|
"order", "view",
|
||||||
wrapV3(http.HandlerFunc(routes.GetProductSecondColorsHandler)),
|
wrapV3(http.HandlerFunc(routes.GetProductSecondColorsHandler)),
|
||||||
)
|
)
|
||||||
|
bindV3(r, pgDB,
|
||||||
|
"/api/product-newsecondcolor", "GET",
|
||||||
|
"order", "view",
|
||||||
|
wrapV3(http.HandlerFunc(routes.GetProductNewSecondColorsHandler)),
|
||||||
|
)
|
||||||
bindV3(r, pgDB,
|
bindV3(r, pgDB,
|
||||||
"/api/product-attributes", "GET",
|
"/api/product-attributes", "GET",
|
||||||
"order", "view",
|
"order", "view",
|
||||||
|
|||||||
@@ -65,10 +65,6 @@ func InsertMissingProductionVariants(mssql *sql.DB, orderHeaderID string, userna
|
|||||||
WHERE l.OrderHeaderID = @p1
|
WHERE l.OrderHeaderID = @p1
|
||||||
AND ISNULL(l.ItemCode,'') LIKE 'U%'
|
AND ISNULL(l.ItemCode,'') LIKE 'U%'
|
||||||
AND pv.ItemCode IS NULL
|
AND pv.ItemCode IS NULL
|
||||||
),
|
|
||||||
MaxPlu AS (
|
|
||||||
SELECT ISNULL(MAX(PLU),0) AS BasePlu
|
|
||||||
FROM dbo.prItemVariant WITH (UPDLOCK, HOLDLOCK)
|
|
||||||
)
|
)
|
||||||
INSERT INTO dbo.prItemVariant (
|
INSERT INTO dbo.prItemVariant (
|
||||||
ItemTypeCode,
|
ItemTypeCode,
|
||||||
@@ -77,7 +73,6 @@ INSERT INTO dbo.prItemVariant (
|
|||||||
ItemDim1Code,
|
ItemDim1Code,
|
||||||
ItemDim2Code,
|
ItemDim2Code,
|
||||||
ItemDim3Code,
|
ItemDim3Code,
|
||||||
PLU,
|
|
||||||
IsSalesOrderClosed,
|
IsSalesOrderClosed,
|
||||||
IsPurchaseOrderClosed,
|
IsPurchaseOrderClosed,
|
||||||
IsLocked,
|
IsLocked,
|
||||||
@@ -97,7 +92,6 @@ SELECT
|
|||||||
m.ItemDim1Code,
|
m.ItemDim1Code,
|
||||||
m.ItemDim2Code,
|
m.ItemDim2Code,
|
||||||
m.ItemDim3Code,
|
m.ItemDim3Code,
|
||||||
mp.BasePlu + ROW_NUMBER() OVER (ORDER BY m.ItemCode, m.ColorCode, m.ItemDim1Code, m.ItemDim2Code, m.ItemDim3Code),
|
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -109,8 +103,7 @@ SELECT
|
|||||||
NEWID(),
|
NEWID(),
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
FROM Missing m
|
FROM Missing m;
|
||||||
CROSS JOIN MaxPlu mp;
|
|
||||||
`
|
`
|
||||||
|
|
||||||
res, err := mssql.Exec(query, orderHeaderID, username)
|
res, err := mssql.Exec(query, orderHeaderID, username)
|
||||||
@@ -140,17 +133,67 @@ WHERE OrderHeaderID = @p1 AND OrderLineID = @p2
|
|||||||
return itemTypeCode, dim1, dim2, dim3, err
|
return itemTypeCode, dim1, dim2, dim3, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OrderLineDims struct {
|
||||||
|
ItemTypeCode int16
|
||||||
|
ItemDim1Code string
|
||||||
|
ItemDim2Code string
|
||||||
|
ItemDim3Code string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOrderLineDimsMap(mssql *sql.DB, orderHeaderID string) (map[string]OrderLineDims, error) {
|
||||||
|
rows, err := mssql.Query(`
|
||||||
|
SELECT
|
||||||
|
CAST(OrderLineID AS NVARCHAR(50)) AS OrderLineID,
|
||||||
|
ItemTypeCode,
|
||||||
|
ISNULL(ItemDim1Code,'') AS ItemDim1Code,
|
||||||
|
ISNULL(ItemDim2Code,'') AS ItemDim2Code,
|
||||||
|
ISNULL(ItemDim3Code,'') AS ItemDim3Code
|
||||||
|
FROM dbo.trOrderLine WITH(NOLOCK)
|
||||||
|
WHERE OrderHeaderID = @p1
|
||||||
|
`, orderHeaderID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
out := make(map[string]OrderLineDims, 128)
|
||||||
|
for rows.Next() {
|
||||||
|
var lineID string
|
||||||
|
var d OrderLineDims
|
||||||
|
if err := rows.Scan(&lineID, &d.ItemTypeCode, &d.ItemDim1Code, &d.ItemDim2Code, &d.ItemDim3Code); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out[strings.TrimSpace(lineID)] = d
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func VariantExists(mssql *sql.DB, itemTypeCode int16, itemCode string, colorCode string, dim1 string, dim2 string, dim3 string) (bool, error) {
|
func VariantExists(mssql *sql.DB, itemTypeCode int16, itemCode string, colorCode string, dim1 string, dim2 string, dim3 string) (bool, error) {
|
||||||
var exists int
|
var exists int
|
||||||
err := mssql.QueryRow(`
|
err := mssql.QueryRow(`
|
||||||
SELECT TOP 1 1
|
SELECT TOP 1 1
|
||||||
FROM dbo.prItemVariant
|
FROM dbo.prItemVariant
|
||||||
WHERE ItemTypeCode = @p1
|
WHERE ItemTypeCode = @p1
|
||||||
AND ISNULL(LTRIM(RTRIM(ItemCode)),'') = ISNULL(LTRIM(RTRIM(@p2)),'')
|
AND ItemCode = @p2
|
||||||
AND ISNULL(LTRIM(RTRIM(ColorCode)),'') = ISNULL(LTRIM(RTRIM(@p3)),'')
|
AND (
|
||||||
AND ISNULL(LTRIM(RTRIM(ItemDim1Code)),'') = ISNULL(LTRIM(RTRIM(@p4)),'')
|
ColorCode = @p3
|
||||||
AND ISNULL(LTRIM(RTRIM(ItemDim2Code)),'') = ISNULL(LTRIM(RTRIM(@p5)),'')
|
OR (@p3 = '' AND (ColorCode IS NULL OR ColorCode = ''))
|
||||||
AND ISNULL(LTRIM(RTRIM(ItemDim3Code)),'') = ISNULL(LTRIM(RTRIM(@p6)),'')
|
)
|
||||||
|
AND (
|
||||||
|
ItemDim1Code = @p4
|
||||||
|
OR (@p4 = '' AND (ItemDim1Code IS NULL OR ItemDim1Code = ''))
|
||||||
|
)
|
||||||
|
AND (
|
||||||
|
ItemDim2Code = @p5
|
||||||
|
OR (@p5 = '' AND (ItemDim2Code IS NULL OR ItemDim2Code = ''))
|
||||||
|
)
|
||||||
|
AND (
|
||||||
|
ItemDim3Code = @p6
|
||||||
|
OR (@p6 = '' AND (ItemDim3Code IS NULL OR ItemDim3Code = ''))
|
||||||
|
)
|
||||||
`, itemTypeCode, itemCode, colorCode, dim1, dim2, dim3).Scan(&exists)
|
`, itemTypeCode, itemCode, colorCode, dim1, dim2, dim3).Scan(&exists)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return false, nil
|
return false, nil
|
||||||
@@ -171,17 +214,24 @@ func InsertMissingVariantsTx(
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var basePlu int64
|
|
||||||
if err := tx.QueryRow(`
|
|
||||||
SELECT ISNULL(MAX(PLU),0) AS BasePlu
|
|
||||||
FROM dbo.prItemVariant WITH (UPDLOCK, HOLDLOCK)
|
|
||||||
`).Scan(&basePlu); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var inserted int64
|
var inserted int64
|
||||||
ensuredItems := make(map[string]struct{}, len(missing))
|
ensuredItems := make(map[string]struct{}, len(missing))
|
||||||
for i, v := range missing {
|
uniqueVariants := make([]models.OrderProductionMissingVariant, 0, len(missing))
|
||||||
|
seenVariants := make(map[string]struct{}, len(missing))
|
||||||
|
|
||||||
|
for _, v := range missing {
|
||||||
|
variantKey := strconv.FormatInt(int64(v.ItemTypeCode), 10) + "|" +
|
||||||
|
strings.ToUpper(strings.TrimSpace(v.ItemCode)) + "|" +
|
||||||
|
strings.ToUpper(strings.TrimSpace(v.ColorCode)) + "|" +
|
||||||
|
strings.ToUpper(strings.TrimSpace(v.ItemDim1Code)) + "|" +
|
||||||
|
strings.ToUpper(strings.TrimSpace(v.ItemDim2Code)) + "|" +
|
||||||
|
strings.ToUpper(strings.TrimSpace(v.ItemDim3Code))
|
||||||
|
if _, ok := seenVariants[variantKey]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seenVariants[variantKey] = struct{}{}
|
||||||
|
uniqueVariants = append(uniqueVariants, v)
|
||||||
|
|
||||||
itemKey := strconv.FormatInt(int64(v.ItemTypeCode), 10) + "|" + v.ItemCode
|
itemKey := strconv.FormatInt(int64(v.ItemTypeCode), 10) + "|" + v.ItemCode
|
||||||
if _, ok := ensuredItems[itemKey]; !ok {
|
if _, ok := ensuredItems[itemKey]; !ok {
|
||||||
draft, hasDraft := cdItemByCode[itemKey]
|
draft, hasDraft := cdItemByCode[itemKey]
|
||||||
@@ -198,18 +248,28 @@ FROM dbo.prItemVariant WITH (UPDLOCK, HOLDLOCK)
|
|||||||
}
|
}
|
||||||
ensuredItems[itemKey] = struct{}{}
|
ensuredItems[itemKey] = struct{}{}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
plu := basePlu + int64(i) + 1
|
if len(uniqueVariants) == 0 {
|
||||||
res, err := tx.Exec(`
|
return 0, nil
|
||||||
IF NOT EXISTS (
|
}
|
||||||
SELECT 1
|
|
||||||
FROM dbo.prItemVariant
|
args := make([]any, 0, len(uniqueVariants)*6+1)
|
||||||
WHERE ItemTypeCode = @p1
|
valueRows := make([]string, 0, len(uniqueVariants))
|
||||||
AND ISNULL(LTRIM(RTRIM(ItemCode)),'') = ISNULL(LTRIM(RTRIM(@p2)),'')
|
paramPos := 1
|
||||||
AND ISNULL(LTRIM(RTRIM(ColorCode)),'') = ISNULL(LTRIM(RTRIM(@p3)),'')
|
for _, v := range uniqueVariants {
|
||||||
AND ISNULL(LTRIM(RTRIM(ItemDim1Code)),'') = ISNULL(LTRIM(RTRIM(@p4)),'')
|
valueRows = append(valueRows, fmt.Sprintf("(@p%d,@p%d,@p%d,@p%d,@p%d,@p%d)", paramPos, paramPos+1, paramPos+2, paramPos+3, paramPos+4, paramPos+5))
|
||||||
AND ISNULL(LTRIM(RTRIM(ItemDim2Code)),'') = ISNULL(LTRIM(RTRIM(@p5)),'')
|
args = append(args, v.ItemTypeCode, v.ItemCode, v.ColorCode, v.ItemDim1Code, v.ItemDim2Code, v.ItemDim3Code)
|
||||||
AND ISNULL(LTRIM(RTRIM(ItemDim3Code)),'') = ISNULL(LTRIM(RTRIM(@p6)),'')
|
paramPos += 6
|
||||||
|
}
|
||||||
|
usernameParam := paramPos
|
||||||
|
args = append(args, username)
|
||||||
|
|
||||||
|
query := fmt.Sprintf(`
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
WITH Missing(ItemTypeCode, ItemCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code) AS (
|
||||||
|
SELECT *
|
||||||
|
FROM (VALUES %s) AS v(ItemTypeCode, ItemCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code)
|
||||||
)
|
)
|
||||||
INSERT INTO dbo.prItemVariant (
|
INSERT INTO dbo.prItemVariant (
|
||||||
ItemTypeCode,
|
ItemTypeCode,
|
||||||
@@ -218,7 +278,6 @@ INSERT INTO dbo.prItemVariant (
|
|||||||
ItemDim1Code,
|
ItemDim1Code,
|
||||||
ItemDim2Code,
|
ItemDim2Code,
|
||||||
ItemDim3Code,
|
ItemDim3Code,
|
||||||
PLU,
|
|
||||||
IsSalesOrderClosed,
|
IsSalesOrderClosed,
|
||||||
IsPurchaseOrderClosed,
|
IsPurchaseOrderClosed,
|
||||||
IsLocked,
|
IsLocked,
|
||||||
@@ -231,23 +290,48 @@ INSERT INTO dbo.prItemVariant (
|
|||||||
UseInternet,
|
UseInternet,
|
||||||
IsStoreOrderClosed
|
IsStoreOrderClosed
|
||||||
)
|
)
|
||||||
VALUES (
|
SELECT
|
||||||
@p1, @p2, @p3, @p4, @p5, @p6,
|
m.ItemTypeCode,
|
||||||
@p7,
|
m.ItemCode,
|
||||||
|
m.ColorCode,
|
||||||
|
m.ItemDim1Code,
|
||||||
|
m.ItemDim2Code,
|
||||||
|
m.ItemDim3Code,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
@p8, GETDATE(), @p8, GETDATE(),
|
@p%d, GETDATE(), @p%d, GETDATE(),
|
||||||
NEWID(),
|
NEWID(),
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
);
|
FROM Missing m
|
||||||
`, v.ItemTypeCode, v.ItemCode, v.ColorCode, v.ItemDim1Code, v.ItemDim2Code, v.ItemDim3Code, plu, username)
|
LEFT JOIN dbo.prItemVariant pv
|
||||||
|
ON pv.ItemTypeCode = m.ItemTypeCode
|
||||||
|
AND pv.ItemCode = m.ItemCode
|
||||||
|
AND (
|
||||||
|
pv.ColorCode = m.ColorCode
|
||||||
|
OR (m.ColorCode = '' AND (pv.ColorCode IS NULL OR pv.ColorCode = ''))
|
||||||
|
)
|
||||||
|
AND (
|
||||||
|
pv.ItemDim1Code = m.ItemDim1Code
|
||||||
|
OR (m.ItemDim1Code = '' AND (pv.ItemDim1Code IS NULL OR pv.ItemDim1Code = ''))
|
||||||
|
)
|
||||||
|
AND (
|
||||||
|
pv.ItemDim2Code = m.ItemDim2Code
|
||||||
|
OR (m.ItemDim2Code = '' AND (pv.ItemDim2Code IS NULL OR pv.ItemDim2Code = ''))
|
||||||
|
)
|
||||||
|
AND (
|
||||||
|
pv.ItemDim3Code = m.ItemDim3Code
|
||||||
|
OR (m.ItemDim3Code = '' AND (pv.ItemDim3Code IS NULL OR pv.ItemDim3Code = ''))
|
||||||
|
)
|
||||||
|
WHERE pv.ItemCode IS NULL;
|
||||||
|
`, strings.Join(valueRows, ","), usernameParam, usernameParam)
|
||||||
|
|
||||||
|
res, err := tx.Exec(query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return inserted, err
|
return inserted, err
|
||||||
}
|
}
|
||||||
if rows, err := res.RowsAffected(); err == nil {
|
if rows, rowsErr := res.RowsAffected(); rowsErr == nil {
|
||||||
inserted += rows
|
inserted += rows
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return inserted, nil
|
return inserted, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +425,7 @@ BEGIN
|
|||||||
'AD', '', 0, 0,
|
'AD', '', 0, 0,
|
||||||
1, 1, 1, 0, 1, 0,
|
1, 1, 1, 0, 1, 0,
|
||||||
0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0,
|
||||||
'', '10%', '', '', '',
|
'', '%10', '', '', '',
|
||||||
'', '', '0', '0', '0',
|
'', '', '0', '0', '0',
|
||||||
'0', '', '', 0, '', '1',
|
'0', '', '', 0, '', '1',
|
||||||
0, 0, '1900-01-01', 0, 0,
|
0, 0, '1900-01-01', 0, 0,
|
||||||
@@ -369,7 +453,15 @@ SET
|
|||||||
ProductHierarchyID = COALESCE(@p5, ProductHierarchyID),
|
ProductHierarchyID = COALESCE(@p5, ProductHierarchyID),
|
||||||
UnitOfMeasureCode1 = COALESCE(NULLIF(@p6,''), UnitOfMeasureCode1),
|
UnitOfMeasureCode1 = COALESCE(NULLIF(@p6,''), UnitOfMeasureCode1),
|
||||||
ItemAccountGrCode = COALESCE(NULLIF(@p7,''), ItemAccountGrCode),
|
ItemAccountGrCode = COALESCE(NULLIF(@p7,''), ItemAccountGrCode),
|
||||||
ItemTaxGrCode = COALESCE(NULLIF(@p8,''), ItemTaxGrCode),
|
ItemTaxGrCode = CASE
|
||||||
|
WHEN NULLIF(@p8,'') IS NULL THEN ItemTaxGrCode
|
||||||
|
WHEN EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM dbo.cdItemTaxGr g WITH(NOLOCK)
|
||||||
|
WHERE LTRIM(RTRIM(g.ItemTaxGrCode)) = LTRIM(RTRIM(@p8))
|
||||||
|
) THEN @p8
|
||||||
|
ELSE ItemTaxGrCode
|
||||||
|
END,
|
||||||
ItemPaymentPlanGrCode = COALESCE(NULLIF(@p9,''), ItemPaymentPlanGrCode),
|
ItemPaymentPlanGrCode = COALESCE(NULLIF(@p9,''), ItemPaymentPlanGrCode),
|
||||||
ItemDiscountGrCode = COALESCE(NULLIF(@p10,''), ItemDiscountGrCode),
|
ItemDiscountGrCode = COALESCE(NULLIF(@p10,''), ItemDiscountGrCode),
|
||||||
ItemVendorGrCode = COALESCE(NULLIF(@p11,''), ItemVendorGrCode),
|
ItemVendorGrCode = COALESCE(NULLIF(@p11,''), ItemVendorGrCode),
|
||||||
@@ -411,23 +503,67 @@ WHERE ItemTypeCode = @p1
|
|||||||
}
|
}
|
||||||
|
|
||||||
func UpdateOrderLinesTx(tx *sql.Tx, orderHeaderID string, lines []models.OrderProductionUpdateLine, username string) (int64, error) {
|
func UpdateOrderLinesTx(tx *sql.Tx, orderHeaderID string, lines []models.OrderProductionUpdateLine, username string) (int64, error) {
|
||||||
var updated int64
|
if len(lines) == 0 {
|
||||||
for _, line := range lines {
|
return 0, nil
|
||||||
res, err := tx.Exec(`
|
|
||||||
UPDATE dbo.trOrderLine
|
|
||||||
SET
|
|
||||||
ItemCode = @p1,
|
|
||||||
ColorCode = @p2,
|
|
||||||
ItemDim2Code = @p3,
|
|
||||||
LineDescription = COALESCE(NULLIF(@p4,''), LineDescription),
|
|
||||||
LastUpdatedUserName = @p5,
|
|
||||||
LastUpdatedDate = GETDATE()
|
|
||||||
WHERE OrderHeaderID = @p6 AND OrderLineID = @p7
|
|
||||||
`, line.NewItemCode, line.NewColor, line.NewDim2, line.NewDesc, username, orderHeaderID, line.OrderLineID)
|
|
||||||
if err != nil {
|
|
||||||
return updated, err
|
|
||||||
}
|
}
|
||||||
if rows, err := res.RowsAffected(); err == nil {
|
|
||||||
|
const chunkSize = 300
|
||||||
|
var updated int64
|
||||||
|
|
||||||
|
for i := 0; i < len(lines); i += chunkSize {
|
||||||
|
end := i + chunkSize
|
||||||
|
if end > len(lines) {
|
||||||
|
end = len(lines)
|
||||||
|
}
|
||||||
|
chunk := lines[i:end]
|
||||||
|
|
||||||
|
values := make([]string, 0, len(chunk))
|
||||||
|
args := make([]any, 0, len(chunk)*5+2)
|
||||||
|
paramPos := 1
|
||||||
|
for _, line := range chunk {
|
||||||
|
values = append(values, fmt.Sprintf("(@p%d,@p%d,@p%d,@p%d,@p%d)", paramPos, paramPos+1, paramPos+2, paramPos+3, paramPos+4))
|
||||||
|
args = append(args,
|
||||||
|
strings.TrimSpace(line.OrderLineID),
|
||||||
|
line.NewItemCode,
|
||||||
|
line.NewColor,
|
||||||
|
line.NewDim2,
|
||||||
|
line.NewDesc,
|
||||||
|
)
|
||||||
|
paramPos += 5
|
||||||
|
}
|
||||||
|
|
||||||
|
orderHeaderParam := paramPos
|
||||||
|
usernameParam := paramPos + 1
|
||||||
|
args = append(args, orderHeaderID, username)
|
||||||
|
|
||||||
|
query := fmt.Sprintf(`
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
WITH src (OrderLineID, NewItemCode, NewColor, NewDim2, NewDesc) AS (
|
||||||
|
SELECT *
|
||||||
|
FROM (VALUES %s) AS v (OrderLineID, NewItemCode, NewColor, NewDim2, NewDesc)
|
||||||
|
)
|
||||||
|
UPDATE l
|
||||||
|
SET
|
||||||
|
l.ItemCode = s.NewItemCode,
|
||||||
|
l.ColorCode = s.NewColor,
|
||||||
|
l.ItemDim2Code = s.NewDim2,
|
||||||
|
l.LineDescription = COALESCE(NULLIF(s.NewDesc,''), l.LineDescription),
|
||||||
|
l.LastUpdatedUserName = @p%d,
|
||||||
|
l.LastUpdatedDate = GETDATE()
|
||||||
|
FROM dbo.trOrderLine l
|
||||||
|
JOIN src s
|
||||||
|
ON CAST(l.OrderLineID AS NVARCHAR(50)) = s.OrderLineID
|
||||||
|
WHERE l.OrderHeaderID = @p%d;
|
||||||
|
`, strings.Join(values, ","), usernameParam, orderHeaderParam)
|
||||||
|
|
||||||
|
chunkStart := time.Now()
|
||||||
|
res, execErr := tx.Exec(query, args...)
|
||||||
|
if execErr != nil {
|
||||||
|
return updated, fmt.Errorf("update lines chunk failed chunkStart=%d chunkEnd=%d duration_ms=%d: %w", i, end, time.Since(chunkStart).Milliseconds(), execErr)
|
||||||
|
}
|
||||||
|
log.Printf("[UpdateOrderLinesTx] orderHeaderID=%s chunk=%d-%d duration_ms=%d", orderHeaderID, i, end, time.Since(chunkStart).Milliseconds())
|
||||||
|
|
||||||
|
if rows, rowsErr := res.RowsAffected(); rowsErr == nil {
|
||||||
updated += rows
|
updated += rows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -439,28 +575,52 @@ func UpsertItemAttributesTx(tx *sql.Tx, attrs []models.OrderProductionItemAttrib
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SQL Server parameter limiti (2100) nedeniyle batch'li set-based upsert kullanilir.
|
||||||
|
const chunkSize = 400 // 400 * 4 param + 1 username = 1601
|
||||||
var affected int64
|
var affected int64
|
||||||
for _, a := range attrs {
|
for i := 0; i < len(attrs); i += chunkSize {
|
||||||
res, err := tx.Exec(`
|
end := i + chunkSize
|
||||||
IF EXISTS (
|
if end > len(attrs) {
|
||||||
SELECT 1
|
end = len(attrs)
|
||||||
FROM dbo.prItemAttribute
|
}
|
||||||
WHERE ItemTypeCode = @p1
|
chunk := attrs[i:end]
|
||||||
AND ItemCode = @p2
|
|
||||||
AND AttributeTypeCode = @p3
|
values := make([]string, 0, len(chunk))
|
||||||
|
args := make([]any, 0, len(chunk)*4+1)
|
||||||
|
paramPos := 1
|
||||||
|
for _, a := range chunk {
|
||||||
|
values = append(values, fmt.Sprintf("(@p%d,@p%d,@p%d,@p%d)", paramPos, paramPos+1, paramPos+2, paramPos+3))
|
||||||
|
args = append(args, a.ItemTypeCode, a.ItemCode, a.AttributeTypeCode, a.AttributeCode)
|
||||||
|
paramPos += 4
|
||||||
|
}
|
||||||
|
usernameParam := paramPos
|
||||||
|
args = append(args, username)
|
||||||
|
|
||||||
|
query := fmt.Sprintf(`
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
DECLARE @updated INT = 0;
|
||||||
|
DECLARE @inserted INT = 0;
|
||||||
|
|
||||||
|
WITH src (ItemTypeCode, ItemCode, AttributeTypeCode, AttributeCode) AS (
|
||||||
|
SELECT *
|
||||||
|
FROM (VALUES %s) AS v (ItemTypeCode, ItemCode, AttributeTypeCode, AttributeCode)
|
||||||
)
|
)
|
||||||
BEGIN
|
UPDATE tgt
|
||||||
UPDATE dbo.prItemAttribute
|
|
||||||
SET
|
SET
|
||||||
AttributeCode = @p4,
|
tgt.AttributeCode = src.AttributeCode,
|
||||||
LastUpdatedUserName = @p5,
|
tgt.LastUpdatedUserName = @p%d,
|
||||||
LastUpdatedDate = GETDATE()
|
tgt.LastUpdatedDate = GETDATE()
|
||||||
WHERE ItemTypeCode = @p1
|
FROM dbo.prItemAttribute tgt
|
||||||
AND ItemCode = @p2
|
JOIN src
|
||||||
AND AttributeTypeCode = @p3
|
ON src.ItemTypeCode = tgt.ItemTypeCode
|
||||||
END
|
AND src.ItemCode = tgt.ItemCode
|
||||||
ELSE
|
AND src.AttributeTypeCode = tgt.AttributeTypeCode;
|
||||||
BEGIN
|
SET @updated = @@ROWCOUNT;
|
||||||
|
|
||||||
|
WITH src (ItemTypeCode, ItemCode, AttributeTypeCode, AttributeCode) AS (
|
||||||
|
SELECT *
|
||||||
|
FROM (VALUES %s) AS v (ItemTypeCode, ItemCode, AttributeTypeCode, AttributeCode)
|
||||||
|
)
|
||||||
INSERT INTO dbo.prItemAttribute (
|
INSERT INTO dbo.prItemAttribute (
|
||||||
ItemTypeCode,
|
ItemTypeCode,
|
||||||
ItemCode,
|
ItemCode,
|
||||||
@@ -472,25 +632,32 @@ BEGIN
|
|||||||
LastUpdatedDate,
|
LastUpdatedDate,
|
||||||
RowGuid
|
RowGuid
|
||||||
)
|
)
|
||||||
VALUES (
|
SELECT
|
||||||
@p1,
|
src.ItemTypeCode,
|
||||||
@p2,
|
src.ItemCode,
|
||||||
@p3,
|
src.AttributeTypeCode,
|
||||||
@p4,
|
src.AttributeCode,
|
||||||
@p5,
|
@p%d,
|
||||||
GETDATE(),
|
GETDATE(),
|
||||||
@p5,
|
@p%d,
|
||||||
GETDATE(),
|
GETDATE(),
|
||||||
NEWID()
|
NEWID()
|
||||||
)
|
FROM src
|
||||||
END
|
LEFT JOIN dbo.prItemAttribute tgt
|
||||||
`, a.ItemTypeCode, a.ItemCode, a.AttributeTypeCode, a.AttributeCode, username)
|
ON src.ItemTypeCode = tgt.ItemTypeCode
|
||||||
if err != nil {
|
AND src.ItemCode = tgt.ItemCode
|
||||||
|
AND src.AttributeTypeCode = tgt.AttributeTypeCode
|
||||||
|
WHERE tgt.ItemCode IS NULL;
|
||||||
|
SET @inserted = @@ROWCOUNT;
|
||||||
|
|
||||||
|
SELECT (@updated + @inserted) AS Affected;
|
||||||
|
`, strings.Join(values, ","), usernameParam, strings.Join(values, ","), usernameParam, usernameParam)
|
||||||
|
|
||||||
|
var chunkAffected int64
|
||||||
|
if err := tx.QueryRow(query, args...).Scan(&chunkAffected); err != nil {
|
||||||
return affected, err
|
return affected, err
|
||||||
}
|
}
|
||||||
if rows, err := res.RowsAffected(); err == nil {
|
affected += chunkAffected
|
||||||
affected += rows
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return affected, nil
|
return affected, nil
|
||||||
}
|
}
|
||||||
|
|||||||
16
svc/queries/productnewcolor.go
Normal file
16
svc/queries/productnewcolor.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
const GetProductNewColors = `
|
||||||
|
SELECT
|
||||||
|
CAST(@p1 AS NVARCHAR(30)) AS ProductCode,
|
||||||
|
LTRIM(RTRIM(c.ColorCode)) AS ColorCode,
|
||||||
|
ISNULL(NULLIF(LTRIM(RTRIM(cd.ColorDescription)), ''), ISNULL(NULLIF(LTRIM(RTRIM(c.ColorHex)), ''), LTRIM(RTRIM(c.ColorCode)))) AS ColorDescription
|
||||||
|
FROM dbo.cdColor AS c WITH(NOLOCK)
|
||||||
|
LEFT JOIN dbo.cdColorDesc AS cd WITH(NOLOCK)
|
||||||
|
ON cd.ColorCode = c.ColorCode
|
||||||
|
AND cd.LangCode = 'TR'
|
||||||
|
WHERE ISNULL(c.IsBlocked, 0) = 0
|
||||||
|
AND LEN(LTRIM(RTRIM(ISNULL(c.ColorCode, '')))) = 3
|
||||||
|
AND LTRIM(RTRIM(ISNULL(c.ColorCatalogCode1, ''))) = N'ÜRÜN'
|
||||||
|
ORDER BY LTRIM(RTRIM(c.ColorCode));
|
||||||
|
`
|
||||||
16
svc/queries/productnewsecondcolor.go
Normal file
16
svc/queries/productnewsecondcolor.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
const GetProductNewSecondColors = `
|
||||||
|
SELECT
|
||||||
|
LTRIM(RTRIM(@ProductCode)) AS ProductCode,
|
||||||
|
LTRIM(RTRIM(ISNULL(@ColorCode, ''))) AS ColorCode,
|
||||||
|
LTRIM(RTRIM(d2.ItemDim2Code)) AS ItemDim2Code,
|
||||||
|
ISNULL(NULLIF(LTRIM(RTRIM(cd.ColorDescription)), ''), LTRIM(RTRIM(d2.ItemDim2Code))) AS ColorDescription
|
||||||
|
FROM dbo.cdItemDim2 AS d2 WITH(NOLOCK)
|
||||||
|
LEFT JOIN dbo.cdColorDesc AS cd WITH(NOLOCK)
|
||||||
|
ON cd.ColorCode = d2.ItemDim2Code
|
||||||
|
AND cd.LangCode = 'TR'
|
||||||
|
WHERE ISNULL(d2.IsBlocked, 0) = 0
|
||||||
|
AND LEN(LTRIM(RTRIM(ISNULL(d2.ItemDim2Code, '')))) = 3
|
||||||
|
ORDER BY LTRIM(RTRIM(d2.ItemDim2Code));
|
||||||
|
`
|
||||||
@@ -150,6 +150,9 @@ func OrderProductionInsertMissingRoute(mssql *sql.DB) http.Handler {
|
|||||||
func OrderProductionValidateRoute(mssql *sql.DB) http.Handler {
|
func OrderProductionValidateRoute(mssql *sql.DB) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
rid := fmt.Sprintf("opv-%d", time.Now().UnixNano())
|
||||||
|
w.Header().Set("X-Debug-Request-Id", rid)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
id := mux.Vars(r)["id"]
|
id := mux.Vars(r)["id"]
|
||||||
if id == "" {
|
if id == "" {
|
||||||
@@ -167,11 +170,16 @@ func OrderProductionValidateRoute(mssql *sql.DB) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stepStart := time.Now()
|
||||||
missing, err := buildMissingVariants(mssql, id, payload.Lines)
|
missing, err := buildMissingVariants(mssql, id, payload.Lines)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("[OrderProductionValidateRoute] rid=%s orderHeaderID=%s step=build_missing failed duration_ms=%d err=%v",
|
||||||
|
rid, id, time.Since(stepStart).Milliseconds(), err)
|
||||||
writeDBError(w, http.StatusInternalServerError, "validate_missing_variants", id, "", len(payload.Lines), err)
|
writeDBError(w, http.StatusInternalServerError, "validate_missing_variants", id, "", len(payload.Lines), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Printf("[OrderProductionValidateRoute] rid=%s orderHeaderID=%s lineCount=%d missingCount=%d build_missing_ms=%d total_ms=%d",
|
||||||
|
rid, id, len(payload.Lines), len(missing), time.Since(stepStart).Milliseconds(), time.Since(start).Milliseconds())
|
||||||
|
|
||||||
resp := map[string]any{
|
resp := map[string]any{
|
||||||
"missingCount": len(missing),
|
"missingCount": len(missing),
|
||||||
@@ -189,6 +197,9 @@ func OrderProductionValidateRoute(mssql *sql.DB) http.Handler {
|
|||||||
func OrderProductionApplyRoute(mssql *sql.DB) http.Handler {
|
func OrderProductionApplyRoute(mssql *sql.DB) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
rid := fmt.Sprintf("opa-%d", time.Now().UnixNano())
|
||||||
|
w.Header().Set("X-Debug-Request-Id", rid)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
id := mux.Vars(r)["id"]
|
id := mux.Vars(r)["id"]
|
||||||
if id == "" {
|
if id == "" {
|
||||||
@@ -206,13 +217,20 @@ func OrderProductionApplyRoute(mssql *sql.DB) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stepMissingStart := time.Now()
|
||||||
missing, err := buildMissingVariants(mssql, id, payload.Lines)
|
missing, err := buildMissingVariants(mssql, id, payload.Lines)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s step=build_missing failed duration_ms=%d err=%v",
|
||||||
|
rid, id, time.Since(stepMissingStart).Milliseconds(), err)
|
||||||
writeDBError(w, http.StatusInternalServerError, "apply_validate_missing_variants", id, "", len(payload.Lines), err)
|
writeDBError(w, http.StatusInternalServerError, "apply_validate_missing_variants", id, "", len(payload.Lines), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s lineCount=%d missingCount=%d build_missing_ms=%d",
|
||||||
|
rid, id, len(payload.Lines), len(missing), time.Since(stepMissingStart).Milliseconds())
|
||||||
|
|
||||||
if len(missing) > 0 && !payload.InsertMissing {
|
if len(missing) > 0 && !payload.InsertMissing {
|
||||||
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s early_exit=missing_variants total_ms=%d",
|
||||||
|
rid, id, time.Since(start).Milliseconds())
|
||||||
w.WriteHeader(http.StatusConflict)
|
w.WriteHeader(http.StatusConflict)
|
||||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||||
"missingCount": len(missing),
|
"missingCount": len(missing),
|
||||||
@@ -231,43 +249,68 @@ func OrderProductionApplyRoute(mssql *sql.DB) http.Handler {
|
|||||||
username = "system"
|
username = "system"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stepBeginStart := time.Now()
|
||||||
tx, err := mssql.Begin()
|
tx, err := mssql.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeDBError(w, http.StatusInternalServerError, "begin_tx", id, username, len(payload.Lines), err)
|
writeDBError(w, http.StatusInternalServerError, "begin_tx", id, username, len(payload.Lines), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer tx.Rollback()
|
defer tx.Rollback()
|
||||||
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s step=begin_tx duration_ms=%d", rid, id, time.Since(stepBeginStart).Milliseconds())
|
||||||
|
|
||||||
|
stepTxSettingsStart := time.Now()
|
||||||
|
if _, err := tx.Exec(`SET XACT_ABORT ON; SET LOCK_TIMEOUT 15000;`); err != nil {
|
||||||
|
writeDBError(w, http.StatusInternalServerError, "tx_settings", id, username, len(payload.Lines), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s step=tx_settings duration_ms=%d", rid, id, time.Since(stepTxSettingsStart).Milliseconds())
|
||||||
|
|
||||||
var inserted int64
|
var inserted int64
|
||||||
if payload.InsertMissing {
|
if payload.InsertMissing {
|
||||||
cdItemByCode := buildCdItemDraftMap(payload.CdItems)
|
cdItemByCode := buildCdItemDraftMap(payload.CdItems)
|
||||||
|
stepInsertMissingStart := time.Now()
|
||||||
inserted, err = queries.InsertMissingVariantsTx(tx, missing, username, cdItemByCode)
|
inserted, err = queries.InsertMissingVariantsTx(tx, missing, username, cdItemByCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeDBError(w, http.StatusInternalServerError, "insert_missing_variants", id, username, len(missing), err)
|
writeDBError(w, http.StatusInternalServerError, "insert_missing_variants", id, username, len(missing), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s step=insert_missing inserted=%d duration_ms=%d",
|
||||||
|
rid, id, inserted, time.Since(stepInsertMissingStart).Milliseconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stepValidateAttrStart := time.Now()
|
||||||
if err := validateProductAttributes(payload.ProductAttributes); err != nil {
|
if err := validateProductAttributes(payload.ProductAttributes); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
attributeAffected, err := queries.UpsertItemAttributesTx(tx, payload.ProductAttributes, username)
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s step=validate_attributes count=%d duration_ms=%d",
|
||||||
if err != nil {
|
rid, id, len(payload.ProductAttributes), time.Since(stepValidateAttrStart).Milliseconds())
|
||||||
writeDBError(w, http.StatusInternalServerError, "upsert_item_attributes", id, username, len(payload.ProductAttributes), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
stepUpdateLinesStart := time.Now()
|
||||||
updated, err := queries.UpdateOrderLinesTx(tx, id, payload.Lines, username)
|
updated, err := queries.UpdateOrderLinesTx(tx, id, payload.Lines, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeDBError(w, http.StatusInternalServerError, "update_order_lines", id, username, len(payload.Lines), err)
|
writeDBError(w, http.StatusInternalServerError, "update_order_lines", id, username, len(payload.Lines), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s step=update_lines updated=%d duration_ms=%d",
|
||||||
|
rid, id, updated, time.Since(stepUpdateLinesStart).Milliseconds())
|
||||||
|
|
||||||
|
stepUpsertAttrStart := time.Now()
|
||||||
|
attributeAffected, err := queries.UpsertItemAttributesTx(tx, payload.ProductAttributes, username)
|
||||||
|
if err != nil {
|
||||||
|
writeDBError(w, http.StatusInternalServerError, "upsert_item_attributes", id, username, len(payload.ProductAttributes), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s step=upsert_attributes affected=%d duration_ms=%d",
|
||||||
|
rid, id, attributeAffected, time.Since(stepUpsertAttrStart).Milliseconds())
|
||||||
|
|
||||||
|
stepCommitStart := time.Now()
|
||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
writeDBError(w, http.StatusInternalServerError, "commit_tx", id, username, len(payload.Lines), err)
|
writeDBError(w, http.StatusInternalServerError, "commit_tx", id, username, len(payload.Lines), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Printf("[OrderProductionApplyRoute] rid=%s orderHeaderID=%s step=commit duration_ms=%d total_ms=%d",
|
||||||
|
rid, id, time.Since(stepCommitStart).Milliseconds(), time.Since(start).Milliseconds())
|
||||||
|
|
||||||
resp := map[string]any{
|
resp := map[string]any{
|
||||||
"updated": updated,
|
"updated": updated,
|
||||||
@@ -319,7 +362,13 @@ func buildCdItemDraftMap(list []models.OrderProductionCdItemDraft) map[string]mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildMissingVariants(mssql *sql.DB, orderHeaderID string, lines []models.OrderProductionUpdateLine) ([]models.OrderProductionMissingVariant, error) {
|
func buildMissingVariants(mssql *sql.DB, orderHeaderID string, lines []models.OrderProductionUpdateLine) ([]models.OrderProductionMissingVariant, error) {
|
||||||
|
start := time.Now()
|
||||||
missing := make([]models.OrderProductionMissingVariant, 0)
|
missing := make([]models.OrderProductionMissingVariant, 0)
|
||||||
|
lineDimsMap, err := queries.GetOrderLineDimsMap(mssql, orderHeaderID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
existsCache := make(map[string]bool, len(lines))
|
||||||
|
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
lineID := strings.TrimSpace(line.OrderLineID)
|
lineID := strings.TrimSpace(line.OrderLineID)
|
||||||
@@ -331,28 +380,43 @@ func buildMissingVariants(mssql *sql.DB, orderHeaderID string, lines []models.Or
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
itemTypeCode, dim1, _, dim3, err := queries.GetOrderLineDims(mssql, orderHeaderID, lineID)
|
dims, ok := lineDimsMap[lineID]
|
||||||
if err != nil {
|
if !ok {
|
||||||
return nil, err
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := queries.VariantExists(mssql, itemTypeCode, newItem, newColor, dim1, newDim2, dim3)
|
cacheKey := fmt.Sprintf("%d|%s|%s|%s|%s|%s",
|
||||||
if err != nil {
|
dims.ItemTypeCode,
|
||||||
return nil, err
|
strings.ToUpper(strings.TrimSpace(newItem)),
|
||||||
|
strings.ToUpper(strings.TrimSpace(newColor)),
|
||||||
|
strings.ToUpper(strings.TrimSpace(dims.ItemDim1Code)),
|
||||||
|
strings.ToUpper(strings.TrimSpace(newDim2)),
|
||||||
|
strings.ToUpper(strings.TrimSpace(dims.ItemDim3Code)),
|
||||||
|
)
|
||||||
|
exists, cached := existsCache[cacheKey]
|
||||||
|
if !cached {
|
||||||
|
var checkErr error
|
||||||
|
exists, checkErr = queries.VariantExists(mssql, dims.ItemTypeCode, newItem, newColor, dims.ItemDim1Code, newDim2, dims.ItemDim3Code)
|
||||||
|
if checkErr != nil {
|
||||||
|
return nil, checkErr
|
||||||
|
}
|
||||||
|
existsCache[cacheKey] = exists
|
||||||
}
|
}
|
||||||
if !exists {
|
if !exists {
|
||||||
missing = append(missing, models.OrderProductionMissingVariant{
|
missing = append(missing, models.OrderProductionMissingVariant{
|
||||||
OrderLineID: lineID,
|
OrderLineID: lineID,
|
||||||
ItemTypeCode: itemTypeCode,
|
ItemTypeCode: dims.ItemTypeCode,
|
||||||
ItemCode: newItem,
|
ItemCode: newItem,
|
||||||
ColorCode: newColor,
|
ColorCode: newColor,
|
||||||
ItemDim1Code: dim1,
|
ItemDim1Code: dims.ItemDim1Code,
|
||||||
ItemDim2Code: newDim2,
|
ItemDim2Code: newDim2,
|
||||||
ItemDim3Code: dim3,
|
ItemDim3Code: dims.ItemDim3Code,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("[buildMissingVariants] orderHeaderID=%s lineCount=%d dimMapCount=%d missingCount=%d total_ms=%d",
|
||||||
|
orderHeaderID, len(lines), len(lineDimsMap), len(missing), time.Since(start).Milliseconds())
|
||||||
return missing, nil
|
return missing, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
45
svc/routes/productnewcolor.go
Normal file
45
svc/routes/productnewcolor.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bssapp-backend/auth"
|
||||||
|
"bssapp-backend/db"
|
||||||
|
"bssapp-backend/models"
|
||||||
|
"bssapp-backend/queries"
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProductNewColorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
claims, ok := auth.GetClaimsFromContext(r.Context())
|
||||||
|
if !ok || claims == nil {
|
||||||
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
code := r.URL.Query().Get("code")
|
||||||
|
if code == "" {
|
||||||
|
http.Error(w, "Eksik parametre: code gerekli", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := db.MssqlDB.Query(queries.GetProductNewColors, code)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Yeni urun renk listesi alinamadi: "+err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var list []models.ProductColor
|
||||||
|
for rows.Next() {
|
||||||
|
var c models.ProductColor
|
||||||
|
if err := rows.Scan(&c.ProductCode, &c.ColorCode, &c.ColorDescription); err != nil {
|
||||||
|
log.Println("Satir okunamadi:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
list = append(list, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
_ = json.NewEncoder(w).Encode(list)
|
||||||
|
}
|
||||||
51
svc/routes/productnewsecondcolor.go
Normal file
51
svc/routes/productnewsecondcolor.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bssapp-backend/auth"
|
||||||
|
"bssapp-backend/db"
|
||||||
|
"bssapp-backend/models"
|
||||||
|
"bssapp-backend/queries"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProductNewSecondColorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
claims, ok := auth.GetClaimsFromContext(r.Context())
|
||||||
|
if !ok || claims == nil {
|
||||||
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
code := r.URL.Query().Get("code")
|
||||||
|
color := r.URL.Query().Get("color")
|
||||||
|
if code == "" || color == "" {
|
||||||
|
http.Error(w, "Eksik parametre: code ve color gerekli", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := db.MssqlDB.Query(
|
||||||
|
queries.GetProductNewSecondColors,
|
||||||
|
sql.Named("ProductCode", code),
|
||||||
|
sql.Named("ColorCode", color),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Yeni urun 2. renk listesi alinamadi: "+err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var list []models.ProductSecondColor
|
||||||
|
for rows.Next() {
|
||||||
|
var c models.ProductSecondColor
|
||||||
|
if err := rows.Scan(&c.ProductCode, &c.ColorCode, &c.ItemDim2Code, &c.ColorDescription); err != nil {
|
||||||
|
log.Println("Satir okunamadi:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
list = append(list, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
_ = json.NewEncoder(w).Encode(list)
|
||||||
|
}
|
||||||
@@ -216,6 +216,7 @@
|
|||||||
filled
|
filled
|
||||||
label="Yeni 2. Renk"
|
label="Yeni 2. Renk"
|
||||||
:disable="isColorSelectionLocked(props.row)"
|
:disable="isColorSelectionLocked(props.row)"
|
||||||
|
@update:model-value="() => onNewDim2Change(props.row)"
|
||||||
/>
|
/>
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
</template>
|
||||||
@@ -331,6 +332,13 @@ const store = useOrderProductionItemStore()
|
|||||||
const BAGGI_CODE_PATTERN = /^[A-Z][0-9]{3}-[A-Z]{3}[0-9]{5}$/
|
const BAGGI_CODE_PATTERN = /^[A-Z][0-9]{3}-[A-Z]{3}[0-9]{5}$/
|
||||||
const BAGGI_CODE_ERROR = 'Girdiginiz kod BAGGI kod sistemine uyumlu degil. Format: X999-XXX99999'
|
const BAGGI_CODE_ERROR = 'Girdiginiz kod BAGGI kod sistemine uyumlu degil. Format: X999-XXX99999'
|
||||||
|
|
||||||
|
function nowMs () {
|
||||||
|
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
|
||||||
|
return performance.now()
|
||||||
|
}
|
||||||
|
return Date.now()
|
||||||
|
}
|
||||||
|
|
||||||
const orderHeaderID = computed(() => String(route.params.orderHeaderID || '').trim())
|
const orderHeaderID = computed(() => String(route.params.orderHeaderID || '').trim())
|
||||||
const header = computed(() => store.header || {})
|
const header = computed(() => store.header || {})
|
||||||
const cariLabel = computed(() => {
|
const cariLabel = computed(() => {
|
||||||
@@ -517,9 +525,14 @@ function onNewItemChange (row, val, source = 'typed') {
|
|||||||
applyNewItemVisualState(row, source)
|
applyNewItemVisualState(row, source)
|
||||||
row.NewColor = ''
|
row.NewColor = ''
|
||||||
row.NewDim2 = ''
|
row.NewDim2 = ''
|
||||||
|
row.NewDesc = mergeDescWithAutoNote(row, row.NewDesc || row.OldDesc)
|
||||||
if (row.NewItemCode) {
|
if (row.NewItemCode) {
|
||||||
|
if (row.NewItemMode === 'new') {
|
||||||
|
store.fetchNewColors(row.NewItemCode)
|
||||||
|
} else {
|
||||||
store.fetchColors(row.NewItemCode)
|
store.fetchColors(row.NewItemCode)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (row.NewItemMode === 'new' && isValidBaggiModelCode(row.NewItemCode) && row.NewItemCode !== prevCode) {
|
if (row.NewItemMode === 'new' && isValidBaggiModelCode(row.NewItemCode) && row.NewItemCode !== prevCode) {
|
||||||
openNewCodeSetupFlow(row.NewItemCode)
|
openNewCodeSetupFlow(row.NewItemCode)
|
||||||
}
|
}
|
||||||
@@ -560,14 +573,27 @@ function openNewCodeSetupFlow (itemCode) {
|
|||||||
function onNewColorChange (row) {
|
function onNewColorChange (row) {
|
||||||
row.NewColor = normalizeShortCode(row.NewColor, 3)
|
row.NewColor = normalizeShortCode(row.NewColor, 3)
|
||||||
row.NewDim2 = ''
|
row.NewDim2 = ''
|
||||||
|
row.NewDesc = mergeDescWithAutoNote(row, row.NewDesc || row.OldDesc)
|
||||||
if (row.NewItemCode && row.NewColor) {
|
if (row.NewItemCode && row.NewColor) {
|
||||||
|
if (String(row?.NewItemMode || '').trim() === 'new') {
|
||||||
|
store.fetchNewSecondColors(row.NewItemCode, row.NewColor)
|
||||||
|
} else {
|
||||||
store.fetchSecondColors(row.NewItemCode, row.NewColor)
|
store.fetchSecondColors(row.NewItemCode, row.NewColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onNewDim2Change (row) {
|
||||||
|
row.NewDim2 = normalizeShortCode(row.NewDim2, 3)
|
||||||
|
row.NewDesc = mergeDescWithAutoNote(row, row.NewDesc || row.OldDesc)
|
||||||
|
}
|
||||||
|
|
||||||
function getColorOptions (row) {
|
function getColorOptions (row) {
|
||||||
const code = row?.NewItemCode || ''
|
const code = row?.NewItemCode || ''
|
||||||
const list = store.colorOptionsByCode[code] || []
|
const isNewMode = String(row?.NewItemMode || '').trim() === 'new'
|
||||||
|
const list = isNewMode
|
||||||
|
? (store.newColorOptionsByCode[code] || [])
|
||||||
|
: (store.colorOptionsByCode[code] || [])
|
||||||
return list.map(c => ({
|
return list.map(c => ({
|
||||||
...c,
|
...c,
|
||||||
colorLabel: `${c.color_code} - ${c.color_description || ''}`.trim()
|
colorLabel: `${c.color_code} - ${c.color_description || ''}`.trim()
|
||||||
@@ -578,7 +604,10 @@ function getSecondColorOptions (row) {
|
|||||||
const code = row?.NewItemCode || ''
|
const code = row?.NewItemCode || ''
|
||||||
const color = row?.NewColor || ''
|
const color = row?.NewColor || ''
|
||||||
const key = `${code}::${color}`
|
const key = `${code}::${color}`
|
||||||
const list = store.secondColorOptionsByKey[key] || []
|
const isNewMode = String(row?.NewItemMode || '').trim() === 'new'
|
||||||
|
const list = isNewMode
|
||||||
|
? (store.newSecondColorOptionsByKey[key] || [])
|
||||||
|
: (store.secondColorOptionsByKey[key] || [])
|
||||||
return list.map(c => ({
|
return list.map(c => ({
|
||||||
...c,
|
...c,
|
||||||
item_dim2_label: `${c.item_dim2_code} - ${c.color_description || ''}`.trim()
|
item_dim2_label: `${c.item_dim2_code} - ${c.color_description || ''}`.trim()
|
||||||
@@ -609,6 +638,55 @@ function isValidBaggiModelCode (code) {
|
|||||||
return BAGGI_CODE_PATTERN.test(code)
|
return BAGGI_CODE_PATTERN.test(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatCodeColorDim2 (itemCode, color, dim2) {
|
||||||
|
const item = String(itemCode || '').trim().toUpperCase()
|
||||||
|
const c1 = normalizeShortCode(color, 3)
|
||||||
|
const c2 = normalizeShortCode(dim2, 3)
|
||||||
|
const c1Safe = c1 || '-'
|
||||||
|
const c2Safe = c2 || '-'
|
||||||
|
return `${item}/${c1Safe}/${c2Safe}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildAutoUpdateNote (row) {
|
||||||
|
const oldInfo = formatCodeColorDim2(row?.OldItemCode, row?.OldColor, row?.OldDim2)
|
||||||
|
const nextInfo = formatCodeColorDim2(row?.NewItemCode, row?.NewColor, row?.NewDim2)
|
||||||
|
return `Bu siparis satirinda kod ${oldInfo} bilgisinden ${nextInfo} bilgisine guncellenmistir.`
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSelectionCompleteByOldShape (row) {
|
||||||
|
const hasModel = String(row?.NewItemCode || '').trim().length > 0
|
||||||
|
if (!hasModel) return false
|
||||||
|
|
||||||
|
const oldHasColor = String(row?.OldColor || '').trim().length > 0
|
||||||
|
const oldHasDim2 = String(row?.OldDim2 || '').trim().length > 0
|
||||||
|
const hasNewColor = normalizeShortCode(row?.NewColor, 3).length === 3
|
||||||
|
const hasNewDim2 = normalizeShortCode(row?.NewDim2, 3).length === 3
|
||||||
|
|
||||||
|
if (oldHasDim2) return hasNewColor && hasNewDim2
|
||||||
|
if (oldHasColor) return hasNewColor
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function stripAutoUpdateNote (text) {
|
||||||
|
const desc = String(text || '').trim()
|
||||||
|
if (!desc) return ''
|
||||||
|
const marker = ' Bu siparis satirinda kod '
|
||||||
|
const idx = desc.indexOf(marker)
|
||||||
|
if (idx > -1) return desc.slice(0, idx).trim()
|
||||||
|
if (desc.startsWith('Bu siparis satirinda kod ')) return ''
|
||||||
|
return desc
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeDescWithAutoNote (row, baseDesc) {
|
||||||
|
const desc = stripAutoUpdateNote(baseDesc)
|
||||||
|
if (!isSelectionCompleteByOldShape(row)) return desc
|
||||||
|
const note = buildAutoUpdateNote(row)
|
||||||
|
if (!note) return desc
|
||||||
|
if (desc.includes(note)) return desc
|
||||||
|
if (!desc) return note
|
||||||
|
return `${desc} ${note}`
|
||||||
|
}
|
||||||
|
|
||||||
function validateRowInput (row) {
|
function validateRowInput (row) {
|
||||||
const entryMode = String(row?.NewItemEntryMode || '').trim()
|
const entryMode = String(row?.NewItemEntryMode || '').trim()
|
||||||
const newItemCode = String(row.NewItemCode || '').trim().toUpperCase()
|
const newItemCode = String(row.NewItemCode || '').trim().toUpperCase()
|
||||||
@@ -631,6 +709,7 @@ function validateRowInput (row) {
|
|||||||
row.NewItemCode = newItemCode
|
row.NewItemCode = newItemCode
|
||||||
row.NewColor = newColor
|
row.NewColor = newColor
|
||||||
row.NewDim2 = newDim2
|
row.NewDim2 = newDim2
|
||||||
|
row.NewDesc = mergeDescWithAutoNote(row, row.NewDesc || row.OldDesc)
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,7 +725,7 @@ function collectLinesFromRows (selectedRows) {
|
|||||||
NewItemCode: String(row.NewItemCode || '').trim().toUpperCase(),
|
NewItemCode: String(row.NewItemCode || '').trim().toUpperCase(),
|
||||||
NewColor: normalizeShortCode(row.NewColor, 3),
|
NewColor: normalizeShortCode(row.NewColor, 3),
|
||||||
NewDim2: normalizeShortCode(row.NewDim2, 3),
|
NewDim2: normalizeShortCode(row.NewDim2, 3),
|
||||||
NewDesc: String((row.NewDesc || row.OldDesc) || '').trim()
|
NewDesc: mergeDescWithAutoNote(row, row.NewDesc || row.OldDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id of (row.OrderLineIDs || [])) {
|
for (const id of (row.OrderLineIDs || [])) {
|
||||||
@@ -668,7 +747,7 @@ function createEmptyCdItemDraft (itemCode) {
|
|||||||
ProductHierarchyID: '',
|
ProductHierarchyID: '',
|
||||||
UnitOfMeasureCode1: 'AD',
|
UnitOfMeasureCode1: 'AD',
|
||||||
ItemAccountGrCode: '',
|
ItemAccountGrCode: '',
|
||||||
ItemTaxGrCode: '10%',
|
ItemTaxGrCode: '%10',
|
||||||
ItemPaymentPlanGrCode: '',
|
ItemPaymentPlanGrCode: '',
|
||||||
ItemDiscountGrCode: '',
|
ItemDiscountGrCode: '',
|
||||||
ItemVendorGrCode: '',
|
ItemVendorGrCode: '',
|
||||||
@@ -715,11 +794,6 @@ function isDummyLookupOption (key, codeRaw, descRaw) {
|
|||||||
if (code === '0' || code === '00' || code === '000' || code === '0000') return true
|
if (code === '0' || code === '00' || code === '000' || code === '0000') return true
|
||||||
if (desc.includes('DUMMY')) return true
|
if (desc.includes('DUMMY')) return true
|
||||||
|
|
||||||
// Is plani dokumanindaki sari/default alanlar
|
|
||||||
if (key === 'unitOfMeasureCode1List' && code === 'AD') return true
|
|
||||||
if (key === 'itemTaxGrCodes' && code === '10%') return true
|
|
||||||
if (key === 'companyCodes' && code === '1') return true
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,19 +829,19 @@ function normalizeCdItemDraftForPayload (draftRaw) {
|
|||||||
ItemTypeCode: toIntOrNil(d.ItemTypeCode) || 1,
|
ItemTypeCode: toIntOrNil(d.ItemTypeCode) || 1,
|
||||||
ItemCode: String(d.ItemCode || '').trim().toUpperCase(),
|
ItemCode: String(d.ItemCode || '').trim().toUpperCase(),
|
||||||
ItemDimTypeCode: toIntOrNil(d.ItemDimTypeCode) || 1,
|
ItemDimTypeCode: toIntOrNil(d.ItemDimTypeCode) || 1,
|
||||||
ProductTypeCode: 1,
|
ProductTypeCode: null,
|
||||||
ProductHierarchyID: toIntOrNil(d.ProductHierarchyID),
|
ProductHierarchyID: toIntOrNil(d.ProductHierarchyID),
|
||||||
UnitOfMeasureCode1: 'AD',
|
UnitOfMeasureCode1: 'AD',
|
||||||
ItemAccountGrCode: null,
|
ItemAccountGrCode: null,
|
||||||
ItemTaxGrCode: '10%',
|
ItemTaxGrCode: '%10',
|
||||||
ItemPaymentPlanGrCode: null,
|
ItemPaymentPlanGrCode: null,
|
||||||
ItemDiscountGrCode: null,
|
ItemDiscountGrCode: null,
|
||||||
ItemVendorGrCode: null,
|
ItemVendorGrCode: null,
|
||||||
PromotionGroupCode: null,
|
PromotionGroupCode: null,
|
||||||
ProductCollectionGrCode: '0',
|
ProductCollectionGrCode: null,
|
||||||
StorePriceLevelCode: '0',
|
StorePriceLevelCode: null,
|
||||||
PerceptionOfFashionCode: '0',
|
PerceptionOfFashionCode: null,
|
||||||
CommercialRoleCode: '0',
|
CommercialRoleCode: null,
|
||||||
StoreCapacityLevelCode: null,
|
StoreCapacityLevelCode: null,
|
||||||
CustomsTariffNumberCode: null,
|
CustomsTariffNumberCode: null,
|
||||||
CompanyCode: '1'
|
CompanyCode: '1'
|
||||||
@@ -956,6 +1030,11 @@ function buildProductionUpdateMailPayload (selectedRows) {
|
|||||||
async function sendUpdateMailAfterApply (selectedRows) {
|
async function sendUpdateMailAfterApply (selectedRows) {
|
||||||
const orderId = String(orderHeaderID.value || '').trim()
|
const orderId = String(orderHeaderID.value || '').trim()
|
||||||
if (!orderId) return
|
if (!orderId) return
|
||||||
|
const host = String(window?.location?.hostname || '').trim().toLowerCase()
|
||||||
|
const isLocalHost = host === 'localhost' || host === '127.0.0.1'
|
||||||
|
if (isLocalHost) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const payload = buildProductionUpdateMailPayload(selectedRows)
|
const payload = buildProductionUpdateMailPayload(selectedRows)
|
||||||
@@ -1082,12 +1161,14 @@ async function refreshAll () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function onBulkSubmit () {
|
async function onBulkSubmit () {
|
||||||
|
const flowStart = nowMs()
|
||||||
const selectedRows = rows.value.filter(r => !!selectedMap.value[r.RowKey])
|
const selectedRows = rows.value.filter(r => !!selectedMap.value[r.RowKey])
|
||||||
if (!selectedRows.length) {
|
if (!selectedRows.length) {
|
||||||
$q.notify({ type: 'warning', message: 'Lutfen en az bir satir seciniz.' })
|
$q.notify({ type: 'warning', message: 'Lutfen en az bir satir seciniz.' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const prepStart = nowMs()
|
||||||
const { errMsg, lines } = collectLinesFromRows(selectedRows)
|
const { errMsg, lines } = collectLinesFromRows(selectedRows)
|
||||||
if (errMsg) {
|
if (errMsg) {
|
||||||
$q.notify({ type: 'negative', message: errMsg })
|
$q.notify({ type: 'negative', message: errMsg })
|
||||||
@@ -1112,8 +1193,24 @@ async function onBulkSubmit () {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.info('[OrderProductionUpdate] onBulkSubmit prepared', {
|
||||||
|
orderHeaderID: orderHeaderID.value,
|
||||||
|
selectedRowCount: selectedRows.length,
|
||||||
|
lineCount: lines.length,
|
||||||
|
cdItemCount: cdItems.length,
|
||||||
|
attributeCount: productAttributes.length,
|
||||||
|
prepDurationMs: Math.round(nowMs() - prepStart)
|
||||||
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const validateStart = nowMs()
|
||||||
const validate = await store.validateUpdates(orderHeaderID.value, lines)
|
const validate = await store.validateUpdates(orderHeaderID.value, lines)
|
||||||
|
console.info('[OrderProductionUpdate] validate finished', {
|
||||||
|
orderHeaderID: orderHeaderID.value,
|
||||||
|
lineCount: lines.length,
|
||||||
|
missingCount: Number(validate?.missingCount || 0),
|
||||||
|
durationMs: Math.round(nowMs() - validateStart)
|
||||||
|
})
|
||||||
const missingCount = validate?.missingCount || 0
|
const missingCount = validate?.missingCount || 0
|
||||||
if (missingCount > 0) {
|
if (missingCount > 0) {
|
||||||
const missingList = (validate?.missing || []).map(v => (
|
const missingList = (validate?.missing || []).map(v => (
|
||||||
@@ -1126,7 +1223,13 @@ async function onBulkSubmit () {
|
|||||||
ok: { label: 'Ekle ve Guncelle', color: 'primary' },
|
ok: { label: 'Ekle ve Guncelle', color: 'primary' },
|
||||||
cancel: { label: 'Vazgec', flat: true }
|
cancel: { label: 'Vazgec', flat: true }
|
||||||
}).onOk(async () => {
|
}).onOk(async () => {
|
||||||
|
const applyStart = nowMs()
|
||||||
await store.applyUpdates(orderHeaderID.value, lines, true, cdItems, productAttributes)
|
await store.applyUpdates(orderHeaderID.value, lines, true, cdItems, productAttributes)
|
||||||
|
console.info('[OrderProductionUpdate] apply finished', {
|
||||||
|
orderHeaderID: orderHeaderID.value,
|
||||||
|
insertMissing: true,
|
||||||
|
durationMs: Math.round(nowMs() - applyStart)
|
||||||
|
})
|
||||||
await store.fetchItems(orderHeaderID.value)
|
await store.fetchItems(orderHeaderID.value)
|
||||||
selectedMap.value = {}
|
selectedMap.value = {}
|
||||||
await sendUpdateMailAfterApply(selectedRows)
|
await sendUpdateMailAfterApply(selectedRows)
|
||||||
@@ -1134,7 +1237,13 @@ async function onBulkSubmit () {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const applyStart = nowMs()
|
||||||
await store.applyUpdates(orderHeaderID.value, lines, false, cdItems, productAttributes)
|
await store.applyUpdates(orderHeaderID.value, lines, false, cdItems, productAttributes)
|
||||||
|
console.info('[OrderProductionUpdate] apply finished', {
|
||||||
|
orderHeaderID: orderHeaderID.value,
|
||||||
|
insertMissing: false,
|
||||||
|
durationMs: Math.round(nowMs() - applyStart)
|
||||||
|
})
|
||||||
await store.fetchItems(orderHeaderID.value)
|
await store.fetchItems(orderHeaderID.value)
|
||||||
selectedMap.value = {}
|
selectedMap.value = {}
|
||||||
await sendUpdateMailAfterApply(selectedRows)
|
await sendUpdateMailAfterApply(selectedRows)
|
||||||
@@ -1148,6 +1257,10 @@ async function onBulkSubmit () {
|
|||||||
})
|
})
|
||||||
$q.notify({ type: 'negative', message: store.error || 'Toplu kayit islemi basarisiz.' })
|
$q.notify({ type: 'negative', message: store.error || 'Toplu kayit islemi basarisiz.' })
|
||||||
}
|
}
|
||||||
|
console.info('[OrderProductionUpdate] onBulkSubmit total', {
|
||||||
|
orderHeaderID: orderHeaderID.value,
|
||||||
|
durationMs: Math.round(nowMs() - flowStart)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -29,13 +29,26 @@ function logApiError (action, err, payload = null) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function nowMs () {
|
||||||
|
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
|
||||||
|
return performance.now()
|
||||||
|
}
|
||||||
|
return Date.now()
|
||||||
|
}
|
||||||
|
|
||||||
export const useOrderProductionItemStore = defineStore('orderproductionitems', {
|
export const useOrderProductionItemStore = defineStore('orderproductionitems', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
items: [],
|
items: [],
|
||||||
header: null,
|
header: null,
|
||||||
products: [],
|
products: [],
|
||||||
colorOptionsByCode: {},
|
colorOptionsByCode: {},
|
||||||
|
newColorOptionsByCode: {},
|
||||||
secondColorOptionsByKey: {},
|
secondColorOptionsByKey: {},
|
||||||
|
newSecondColorOptionsByKey: {},
|
||||||
|
colorRequestsByCode: {},
|
||||||
|
newColorRequestsByCode: {},
|
||||||
|
secondColorRequestsByKey: {},
|
||||||
|
newSecondColorRequestsByKey: {},
|
||||||
productAttributesByItemType: {},
|
productAttributesByItemType: {},
|
||||||
cdItemLookups: null,
|
cdItemLookups: null,
|
||||||
cdItemDraftsByCode: {},
|
cdItemDraftsByCode: {},
|
||||||
@@ -127,16 +140,57 @@ export const useOrderProductionItemStore = defineStore('orderproductionitems', {
|
|||||||
if (this.colorOptionsByCode[code]) {
|
if (this.colorOptionsByCode[code]) {
|
||||||
return this.colorOptionsByCode[code]
|
return this.colorOptionsByCode[code]
|
||||||
}
|
}
|
||||||
|
if (this.colorRequestsByCode[code]) {
|
||||||
|
return this.colorRequestsByCode[code]
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
this.colorRequestsByCode[code] = (async () => {
|
||||||
|
const t0 = nowMs()
|
||||||
|
console.info('[OrderProductionItemStore] fetchColors start', { code })
|
||||||
const res = await api.get('/product-colors', { params: { code } })
|
const res = await api.get('/product-colors', { params: { code } })
|
||||||
const data = res?.data
|
const data = res?.data
|
||||||
const list = Array.isArray(data) ? data : []
|
const list = Array.isArray(data) ? data : []
|
||||||
this.colorOptionsByCode[code] = list
|
this.colorOptionsByCode[code] = list
|
||||||
|
console.info('[OrderProductionItemStore] fetchColors done', { code, count: list.length, durationMs: Math.round(nowMs() - t0) })
|
||||||
return list
|
return list
|
||||||
|
})()
|
||||||
|
return await this.colorRequestsByCode[code]
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.error = err?.response?.data || err?.message || 'Renk listesi alinamadi'
|
this.error = err?.response?.data || err?.message || 'Renk listesi alinamadi'
|
||||||
return []
|
return []
|
||||||
|
} finally {
|
||||||
|
delete this.colorRequestsByCode[code]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async fetchNewColors (productCode) {
|
||||||
|
const code = String(productCode || '').trim()
|
||||||
|
if (!code) return []
|
||||||
|
|
||||||
|
if (this.newColorOptionsByCode[code]) {
|
||||||
|
return this.newColorOptionsByCode[code]
|
||||||
|
}
|
||||||
|
if (this.newColorRequestsByCode[code]) {
|
||||||
|
return this.newColorRequestsByCode[code]
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.newColorRequestsByCode[code] = (async () => {
|
||||||
|
const t0 = nowMs()
|
||||||
|
console.info('[OrderProductionItemStore] fetchNewColors start', { code })
|
||||||
|
const res = await api.get('/product-newcolors', { params: { code } })
|
||||||
|
const data = res?.data
|
||||||
|
const list = Array.isArray(data) ? data : []
|
||||||
|
this.newColorOptionsByCode[code] = list
|
||||||
|
console.info('[OrderProductionItemStore] fetchNewColors done', { code, count: list.length, durationMs: Math.round(nowMs() - t0) })
|
||||||
|
return list
|
||||||
|
})()
|
||||||
|
return await this.newColorRequestsByCode[code]
|
||||||
|
} catch (err) {
|
||||||
|
this.error = err?.response?.data || err?.message || 'Yeni urun renk listesi alinamadi'
|
||||||
|
return []
|
||||||
|
} finally {
|
||||||
|
delete this.newColorRequestsByCode[code]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async fetchSecondColors (productCode, colorCode) {
|
async fetchSecondColors (productCode, colorCode) {
|
||||||
@@ -148,16 +202,59 @@ export const useOrderProductionItemStore = defineStore('orderproductionitems', {
|
|||||||
if (this.secondColorOptionsByKey[key]) {
|
if (this.secondColorOptionsByKey[key]) {
|
||||||
return this.secondColorOptionsByKey[key]
|
return this.secondColorOptionsByKey[key]
|
||||||
}
|
}
|
||||||
|
if (this.secondColorRequestsByKey[key]) {
|
||||||
|
return this.secondColorRequestsByKey[key]
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
this.secondColorRequestsByKey[key] = (async () => {
|
||||||
|
const t0 = nowMs()
|
||||||
|
console.info('[OrderProductionItemStore] fetchSecondColors start', { code, color })
|
||||||
const res = await api.get('/product-secondcolor', { params: { code, color } })
|
const res = await api.get('/product-secondcolor', { params: { code, color } })
|
||||||
const data = res?.data
|
const data = res?.data
|
||||||
const list = Array.isArray(data) ? data : []
|
const list = Array.isArray(data) ? data : []
|
||||||
this.secondColorOptionsByKey[key] = list
|
this.secondColorOptionsByKey[key] = list
|
||||||
|
console.info('[OrderProductionItemStore] fetchSecondColors done', { code, color, count: list.length, durationMs: Math.round(nowMs() - t0) })
|
||||||
return list
|
return list
|
||||||
|
})()
|
||||||
|
return await this.secondColorRequestsByKey[key]
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.error = err?.response?.data || err?.message || '2. renk listesi alinamadi'
|
this.error = err?.response?.data || err?.message || '2. renk listesi alinamadi'
|
||||||
return []
|
return []
|
||||||
|
} finally {
|
||||||
|
delete this.secondColorRequestsByKey[key]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async fetchNewSecondColors (productCode, colorCode) {
|
||||||
|
const code = String(productCode || '').trim()
|
||||||
|
const color = String(colorCode || '').trim()
|
||||||
|
if (!code || !color) return []
|
||||||
|
|
||||||
|
const key = `${code}::${color}`
|
||||||
|
if (this.newSecondColorOptionsByKey[key]) {
|
||||||
|
return this.newSecondColorOptionsByKey[key]
|
||||||
|
}
|
||||||
|
if (this.newSecondColorRequestsByKey[key]) {
|
||||||
|
return this.newSecondColorRequestsByKey[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.newSecondColorRequestsByKey[key] = (async () => {
|
||||||
|
const t0 = nowMs()
|
||||||
|
console.info('[OrderProductionItemStore] fetchNewSecondColors start', { code, color })
|
||||||
|
const res = await api.get('/product-newsecondcolor', { params: { code, color } })
|
||||||
|
const data = res?.data
|
||||||
|
const list = Array.isArray(data) ? data : []
|
||||||
|
this.newSecondColorOptionsByKey[key] = list
|
||||||
|
console.info('[OrderProductionItemStore] fetchNewSecondColors done', { code, color, count: list.length, durationMs: Math.round(nowMs() - t0) })
|
||||||
|
return list
|
||||||
|
})()
|
||||||
|
return await this.newSecondColorRequestsByKey[key]
|
||||||
|
} catch (err) {
|
||||||
|
this.error = err?.response?.data || err?.message || 'Yeni urun 2. renk listesi alinamadi'
|
||||||
|
return []
|
||||||
|
} finally {
|
||||||
|
delete this.newSecondColorRequestsByKey[key]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async fetchProductAttributes (itemTypeCode = 1) {
|
async fetchProductAttributes (itemTypeCode = 1) {
|
||||||
@@ -231,11 +328,22 @@ export const useOrderProductionItemStore = defineStore('orderproductionitems', {
|
|||||||
this.error = null
|
this.error = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const t0 = nowMs()
|
||||||
|
console.info('[OrderProductionItemStore] validateUpdates start', { orderHeaderID, lineCount: lines?.length || 0 })
|
||||||
const res = await api.post(
|
const res = await api.post(
|
||||||
`/orders/production-items/${encodeURIComponent(orderHeaderID)}/validate`,
|
`/orders/production-items/${encodeURIComponent(orderHeaderID)}/validate`,
|
||||||
{ lines }
|
{ lines }
|
||||||
)
|
)
|
||||||
return res?.data || { missingCount: 0, missing: [] }
|
const data = res?.data || { missingCount: 0, missing: [] }
|
||||||
|
const rid = res?.headers?.['x-debug-request-id'] || ''
|
||||||
|
console.info('[OrderProductionItemStore] validateUpdates done', {
|
||||||
|
orderHeaderID,
|
||||||
|
lineCount: lines?.length || 0,
|
||||||
|
missingCount: Number(data?.missingCount || 0),
|
||||||
|
requestId: rid,
|
||||||
|
durationMs: Math.round(nowMs() - t0)
|
||||||
|
})
|
||||||
|
return data
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logApiError('validateUpdates', err, { orderHeaderID, lineCount: lines?.length || 0 })
|
logApiError('validateUpdates', err, { orderHeaderID, lineCount: lines?.length || 0 })
|
||||||
this.error = extractApiErrorMessage(err, 'Kontrol basarisiz')
|
this.error = extractApiErrorMessage(err, 'Kontrol basarisiz')
|
||||||
@@ -251,11 +359,29 @@ export const useOrderProductionItemStore = defineStore('orderproductionitems', {
|
|||||||
this.error = null
|
this.error = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const t0 = nowMs()
|
||||||
|
console.info('[OrderProductionItemStore] applyUpdates start', {
|
||||||
|
orderHeaderID,
|
||||||
|
lineCount: lines?.length || 0,
|
||||||
|
insertMissing: !!insertMissing,
|
||||||
|
cdItemCount: cdItems?.length || 0,
|
||||||
|
attributeCount: productAttributes?.length || 0
|
||||||
|
})
|
||||||
const res = await api.post(
|
const res = await api.post(
|
||||||
`/orders/production-items/${encodeURIComponent(orderHeaderID)}/apply`,
|
`/orders/production-items/${encodeURIComponent(orderHeaderID)}/apply`,
|
||||||
{ lines, insertMissing, cdItems, productAttributes }
|
{ lines, insertMissing, cdItems, productAttributes }
|
||||||
)
|
)
|
||||||
return res?.data || { updated: 0, inserted: 0 }
|
const data = res?.data || { updated: 0, inserted: 0 }
|
||||||
|
const rid = res?.headers?.['x-debug-request-id'] || ''
|
||||||
|
console.info('[OrderProductionItemStore] applyUpdates done', {
|
||||||
|
orderHeaderID,
|
||||||
|
updated: Number(data?.updated || 0),
|
||||||
|
inserted: Number(data?.inserted || 0),
|
||||||
|
attributeUpserted: Number(data?.attributeUpserted || 0),
|
||||||
|
requestId: rid,
|
||||||
|
durationMs: Math.round(nowMs() - t0)
|
||||||
|
})
|
||||||
|
return data
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logApiError('applyUpdates', err, { orderHeaderID, lineCount: lines?.length || 0, insertMissing })
|
logApiError('applyUpdates', err, { orderHeaderID, lineCount: lines?.length || 0, insertMissing })
|
||||||
this.error = extractApiErrorMessage(err, 'Guncelleme basarisiz')
|
this.error = extractApiErrorMessage(err, 'Guncelleme basarisiz')
|
||||||
|
|||||||
Reference in New Issue
Block a user