Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -23,6 +23,7 @@ UI_DIR=/opt/bssapp/ui/dist
|
||||
# ===============================
|
||||
POSTGRES_CONN=host=46.224.33.150 port=5432 user=postgres password=tayitkan dbname=baggib2b sslmode=disable
|
||||
MSSQL_CONN=sqlserver://sa:Gil_0150@10.0.0.9:1433?database=BAGGI_V3&encrypt=disable
|
||||
URETIM_MSSQL_CONN=sqlserver://sa:Gil_0150@10.0.0.9:1433?database=URETIM&encrypt=disable
|
||||
|
||||
# ===============================
|
||||
# PDF
|
||||
|
||||
0
svc/backend-dev.err.log
Normal file
0
svc/backend-dev.err.log
Normal file
365
svc/backend-dev.out.log
Normal file
365
svc/backend-dev.out.log
Normal file
@@ -0,0 +1,365 @@
|
||||
time=2026-04-29T21:47:12.721+03:00 level=INFO msg="backend start" app=bssapp-backend scope=main
|
||||
time=2026-04-29T21:47:12.767+03:00 level=INFO msg="🔥🔥🔥 BSSAPP BACKEND STARTED — LOGIN ROUTE SHOULD EXIST 🔥🔥🔥" app=bssapp-backend
|
||||
time=2026-04-29T21:47:12.770+03:00 level=INFO msg="🔐 JWT_SECRET yüklendi" app=bssapp-backend
|
||||
MSSQL baglantisi basarili (connection timeout=120s, dial timeout=120s)
|
||||
URETIM MSSQL baglantisi basarili (connection timeout=120s, dial timeout=120s)
|
||||
time=2026-04-29T21:47:13.271+03:00 level=INFO msg="PostgreSQL bağlantısı başarılı" app=bssapp-backend
|
||||
time=2026-04-29T21:47:13.581+03:00 level=INFO msg="✅ Admin dept permissions seeded" app=bssapp-backend
|
||||
time=2026-04-29T21:47:13.581+03:00 level=INFO msg="🟢 auditlog Init called, buffer: 1000" app=bssapp-backend
|
||||
time=2026-04-29T21:47:13.587+03:00 level=INFO msg="🟢 auditlog worker STARTED" app=bssapp-backend
|
||||
time=2026-04-29T21:47:13.588+03:00 level=INFO msg="🕵️ AuditLog sistemi başlatıldı (buffer=1000)" app=bssapp-backend
|
||||
time=2026-04-29T21:47:13.678+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE EXTENSION IF NOT EXISTS pg_trgm\"" app=bssapp-backend
|
||||
time=2026-04-29T21:47:13.765+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_t_key_lang ON mk_translator (t_key, lang_code)\"" app=bssapp-backend
|
||||
time=2026-04-29T21:47:13.854+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_status_lang_updated ON mk_translator (status, lang_code...\"" app=bssapp-backend
|
||||
time=2026-04-29T21:47:13.944+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_manual_status ON mk_translator (is_manual, status)\"" app=bssapp-backend
|
||||
time=2026-04-29T21:47:14.032+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_source_type_expr ON mk_translator ((COALESCE(NULLIF(pro...\"" app=bssapp-backend
|
||||
time=2026-04-29T21:47:14.133+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_source_text_trgm ON mk_translator USING gin (source_tex...\"" app=bssapp-backend
|
||||
time=2026-04-29T21:47:14.222+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_translated_text_trgm ON mk_translator USING gin (transl...\"" app=bssapp-backend
|
||||
time=2026-04-29T21:47:14.223+03:00 level=INFO msg="✉️ Graph Mailer hazır (App-only token) | from=baggiss@baggi.com.tr" app=bssapp-backend
|
||||
time=2026-04-29T21:47:14.223+03:00 level=INFO msg="✉️ Graph Mailer hazır" app=bssapp-backend
|
||||
📋 [DEBUG] İlk 10 kullanıcı:
|
||||
- 1 : ctengiz
|
||||
- 2 : ali.kale
|
||||
- 5 : mehmet.keçeci
|
||||
- 6 : mert.keçeci
|
||||
- 7 : samet.keçeci
|
||||
- 9 : orhan.caliskan
|
||||
- 10 : nilgun.sara
|
||||
- 14 : rustem.kurbanov
|
||||
- 15 : caner.akyol
|
||||
- 16 : kemal.matyakupov
|
||||
time=2026-04-29T21:47:15.216+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/auth/login [auth:login]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:16.101+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/auth/refresh [auth:refresh]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:16.996+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/password/forgot [auth:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:17.904+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/password/reset/validate/{token} [auth:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:18.782+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/password/reset [auth:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:19.673+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/password/change [auth:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:20.563+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/activity-logs [system:read]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:21.444+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/test-mail [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:22.332+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/system/market-mail-mappings/lookups [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:23.224+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/system/market-mail-mappings [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:24.100+03:00 level=INFO msg="✅ Route+Perm registered → PUT /api/system/market-mail-mappings/{marketId} [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:24.978+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/language/translations [language:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:25.870+03:00 level=INFO msg="✅ Route+Perm registered → PUT /api/language/translations/{id} [language:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:26.752+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/upsert-missing [language:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:27.638+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/sync-sources [language:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:28.520+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/translate-selected [language:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:29.449+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/bulk-approve [language:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:30.328+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/bulk-update [language:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:31.208+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/roles/{id}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:32.090+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/roles/{id}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:32.979+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/users/{id}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:33.884+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/{id}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:34.814+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/permissions/routes [system:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:35.718+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/permissions/effective [system:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:36.597+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/permissions/matrix [system:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:37.490+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/role-dept-permissions/list [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:38.395+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/roles/{roleId}/departments/{deptCode}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:39.290+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/roles/{roleId}/departments/{deptCode}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:40.177+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/users/list [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:41.060+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users [user:insert]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:41.940+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/users/{id} [user:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:42.841+03:00 level=INFO msg="✅ Route+Perm registered → PUT /api/users/{id} [user:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:43.736+03:00 level=INFO msg="✅ Route+Perm registered → DELETE /api/users/{id} [user:delete]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:44.618+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/{id}/admin-reset-password [user:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:45.499+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/{id}/send-password-mail [user:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:46.389+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/create [user:insert]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:47.287+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/nebim-users [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:48.184+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/piyasalar [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:49.074+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/users-perm [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:49.968+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/roles-perm [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:50.851+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/departments-perm [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:52.990+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/modules [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:53.893+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/roles [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:54.789+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/departments [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:55.694+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/accounts [customer:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:56.587+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/customer-list [customer:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:57.474+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/today-currency [finance:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:58.358+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/export-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-04-29T21:47:59.303+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/exportstamentheaderreport-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:00.197+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/customer-balances [finance:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:01.080+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/customer-balances/export-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:01.968+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/customer-balances/export-excel [finance:export]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:02.850+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/account-aging-statement [finance:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:03.759+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/account-aging-statement/export-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:04.664+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/account-aging-statement/export-screen-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:05.600+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/account-aging-statement/export-excel [finance:export]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:06.513+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/aged-customer-balance-list [finance:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:07.460+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/statements [finance:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:08.375+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/statements/{id}/details [finance:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:09.258+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/create [order:insert]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:10.154+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/update [order:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:11.034+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/{id}/bulk-due-date [order:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:11.924+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/order/get/{id} [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:12.811+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/list [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:13.695+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/production-list [order:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:14.624+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/production-items/cditem-lookups [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:15.544+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/production-items/{id} [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:17.930+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/orders/production-items/{id}/insert-missing [order:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:18.825+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/orders/production-items/{id}/validate [order:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:20.012+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/orders/production-items/{id}/apply [order:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:20.955+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/close-ready [order:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:21.854+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/orders/bulk-close [order:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:23.037+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/export [order:export]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:23.994+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/order/check/{id} [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:24.943+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/validate [order:insert]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:26.184+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/order/pdf/{id} [order:export]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:27.066+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/send-market-mail [order:read]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:27.952+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/order-inventory [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:28.844+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orderpricelistb2b [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:29.747+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/min-price [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:30.627+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/products [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:31.512+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-detail [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:32.407+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-cditem [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:33.297+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-colors [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:34.190+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-newcolors [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:35.380+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-colorsize [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:36.265+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-secondcolor [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:37.162+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-newsecondcolor [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:38.051+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-attributes [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:38.944+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-item-attributes [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:39.858+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-stock-query [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:40.753+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-stock-attribute-options [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:41.640+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-stock-query-by-attributes [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:42.531+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-images [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:43.410+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-images/{id}/content [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:44.296+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-size-match/rules [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:45.193+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/products [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:46.071+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/no-cost-products [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:46.982+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-products [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:48.168+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-history [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:49.052+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-groups [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:49.942+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-header [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:50.846+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/production-types [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:51.740+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/detail-editor-options [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:52.639+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:53.538+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-line-history [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:54.426+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-similar-history [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:55.308+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/pricing/production-product-costing/has-cost-detail-bulk-prices [order:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:56.205+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/roles [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:57.093+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/departments [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:48:57.980+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/piyasalar [user:view]" app=bssapp-backend
|
||||
time=2026-04-29T21:49:00.122+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/roles/{id}/departments [user:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:49:01.048+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/roles/{id}/piyasalar [user:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:49:01.970+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/{id}/roles [user:update]" app=bssapp-backend
|
||||
time=2026-04-29T21:49:03.170+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/admin/users/{id}/piyasa-sync [admin:user.update]" app=bssapp-backend
|
||||
time=2026-04-29T21:49:03.172+03:00 level=INFO msg="🌍 CORS Allowed Origin: http://ss.baggi.com.tr/app" app=bssapp-backend
|
||||
time=2026-04-29T21:49:03.172+03:00 level=INFO msg="🚀 Server running at: 0.0.0.0:8080" app=bssapp-backend
|
||||
time=2026-04-29T21:49:03.172+03:00 level=INFO msg="🕓 Translation sync next run at 2026-04-30T04:00:00+03:00 (in 6h10m57s)" app=bssapp-backend
|
||||
time=2026-04-29T21:57:23.596+03:00 level=INFO msg="➡️ POST /api/auth/refresh | auth=false" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.523+03:00 level=INFO msg="⬅️ POST /api/auth/refresh | status=200 | 927.7384ms" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.524+03:00 level=INFO msg="⚠️ LOGGER: claims is NIL" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.524+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=<nil> actor_user=<nil> role=public nav /api/auth/refresh target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.544+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.545+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-header | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.546+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.546+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-groups | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.546+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-header" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.546+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-groups" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.850+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.850+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/production-types | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.850+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/production-types" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.964+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:57:24.964+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.021+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.295+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.297+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:57:25.297+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-rows recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:57:25.300+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.301+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:57:25.302+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-header recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:57:25.350+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.351+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types
|
||||
time=2026-04-29T21:57:25.389+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 n_urt_recete_id=20815 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:57:25.391+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-header | status=200 | 845.3861ms" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.391+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.391+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-header target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.406+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types row_count=4
|
||||
time=2026-04-29T21:57:25.406+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 group_count=3 row_count=26 scan_errors=0
|
||||
time=2026-04-29T21:57:25.407+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/production-types | status=200 | 556.5518ms" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.409+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.409+03:00 level=INFO msg="[ProductionNoCostDetailGroups] done recete_kodu=S001-DMY26211 groups=3" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.411+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-groups | status=200 | 864.8427ms" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.412+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.567+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/production-types target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:57:25.733+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-groups target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:57:26.592+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:57:26.593+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:57:26.593+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-exchange-rates" app=bssapp-backend
|
||||
time=2026-04-29T21:57:26.758+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:57:27.095+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:57:27.097+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.exchange-rates maliyet_tarihi=2026-04-29
|
||||
time=2026-04-29T21:57:27.097+03:00 level=INFO msg="[ProductionHasCostDetailExchangeRates] start maliyet_tarihi=2026-04-29" app=bssapp-backend
|
||||
time=2026-04-29T21:57:27.191+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.exchange-rates rate_date=2026-04-29 usd_rate=45.0515 eur_rate=52.6761 gbp_rate=60.8954
|
||||
time=2026-04-29T21:57:27.191+03:00 level=INFO msg="[ProductionHasCostDetailExchangeRates] done maliyet_tarihi=2026-04-29 rate_date=2026-04-29 usd=45.0515 eur=52.6761" app=bssapp-backend
|
||||
time=2026-04-29T21:57:27.191+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates | status=200 | 598.5886ms" app=bssapp-backend
|
||||
time=2026-04-29T21:57:27.191+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:57:27.191+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-exchange-rates target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:04.959+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:04.961+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-header | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:04.961+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:04.961+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-groups | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:04.962+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-header" app=bssapp-backend
|
||||
time=2026-04-29T21:58:04.962+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:04.963+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-groups" app=bssapp-backend
|
||||
time=2026-04-29T21:58:04.963+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.269+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.270+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/production-types | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.271+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/production-types" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.271+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.353+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.355+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:05.355+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-rows recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:05.394+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 group_count=3 row_count=26 scan_errors=0
|
||||
time=2026-04-29T21:58:05.396+03:00 level=INFO msg="[ProductionNoCostDetailGroups] done recete_kodu=S001-DMY26211 groups=3" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.397+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-groups | status=200 | 435.4404ms" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.397+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.397+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-groups target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.432+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.433+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-groups | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.433+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-groups" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.433+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.652+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.653+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types
|
||||
time=2026-04-29T21:58:05.680+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types row_count=4
|
||||
time=2026-04-29T21:58:05.681+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/production-types | status=200 | 410.1372ms" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.681+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.681+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/production-types target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.690+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.690+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/production-types | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.691+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/production-types" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.691+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.943+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:05.944+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:05.944+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-header recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:06.066+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.067+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types
|
||||
time=2026-04-29T21:58:06.494+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 n_urt_recete_id=20815 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:06.494+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-header | status=200 | 1.5333479s" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.495+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.495+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-header target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.545+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types row_count=4
|
||||
time=2026-04-29T21:58:06.545+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/production-types | status=200 | 855.4172ms" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.546+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.667+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/production-types target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.751+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.752+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:06.753+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-rows recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:06.817+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.818+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-header | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.818+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-header" app=bssapp-backend
|
||||
time=2026-04-29T21:58:06.819+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:07.050+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 group_count=3 row_count=26 scan_errors=0
|
||||
time=2026-04-29T21:58:07.050+03:00 level=INFO msg="[ProductionNoCostDetailGroups] done recete_kodu=S001-DMY26211 groups=3" app=bssapp-backend
|
||||
time=2026-04-29T21:58:07.050+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-groups | status=200 | 1.617361s" app=bssapp-backend
|
||||
time=2026-04-29T21:58:07.051+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:07.051+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-groups target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:07.183+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:07.183+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:07.184+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-header recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:07.213+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 n_urt_recete_id=20815 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:07.214+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-header | status=200 | 396.483ms" app=bssapp-backend
|
||||
time=2026-04-29T21:58:07.214+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:07.242+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-header target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.489+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.491+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.491+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-exchange-rates" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.492+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.823+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.823+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.exchange-rates maliyet_tarihi=2026-04-29
|
||||
time=2026-04-29T21:58:08.823+03:00 level=INFO msg="[ProductionHasCostDetailExchangeRates] start maliyet_tarihi=2026-04-29" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.851+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.exchange-rates rate_date=2026-04-29 usd_rate=45.0515 eur_rate=52.6761 gbp_rate=60.8954
|
||||
time=2026-04-29T21:58:08.853+03:00 level=INFO msg="[ProductionHasCostDetailExchangeRates] done maliyet_tarihi=2026-04-29 rate_date=2026-04-29 usd=45.0515 eur=52.6761" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.853+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates | status=200 | 361.9866ms" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.853+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:08.853+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-exchange-rates target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:55.938+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:55.939+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-header | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:55.939+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-header" app=bssapp-backend
|
||||
time=2026-04-29T21:58:55.939+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.076+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.078+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-groups | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.079+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-groups" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.080+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.251+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.252+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/production-types | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.252+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/production-types" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.252+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.269+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.270+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:56.270+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-header recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:56.297+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 n_urt_recete_id=20815 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:56.299+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-header | status=200 | 359.9756ms" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.299+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.299+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-header target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.418+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.419+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:56.419+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-rows recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:58:56.462+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 group_count=3 row_count=26 scan_errors=0
|
||||
time=2026-04-29T21:58:56.463+03:00 level=INFO msg="[ProductionNoCostDetailGroups] done recete_kodu=S001-DMY26211 groups=3" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.463+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-groups | status=200 | 385.19ms" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.463+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.467+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-groups target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.589+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.590+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types
|
||||
time=2026-04-29T21:58:56.598+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types row_count=4
|
||||
time=2026-04-29T21:58:56.598+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/production-types | status=200 | 346.1189ms" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.598+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:56.635+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/production-types target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.550+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.551+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.552+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-exchange-rates" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.553+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.891+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.891+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.exchange-rates maliyet_tarihi=2026-04-29
|
||||
time=2026-04-29T21:58:57.891+03:00 level=INFO msg="[ProductionHasCostDetailExchangeRates] start maliyet_tarihi=2026-04-29" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.923+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.exchange-rates rate_date=2026-04-29 usd_rate=45.0515 eur_rate=52.6761 gbp_rate=60.8954
|
||||
time=2026-04-29T21:58:57.924+03:00 level=INFO msg="[ProductionHasCostDetailExchangeRates] done maliyet_tarihi=2026-04-29 rate_date=2026-04-29 usd=45.0515 eur=52.6761" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.925+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates | status=200 | 373.817ms" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.925+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:58:57.925+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-exchange-rates target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.728+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.729+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-header | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.729+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.730+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-groups | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.730+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-groups" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.730+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.731+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-header" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.731+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.820+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.820+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/production-types | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.821+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/production-types" app=bssapp-backend
|
||||
time=2026-04-29T21:59:35.821+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.078+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.079+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:59:36.079+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-header recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:59:36.079+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.079+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:59:36.079+03:00 level=INFO msg="query dispatch" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 query=production-product-costing.no-cost-detail-rows recete_kodu=S001-DMY26211 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:59:36.108+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-header detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 n_urt_recete_id=20815 urun_kodu=S001-DMY26211
|
||||
time=2026-04-29T21:59:36.108+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-header | status=200 | 379.6458ms" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.108+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.108+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-header target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.161+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.161+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types
|
||||
time=2026-04-29T21:59:36.168+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.production-types row_count=4
|
||||
time=2026-04-29T21:59:36.168+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/production-types | status=200 | 347.978ms" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.169+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.172+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.detail-groups detail_source=no-cost urun_kodu=S001-DMY26211 recete_kodu=S001-DMY26211 group_count=3 row_count=26 scan_errors=0
|
||||
time=2026-04-29T21:59:36.173+03:00 level=INFO msg="[ProductionNoCostDetailGroups] done recete_kodu=S001-DMY26211 groups=3" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.173+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-groups | status=200 | 443.1026ms" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.174+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.276+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/production-types target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:59:36.441+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-groups target=<nil>" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.181+03:00 level=INFO msg="🔐 GLOBAL AUTH user=5 role=admin" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.182+03:00 level=INFO msg="➡️ GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates | auth=true" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.183+03:00 level=INFO msg="AUTH_MIDDLEWARE PASS user=5 role=admin method=GET path=/api/pricing/production-product-costing/has-cost-detail-exchange-rates" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.184+03:00 level=INFO msg="🔐 PERM CHECK user=5 role=3 dept=[UST_YONETIM] order:view" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.526+03:00 level=INFO msg=" ↳ ROLE+DEPT OVERRIDE = true" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.527+03:00 level=INFO msg="request start" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.exchange-rates maliyet_tarihi=2026-04-29
|
||||
time=2026-04-29T21:59:37.527+03:00 level=INFO msg="[ProductionHasCostDetailExchangeRates] start maliyet_tarihi=2026-04-29" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.566+03:00 level=INFO msg="request done" app=bssapp-backend trace_id=pcd-no-cost-4d8aee0f-e28c-4f5a-b758-1aea1d646a62 handler=production-product-costing.exchange-rates rate_date=2026-04-29 usd_rate=45.0515 eur_rate=52.6761 gbp_rate=60.8954
|
||||
time=2026-04-29T21:59:37.566+03:00 level=INFO msg="[ProductionHasCostDetailExchangeRates] done maliyet_tarihi=2026-04-29 rate_date=2026-04-29 usd=45.0515 eur=52.6761" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.567+03:00 level=INFO msg="⬅️ GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates | status=200 | 384.597ms" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.567+03:00 level=INFO msg="✅ LOGGER CLAIMS user=mehmet.keçeci role=admin id=5" app=bssapp-backend
|
||||
time=2026-04-29T21:59:37.568+03:00 level=INFO msg="🧾 auditlog INSERT | actor_dfusr=5 actor_user=mehmet.keçeci role=admin nav /api/pricing/production-product-costing/has-cost-detail-exchange-rates target=<nil>" app=bssapp-backend
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
)
|
||||
|
||||
var MssqlDB *sql.DB
|
||||
var UretimDB *sql.DB
|
||||
|
||||
func envInt(name string, fallback int) int {
|
||||
raw := strings.TrimSpace(os.Getenv(name))
|
||||
@@ -123,3 +124,37 @@ func ConnectMSSQL() error {
|
||||
func GetDB() *sql.DB {
|
||||
return MssqlDB
|
||||
}
|
||||
|
||||
// ConnectMSSQLUretim initializes the URETIM MSSQL connection from environment.
|
||||
func ConnectMSSQLUretim() error {
|
||||
connString := strings.TrimSpace(os.Getenv("URETIM_MSSQL_CONN"))
|
||||
if connString == "" {
|
||||
return fmt.Errorf("URETIM_MSSQL_CONN tanimli degil")
|
||||
}
|
||||
|
||||
connectionTimeoutSec := envInt("URETIM_MSSQL_CONNECTION_TIMEOUT_SEC", envInt("MSSQL_CONNECTION_TIMEOUT_SEC", 120))
|
||||
dialTimeoutSec := envInt("URETIM_MSSQL_DIAL_TIMEOUT_SEC", connectionTimeoutSec)
|
||||
connString = ensureMSSQLTimeouts(connString, connectionTimeoutSec, dialTimeoutSec)
|
||||
|
||||
var err error
|
||||
UretimDB, err = sql.Open("sqlserver", connString)
|
||||
if err != nil {
|
||||
return fmt.Errorf("URETIM MSSQL baglanti hatasi: %w", err)
|
||||
}
|
||||
|
||||
UretimDB.SetMaxOpenConns(envInt("URETIM_MSSQL_MAX_OPEN_CONNS", envInt("MSSQL_MAX_OPEN_CONNS", 40)))
|
||||
UretimDB.SetMaxIdleConns(envInt("URETIM_MSSQL_MAX_IDLE_CONNS", envInt("MSSQL_MAX_IDLE_CONNS", 40)))
|
||||
UretimDB.SetConnMaxLifetime(time.Duration(envInt("URETIM_MSSQL_CONN_MAX_LIFETIME_MIN", envInt("MSSQL_CONN_MAX_LIFETIME_MIN", 30))) * time.Minute)
|
||||
UretimDB.SetConnMaxIdleTime(time.Duration(envInt("URETIM_MSSQL_CONN_MAX_IDLE_MIN", envInt("MSSQL_CONN_MAX_IDLE_MIN", 10))) * time.Minute)
|
||||
|
||||
if err = UretimDB.Ping(); err != nil {
|
||||
return fmt.Errorf("URETIM MSSQL erisilemiyor: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("URETIM MSSQL baglantisi basarili (connection timeout=%ds, dial timeout=%ds)\n", connectionTimeoutSec, dialTimeoutSec)
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetUretimDB() *sql.DB {
|
||||
return UretimDB
|
||||
}
|
||||
|
||||
106
svc/main.go
106
svc/main.go
@@ -8,8 +8,10 @@ import (
|
||||
"bssapp-backend/permissions"
|
||||
"bssapp-backend/repository"
|
||||
"bssapp-backend/routes"
|
||||
"bssapp-backend/utils"
|
||||
"database/sql"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -738,6 +740,101 @@ func InitRoutes(pgDB *sql.DB, mssql *sql.DB, ml *mailer.GraphMailer) *mux.Router
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductPricingListHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/no-cost-products", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionNoCostProductsHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/has-cost-products", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionHasCostProductsHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/has-cost-history", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionHasCostHistoryHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/has-cost-detail-groups", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionHasCostDetailGroupsHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/has-cost-detail-header", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionHasCostDetailHeaderHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/production-types", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionTypesHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/detail-editor-options", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionHasCostDetailEditorOptionsHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/has-cost-detail-exchange-rates", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionHasCostDetailExchangeRatesHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/has-cost-detail-line-history", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionHasCostDetailLineHistoryHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/has-cost-detail-similar-history", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionHasCostDetailSimilarHistoryHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/has-cost-detail-bulk-prices", "POST",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.PostProductionHasCostDetailBulkPricesHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/options/urun-ana-grup", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionProductCostingUrunAnaGrupOptionsHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/options/urun-alt-grup", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionProductCostingUrunAltGrupOptionsHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/options/urun-ana-alt-combos", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionProductCostingUrunAnaAltCombosHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/options/mtbolum", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionProductCostingMTBolumOptionsHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/maliyet-parca-eslestirme", "GET",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.GetProductionProductCostingParcaMappingsHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/maliyet-parca-eslestirme", "DELETE",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.DeleteProductionProductCostingParcaMappingHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/maliyet-parca-eslestirme/upsert", "POST",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.PostProductionProductCostingParcaMappingUpsertHandler)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
"/api/pricing/production-product-costing/maliyet-parca-eslestirme/set-active", "POST",
|
||||
"order", "view",
|
||||
wrapV3(http.HandlerFunc(routes.PostProductionProductCostingParcaMappingSetActiveHandler)),
|
||||
)
|
||||
|
||||
// ============================================================
|
||||
// ROLE MANAGEMENT
|
||||
@@ -797,6 +894,8 @@ func InitRoutes(pgDB *sql.DB, mssql *sql.DB, ml *mailer.GraphMailer) *mux.Router
|
||||
}
|
||||
|
||||
func main() {
|
||||
utils.InitSlog()
|
||||
slog.Info("backend start", "scope", "main")
|
||||
log.Println("🔥🔥🔥 BSSAPP BACKEND STARTED — LOGIN ROUTE SHOULD EXIST 🔥🔥🔥")
|
||||
|
||||
// -------------------------------------------------------
|
||||
@@ -825,6 +924,13 @@ func main() {
|
||||
log.Fatal(err3)
|
||||
}
|
||||
}
|
||||
if err := db.ConnectMSSQLUretim(); err != nil {
|
||||
if strings.Contains(err.Error(), "URETIM_MSSQL_CONN tanimli degil") {
|
||||
log.Println("⚠️ URETIM DB baglantisi atlandi: URETIM_MSSQL_CONN tanimli degil")
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
pgDB, err := db.ConnectPostgres()
|
||||
if err != nil {
|
||||
|
||||
282
svc/models/production_product_costing.go
Normal file
282
svc/models/production_product_costing.go
Normal file
@@ -0,0 +1,282 @@
|
||||
package models
|
||||
|
||||
type ProductionNoCostProductRow struct {
|
||||
UretimSekli string `json:"UretimSekli"`
|
||||
UrtSiparisNo string `json:"nUrtSiparisNo"`
|
||||
IslemTarihi string `json:"dteIslemTarihi"`
|
||||
FirmaKodu string `json:"FirmaKodu"`
|
||||
FirmaAdi string `json:"FirmaAdi"`
|
||||
SonIsEmriVeren string `json:"SonIsEmriVeren"`
|
||||
ModelAdi string `json:"sAdi"`
|
||||
Kodu string `json:"sKodu"`
|
||||
SKullaniciAdi string `json:"sKullaniciAdi"`
|
||||
SKullaniciGunc string `json:"sKullaniciAdiGunc"`
|
||||
MMiktarG float64 `json:"lMMiktar_G"`
|
||||
MModelKodu string `json:"sMModelKodu"`
|
||||
}
|
||||
|
||||
type ProductionHasCostProductRow struct {
|
||||
UretimSekli string `json:"UretimSekli"`
|
||||
NOnMLNo string `json:"nOnMLNo"`
|
||||
UrunKodu string `json:"UrunKodu"`
|
||||
UrunAdi string `json:"UrunAdi"`
|
||||
Tarihi string `json:"Tarihi"`
|
||||
DteKayitTarihi string `json:"dteKayitTarihi"`
|
||||
SKullaniciAdi string `json:"sKullaniciAdi"`
|
||||
LTutarTL float64 `json:"lTutarTL"`
|
||||
LTutarUSD float64 `json:"lTutarUSD"`
|
||||
LTutarEURO float64 `json:"lTutarEURO"`
|
||||
DteGuncellemeTarihi string `json:"dteGuncellemeTarihi"`
|
||||
SGuncellemeKullaniciAdi string `json:"sGuncellemeKullaniciAdi"`
|
||||
NUrtReceteID string `json:"nUrtReceteID"`
|
||||
SAciklama string `json:"sAciklama"`
|
||||
SonSiparisTarihi string `json:"SonSiparisTarihi"`
|
||||
MaliyetDurumu string `json:"MaliyetDurumu"`
|
||||
}
|
||||
|
||||
type ProductionHasCostHistoryRow struct {
|
||||
NOnMLNo string `json:"nOnMLNo"`
|
||||
UrunKodu string `json:"UrunKodu"`
|
||||
UrunAdi string `json:"UrunAdi"`
|
||||
Tarihi string `json:"Tarihi"`
|
||||
SKullaniciAdi string `json:"sKullaniciAdi"`
|
||||
LTutarUSD float64 `json:"lTutarUSD"`
|
||||
LTutarTL float64 `json:"lTutarTL"`
|
||||
LTutarEURO float64 `json:"lTutarEURO"`
|
||||
LTutarGBP float64 `json:"lTutarGBP"`
|
||||
SDovizCinsi string `json:"sDovizCinsi"`
|
||||
LTutarDoviz float64 `json:"lTutarDoviz"`
|
||||
DteGuncellemeTarihi string `json:"dteGuncellemeTarihi"`
|
||||
SGuncellemeKullaniciAdi string `json:"sGuncellemeKullaniciAdi"`
|
||||
NUrtReceteID string `json:"nUrtReceteID"`
|
||||
SAciklama string `json:"sAciklama"`
|
||||
}
|
||||
|
||||
type ProductionType struct {
|
||||
ID string `json:"id"`
|
||||
Aciklama string `json:"aciklama"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailGroupItem struct {
|
||||
NOnMLNo string `json:"nOnMLNo"`
|
||||
NOnMLDetNo string `json:"nOnMLDetNo"`
|
||||
NHammaddeTuruNo string `json:"nHammaddeTuruNo"`
|
||||
SKodu string `json:"sKodu"`
|
||||
SAciklama string `json:"sAciklama"`
|
||||
SRenk string `json:"sRenk"`
|
||||
SBeden string `json:"sBeden"`
|
||||
SAciklama2 string `json:"sAciklama2"`
|
||||
LMiktar float64 `json:"lMiktar"`
|
||||
LFiyat float64 `json:"lFiyat"`
|
||||
LTutar float64 `json:"lTutar"`
|
||||
SFiyatTipi string `json:"sFiyatTipi"`
|
||||
SDovizCinsi string `json:"sDovizCinsi"`
|
||||
LDovizKuru float64 `json:"lDovizKuru"`
|
||||
LDovizFiyati float64 `json:"lDovizFiyati"`
|
||||
FiyatGirilen *float64 `json:"fiyat_girilen"`
|
||||
FiyatDoviz string `json:"fiyat_doviz"`
|
||||
MaliyeteDahil bool `json:"maliyete_dahil"`
|
||||
CMPriceTypeID *int `json:"cm_price_type_id"`
|
||||
USDTutar float64 `json:"usdTutar"`
|
||||
EURTutar float64 `json:"eurTutar"`
|
||||
GBPTutar float64 `json:"gbpTutar"`
|
||||
SBirim string `json:"sBirim"`
|
||||
SHammaddeTuruAdi string `json:"sHammaddeTuruAdi"`
|
||||
SParcaAdi string `json:"sParcaAdi"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailGroup struct {
|
||||
SAciklama3 string `json:"sAciklama3"`
|
||||
TotalTutar float64 `json:"totalTutar"`
|
||||
TotalUSDTutar float64 `json:"totalUSDTutar"`
|
||||
Items []ProductionHasCostDetailGroupItem `json:"items"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailHeader struct {
|
||||
UretimiYapanFirma string `json:"UretimiYapanFirma"`
|
||||
SonIsEmriVeren string `json:"SonIsEmriVeren"`
|
||||
NOnMLNo string `json:"nOnMLNo"`
|
||||
UrunKodu string `json:"UrunKodu"`
|
||||
UrunAdi string `json:"UrunAdi"`
|
||||
UrunAnaGrubu string `json:"UrunAnaGrubu"`
|
||||
UrunAltGrubu string `json:"UrunAltGrubu"`
|
||||
UretimSekliID string `json:"UretimSekliID"`
|
||||
UretimSekli string `json:"UretimSekli"`
|
||||
DteKayitTarihi string `json:"dteKayitTarihi"`
|
||||
SKullaniciAdi string `json:"sKullaniciAdi"`
|
||||
LTutarTL float64 `json:"lTutarTL"`
|
||||
LTutarUSD float64 `json:"lTutarUSD"`
|
||||
LTutarEURO float64 `json:"lTutarEURO"`
|
||||
LTutarGBP float64 `json:"lTutarGBP"`
|
||||
SDovizCinsi string `json:"sDovizCinsi"`
|
||||
LTutarDoviz float64 `json:"lTutarDoviz"`
|
||||
DteGuncellemeTarihi string `json:"dteGuncellemeTarihi"`
|
||||
SGuncellemeKullaniciAdi string `json:"sGuncellemeKullaniciAdi"`
|
||||
NUrtReceteID string `json:"nUrtReceteID"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailExchangeRates struct {
|
||||
RateDate string `json:"rateDate"`
|
||||
TRYRate float64 `json:"tryRate"`
|
||||
USDRate float64 `json:"usdRate"`
|
||||
EURRate float64 `json:"eurRate"`
|
||||
GBPRate float64 `json:"gbpRate"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailEditorOption struct {
|
||||
Kind string `json:"kind"`
|
||||
Value string `json:"value"`
|
||||
Label string `json:"label"`
|
||||
NStokID string `json:"nStokID"`
|
||||
NHammaddeTuruNo string `json:"nHammaddeTuruNo"`
|
||||
SHammaddeTuruAdi string `json:"sHammaddeTuruAdi"`
|
||||
SAciklama3 string `json:"sAciklama3"`
|
||||
SKodu string `json:"sKodu"`
|
||||
SAciklama string `json:"sAciklama"`
|
||||
SModel string `json:"sModel"`
|
||||
SBirim string `json:"sBirim"`
|
||||
ColorCode string `json:"colorCode"`
|
||||
ColorDescription string `json:"colorDescription"`
|
||||
SParcaAdi string `json:"sParcaAdi"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailPriceLookupItem struct {
|
||||
RowKey string `json:"__rowKey"`
|
||||
NOnMLNo string `json:"n_onml_no"`
|
||||
NOnMLDetNo string `json:"n_onml_det_no"`
|
||||
NHammaddeTuruNo string `json:"n_hammadde_turu_no"`
|
||||
SKodu string `json:"s_kodu"`
|
||||
SAciklama string `json:"s_aciklama"`
|
||||
SRenk string `json:"s_renk"`
|
||||
ColorCode string `json:"color_code"`
|
||||
ColorDescription string `json:"color_description"`
|
||||
ItemDim1Code string `json:"item_dim1_code"`
|
||||
ItemDim1Description string `json:"item_dim1_description"`
|
||||
SBirim string `json:"s_birim"`
|
||||
LMiktar float64 `json:"l_miktar"`
|
||||
FiyatGirilen float64 `json:"fiyat_girilen"`
|
||||
FiyatDoviz string `json:"fiyat_doviz"`
|
||||
MaliyeteDahil int `json:"maliyete_dahil"`
|
||||
CMPriceTypeID *int `json:"cm_price_type_id"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailBulkPriceRequest struct {
|
||||
NOnMLNo string `json:"n_onml_no"`
|
||||
UrunKodu string `json:"urun_kodu"`
|
||||
NUrtReceteID string `json:"n_urt_recete_id"`
|
||||
MaliyetTarihi string `json:"maliyet_tarihi"`
|
||||
Items []ProductionHasCostDetailPriceLookupItem `json:"items"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailBulkPriceRow struct {
|
||||
RowKey string `json:"__rowKey"`
|
||||
NOnMLDetNo string `json:"nOnMLDetNo"`
|
||||
NHammaddeTuruNo string `json:"nHammaddeTuruNo"`
|
||||
SKodu string `json:"sKodu"`
|
||||
ColorCode string `json:"ColorCode"`
|
||||
ColorDescription string `json:"ColorDescription"`
|
||||
ItemDim1Code string `json:"ItemDim1Code"`
|
||||
ItemDim1Description string `json:"ItemDim1Description"`
|
||||
FiyatGirilen float64 `json:"fiyat_girilen"`
|
||||
FiyatDoviz string `json:"fiyat_doviz"`
|
||||
PriceType string `json:"priceType"`
|
||||
Tarih string `json:"Tarih"`
|
||||
FaturaKodu string `json:"FaturaKodu"`
|
||||
MasrafKodu string `json:"MasrafKodu"`
|
||||
MasrafDetay string `json:"MasrafDetay"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailPurchaseHistoryRow struct {
|
||||
SourceType string `json:"sourceType"`
|
||||
Tarih string `json:"Tarih"`
|
||||
FaturaKodu string `json:"FaturaKodu"`
|
||||
FirmaKodu string `json:"FirmaKodu"`
|
||||
FirmaAciklama string `json:"FirmaAciklama"`
|
||||
MasrafKodu string `json:"MasrafKodu"`
|
||||
MasrafDetay string `json:"MasrafDetay"`
|
||||
ColorCode string `json:"ColorCode"`
|
||||
ColorDescription string `json:"ColorDescription"`
|
||||
ItemDim1Code string `json:"ItemDim1Code"`
|
||||
ItemDim1Description string `json:"ItemDim1Description"`
|
||||
Miktar float64 `json:"Miktar"`
|
||||
BIRIM string `json:"BIRIM"`
|
||||
EvrakFiyat float64 `json:"EvrakFiyat"`
|
||||
EvrakTutar float64 `json:"EvrakTutar"`
|
||||
EvrakDoviz string `json:"EvrakDoviz"`
|
||||
PriceType string `json:"priceType"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailRecipeHistoryRow struct {
|
||||
SourceType string `json:"sourceType"`
|
||||
DteIslemTarihi string `json:"dteIslemTarihi"`
|
||||
NOnMLNo string `json:"nOnMLNo"`
|
||||
FirmaKodu string `json:"FirmaKodu"`
|
||||
FirmaAciklama string `json:"FirmaAciklama"`
|
||||
SKodu string `json:"sKodu"`
|
||||
SAciklama string `json:"sAciklama"`
|
||||
SRenk string `json:"sRenk"`
|
||||
LMiktar float64 `json:"lMiktar"`
|
||||
SBirim string `json:"sBirim"`
|
||||
LDovizFiyati float64 `json:"lDovizFiyati"`
|
||||
LDovizTutari float64 `json:"lDovizTutari"`
|
||||
USD string `json:"USD"`
|
||||
PriceType string `json:"priceType"`
|
||||
DUMMY string `json:"DUMMY"`
|
||||
}
|
||||
|
||||
type ProductionHasCostDetailLineHistoryResponse struct {
|
||||
PurchaseRows []ProductionHasCostDetailPurchaseHistoryRow `json:"purchaseRows"`
|
||||
RecipeRows []ProductionHasCostDetailRecipeHistoryRow `json:"recipeRows"`
|
||||
}
|
||||
|
||||
type ProductionProductCostingMTBolumMappingRow struct {
|
||||
ID int `json:"id"`
|
||||
UrunAnaGrubu string `json:"urunAnaGrubu"`
|
||||
UrunAltGrubu string `json:"urunAltGrubu"`
|
||||
NUrtMTBolumID int `json:"nUrtMTBolumID"`
|
||||
MTBolumAdi string `json:"mtBolumAdi"`
|
||||
BAktif bool `json:"bAktif"`
|
||||
DteIslem string `json:"dteIslemTarihi"`
|
||||
SKullaniciAdi string `json:"sKullaniciAdi"`
|
||||
}
|
||||
|
||||
type ProductionProductCostingMTBolumMappingUpsertRequest struct {
|
||||
UrunAnaGrubu string `json:"urunAnaGrubu"`
|
||||
UrunAltGrubu string `json:"urunAltGrubu"`
|
||||
NUrtMTBolumID int `json:"nUrtMTBolumID"`
|
||||
BAktif bool `json:"bAktif"`
|
||||
}
|
||||
|
||||
// NEW: Maliyet Parca Eslestirme (Ana/Alt Grup + MTBolum + cok secmeli HammaddeTurleri)
|
||||
type ProductionProductCostingParcaMappingRow struct {
|
||||
ID int `json:"id"`
|
||||
UrunIlkGrubu string `json:"urunIlkGrubu"`
|
||||
UrunAnaGrubu string `json:"urunAnaGrubu"`
|
||||
UrunAltGrubu string `json:"urunAltGrubu"`
|
||||
NUrtMTBolumID int `json:"nUrtMTBolumID"`
|
||||
ParcaBolumAdi string `json:"parcaBolumAdi"`
|
||||
NHammaddeTurleri []string `json:"nHammaddeTurleri"`
|
||||
BAktif bool `json:"bAktif"`
|
||||
DteIslem string `json:"dteIslemTarihi"`
|
||||
SKullaniciAdi string `json:"sKullaniciAdi"`
|
||||
}
|
||||
|
||||
type ProductionProductCostingParcaMappingUpsertRequest struct {
|
||||
UrunIlkGrubu string `json:"urunIlkGrubu"`
|
||||
UrunAnaGrubu string `json:"urunAnaGrubu"`
|
||||
UrunAltGrubu string `json:"urunAltGrubu"`
|
||||
NUrtMTBolumID int `json:"nUrtMTBolumID"`
|
||||
NHammaddeTurleri []int `json:"nHammaddeTurleri"`
|
||||
BAktif bool `json:"bAktif"`
|
||||
}
|
||||
|
||||
type ProductionProductCostingLookupOption struct {
|
||||
Value string `json:"value"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
type ProductionProductCostingAnaAltComboRow struct {
|
||||
UrunIlkGrubu string `json:"urunIlkGrubu"`
|
||||
UrunAnaGrubu string `json:"urunAnaGrubu"`
|
||||
UrunAltGrubu string `json:"urunAltGrubu"`
|
||||
}
|
||||
@@ -121,7 +121,14 @@ LEFT JOIN (
|
||||
-- Paketlenen (OrderLine IsClosed=1) belge PB toplam
|
||||
SUM(
|
||||
CASE
|
||||
WHEN ISNULL(l.IsClosed,0) = 1
|
||||
WHEN (
|
||||
ISNULL(l.IsClosed,0) = 1
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM dbo.trInvoiceLine il WITH (NOLOCK)
|
||||
WHERE il.OrderLineID = l.OrderLineID
|
||||
)
|
||||
)
|
||||
AND c.CurrencyCode = h.DocCurrencyCode
|
||||
THEN c.NetAmount
|
||||
ELSE 0
|
||||
@@ -131,7 +138,14 @@ LEFT JOIN (
|
||||
-- Paketlenen TRY toplam
|
||||
SUM(
|
||||
CASE
|
||||
WHEN ISNULL(l.IsClosed,0) = 1
|
||||
WHEN (
|
||||
ISNULL(l.IsClosed,0) = 1
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM dbo.trInvoiceLine il WITH (NOLOCK)
|
||||
WHERE il.OrderLineID = l.OrderLineID
|
||||
)
|
||||
)
|
||||
AND c.CurrencyCode = 'TRY'
|
||||
THEN c.NetAmount
|
||||
ELSE 0
|
||||
|
||||
@@ -216,7 +216,16 @@ SELECT
|
||||
L.DeliveryDate,
|
||||
L.PlannedDateOfLading,
|
||||
L.LineDescription,
|
||||
L.IsClosed,
|
||||
CASE
|
||||
WHEN ISNULL(L.IsClosed, 0) = 1
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM BAGGI_V3.dbo.trInvoiceLine il WITH (NOLOCK)
|
||||
WHERE il.OrderLineID = L.OrderLineID
|
||||
)
|
||||
THEN CAST(1 AS bit)
|
||||
ELSE CAST(0 AS bit)
|
||||
END AS IsClosed,
|
||||
L.CreatedUserName,
|
||||
L.CreatedDate,
|
||||
L.LastUpdatedUserName,
|
||||
|
||||
@@ -143,15 +143,29 @@ JOIN (
|
||||
) AS TotalTRY,
|
||||
SUM(
|
||||
CASE
|
||||
-- "Paketlenen" = satir kapaliysa VEYA satir irsaliyeye/faturaya baglandiysa.
|
||||
-- Not: IsClosed her zaman guncellenmiyor; trInvoiceLine.OrderLineID iliskiyi yakalar.
|
||||
WHEN ISNULL(l.IsClosed,0) = 1
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM dbo.trInvoiceLine il WITH (NOLOCK)
|
||||
WHERE il.OrderLineID = l.OrderLineID
|
||||
)
|
||||
THEN ISNULL(c.NetAmount,0)
|
||||
ELSE 0
|
||||
END
|
||||
) AS PackedAmount,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN ISNULL(l.IsClosed,0) = 1
|
||||
AND ISNULL(c.CurrencyCode,'') = 'TRY'
|
||||
WHEN (
|
||||
ISNULL(l.IsClosed,0) = 1
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM dbo.trInvoiceLine il WITH (NOLOCK)
|
||||
WHERE il.OrderLineID = l.OrderLineID
|
||||
)
|
||||
)
|
||||
AND ISNULL(c.CurrencyCode,'') = 'TRY'
|
||||
THEN ISNULL(c.NetAmount,0)
|
||||
ELSE 0
|
||||
END
|
||||
|
||||
1702
svc/queries/production_product_costing.go
Normal file
1702
svc/queries/production_product_costing.go
Normal file
@@ -0,0 +1,1702 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"bssapp-backend/utils"
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func GetProductAnaAltGrupByUrunKodu(ctx context.Context, mssqlDB *sql.DB, urunKodu string) (urunAnaGrubu string, urunAltGrubu string, err error) {
|
||||
urunKodu = strings.TrimSpace(urunKodu)
|
||||
if mssqlDB == nil || urunKodu == "" {
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
// Nebim V3: ProductFilterWithDescription exposes ProductAtt01Desc (ana grup) and ProductAtt02Desc (alt grup).
|
||||
sqlText := `
|
||||
SELECT TOP 1
|
||||
ISNULL(ProductAtt01Desc, '') AS UrunAnaGrubu,
|
||||
ISNULL(ProductAtt02Desc, '') AS UrunAltGrubu
|
||||
FROM ProductFilterWithDescription('TR')
|
||||
WHERE IsBlocked = 0
|
||||
AND LTRIM(RTRIM(ProductCode)) = @p1
|
||||
ORDER BY ProductCode;
|
||||
`
|
||||
|
||||
row := mssqlDB.QueryRowContext(ctx, sqlText, urunKodu)
|
||||
if err := row.Scan(&urunAnaGrubu, &urunAltGrubu); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return "", "", nil
|
||||
}
|
||||
return "", "", err
|
||||
}
|
||||
return urunAnaGrubu, urunAltGrubu, nil
|
||||
}
|
||||
|
||||
func GetProductionProductCostingAnaGrupOptions(ctx context.Context, mssqlDB *sql.DB, search string, limit int) (*sql.Rows, error) {
|
||||
search = strings.TrimSpace(search)
|
||||
if limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
searchLike := "%" + search + "%"
|
||||
sqlText := `
|
||||
SELECT TOP (@p2)
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(P.ProductAtt01Desc)), ''), '') AS UrunAnaGrubu
|
||||
FROM ProductFilterWithDescription('TR') AS P
|
||||
WHERE P.IsBlocked = 0
|
||||
AND NULLIF(LTRIM(RTRIM(P.ProductAtt01Desc)), '') IS NOT NULL
|
||||
AND (@p1 = '' OR P.ProductAtt01Desc LIKE @p3)
|
||||
GROUP BY P.ProductAtt01Desc
|
||||
ORDER BY P.ProductAtt01Desc
|
||||
`
|
||||
return mssqlDB.QueryContext(ctx, sqlText, search, limit, searchLike)
|
||||
}
|
||||
|
||||
func GetProductionProductCostingAltGrupOptions(ctx context.Context, mssqlDB *sql.DB, urunAnaGrubu string, search string, limit int) (*sql.Rows, error) {
|
||||
urunAnaGrubu = strings.TrimSpace(urunAnaGrubu)
|
||||
search = strings.TrimSpace(search)
|
||||
if limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
searchLike := "%" + search + "%"
|
||||
sqlText := `
|
||||
SELECT TOP (@p3)
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(P.ProductAtt02Desc)), ''), '') AS UrunAltGrubu
|
||||
FROM ProductFilterWithDescription('TR') AS P
|
||||
WHERE P.IsBlocked = 0
|
||||
AND NULLIF(LTRIM(RTRIM(P.ProductAtt02Desc)), '') IS NOT NULL
|
||||
AND (@p1 = '' OR LTRIM(RTRIM(P.ProductAtt01Desc)) = @p1)
|
||||
AND (@p2 = '' OR P.ProductAtt02Desc LIKE @p4)
|
||||
GROUP BY P.ProductAtt02Desc
|
||||
ORDER BY P.ProductAtt02Desc
|
||||
`
|
||||
return mssqlDB.QueryContext(ctx, sqlText, urunAnaGrubu, search, limit, searchLike)
|
||||
}
|
||||
|
||||
func GetProductionProductCostingAnaAltComboRows(ctx context.Context, mssqlDB *sql.DB, search string, limit int) (*sql.Rows, error) {
|
||||
search = strings.TrimSpace(search)
|
||||
if limit <= 0 {
|
||||
limit = 500
|
||||
}
|
||||
if limit > 5000 {
|
||||
limit = 5000
|
||||
}
|
||||
// For very short searches, avoid leading-wildcard LIKE which can be extremely expensive on MSSQL side.
|
||||
// Example: "ce" should match "CEKET%" cheaply vs "%ce%" scanning everything.
|
||||
searchLike := "%" + search + "%"
|
||||
if len([]rune(search)) > 0 && len([]rune(search)) < 3 {
|
||||
searchLike = search + "%"
|
||||
}
|
||||
sqlText := `
|
||||
SELECT TOP (@p2)
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(CONVERT(NVARCHAR(200), P.ProductAtt42Desc))), ''), '') AS UrunIlkGrubu,
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(CONVERT(NVARCHAR(200), P.ProductAtt01Desc))), ''), '') AS UrunAnaGrubu,
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(CONVERT(NVARCHAR(200), P.ProductAtt02Desc))), ''), '') AS UrunAltGrubu
|
||||
FROM ProductFilterWithDescription('TR') AS P
|
||||
WHERE P.IsBlocked = 0
|
||||
AND NULLIF(LTRIM(RTRIM(CONVERT(NVARCHAR(200), P.ProductAtt42Desc))), '') IS NOT NULL
|
||||
AND NULLIF(LTRIM(RTRIM(CONVERT(NVARCHAR(200), P.ProductAtt01Desc))), '') IS NOT NULL
|
||||
AND NULLIF(LTRIM(RTRIM(CONVERT(NVARCHAR(200), P.ProductAtt02Desc))), '') IS NOT NULL
|
||||
AND (
|
||||
@p1 = ''
|
||||
OR CONVERT(NVARCHAR(200), P.ProductAtt42Desc) LIKE @p3
|
||||
OR CONVERT(NVARCHAR(200), P.ProductAtt01Desc) LIKE @p3
|
||||
OR CONVERT(NVARCHAR(200), P.ProductAtt02Desc) LIKE @p3
|
||||
)
|
||||
GROUP BY
|
||||
CONVERT(NVARCHAR(200), P.ProductAtt42Desc),
|
||||
CONVERT(NVARCHAR(200), P.ProductAtt01Desc),
|
||||
CONVERT(NVARCHAR(200), P.ProductAtt02Desc)
|
||||
ORDER BY
|
||||
CONVERT(NVARCHAR(200), P.ProductAtt42Desc),
|
||||
CONVERT(NVARCHAR(200), P.ProductAtt02Desc),
|
||||
CONVERT(NVARCHAR(200), P.ProductAtt01Desc)
|
||||
`
|
||||
return mssqlDB.QueryContext(ctx, sqlText, search, limit, searchLike)
|
||||
}
|
||||
|
||||
func GetProductionProductCostingMTBolumOptions(ctx context.Context, uretimDB *sql.DB, search string, limit int) (*sql.Rows, error) {
|
||||
search = strings.TrimSpace(search)
|
||||
if limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
searchLike := "%" + search + "%"
|
||||
sqlText := `
|
||||
SELECT TOP (@p2)
|
||||
ISNULL(B.nUrtMTBolumID, 0) AS nUrtMTBolumID,
|
||||
ISNULL(B.sAdi, '') AS sAdi
|
||||
FROM dbo.spUrtMTBolum B WITH (NOLOCK)
|
||||
WHERE ISNULL(B.bAktif, 0) = 1
|
||||
AND (@p1 = '' OR ISNULL(B.sAdi, '') LIKE @p3 OR CONVERT(VARCHAR(32), ISNULL(B.nUrtMTBolumID, 0)) LIKE @p3)
|
||||
ORDER BY B.nUrtMTBolumID
|
||||
`
|
||||
return uretimDB.QueryContext(ctx, sqlText, search, limit, searchLike)
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Maliyet Parca Eslestirme (URETIM DB)
|
||||
// ============================================================
|
||||
|
||||
func ListProductionProductCostingParcaMappings(ctx context.Context, uretimDB *sql.DB, urunIlkGrubu string, urunAnaGrubu string, urunAltGrubu string, nUrtMTBolumID int, onlyActive *bool) (*sql.Rows, error) {
|
||||
urunIlkGrubu = strings.TrimSpace(urunIlkGrubu)
|
||||
urunAnaGrubu = strings.TrimSpace(urunAnaGrubu)
|
||||
urunAltGrubu = strings.TrimSpace(urunAltGrubu)
|
||||
sqlText := `
|
||||
SELECT
|
||||
M.id,
|
||||
ISNULL(M.UrunIlkGrubu, '') AS UrunIlkGrubu,
|
||||
ISNULL(M.UrunAnaGrubu, '') AS UrunAnaGrubu,
|
||||
ISNULL(M.UrunAltGrubu, '') AS UrunAltGrubu,
|
||||
ISNULL(M.nUrtMTBolumID, 0) AS nUrtMTBolumID,
|
||||
ISNULL(B.sAdi, '') AS MTBolumAdi,
|
||||
ISNULL(H.HammaddeTurleri, '') AS HammaddeTurleri,
|
||||
CAST(CASE WHEN ISNULL(M.bAktif, 0) = 1 THEN 1 ELSE 0 END AS bit) AS bAktif,
|
||||
CONVERT(VARCHAR(16), M.dteIslemTarihi, 120) AS dteIslemTarihi,
|
||||
ISNULL(M.sKullaniciAdi, '') AS sKullaniciAdi
|
||||
FROM dbo.mk_MaliyetParcaEslestirme M WITH (NOLOCK)
|
||||
LEFT JOIN dbo.spUrtMTBolum B WITH (NOLOCK)
|
||||
ON B.nUrtMTBolumID = M.nUrtMTBolumID
|
||||
OUTER APPLY (
|
||||
SELECT
|
||||
STUFF((
|
||||
SELECT ',' + LTRIM(RTRIM(CONVERT(VARCHAR(32), X.nHammaddeTuruNo)))
|
||||
FROM dbo.mk_MaliyetParcaEslestirme_HammaddeTuru X WITH (NOLOCK)
|
||||
WHERE X.mapping_id = M.id
|
||||
ORDER BY X.nHammaddeTuruNo
|
||||
FOR XML PATH(''), TYPE
|
||||
).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS HammaddeTurleri
|
||||
) H
|
||||
WHERE (@p1 = '' OR LTRIM(RTRIM(M.UrunIlkGrubu)) = @p1)
|
||||
AND (@p2 = '' OR LTRIM(RTRIM(M.UrunAnaGrubu)) = @p2)
|
||||
AND (@p3 = '' OR LTRIM(RTRIM(M.UrunAltGrubu)) = @p3)
|
||||
AND (@p4 <= 0 OR M.nUrtMTBolumID = @p4)
|
||||
AND (@p5 IS NULL OR ISNULL(M.bAktif, 0) = @p5)
|
||||
ORDER BY M.UrunAltGrubu, M.UrunAnaGrubu, M.nUrtMTBolumID
|
||||
`
|
||||
var activeParam any = nil
|
||||
if onlyActive != nil {
|
||||
if *onlyActive {
|
||||
activeParam = 1
|
||||
} else {
|
||||
activeParam = 0
|
||||
}
|
||||
}
|
||||
return uretimDB.QueryContext(ctx, sqlText, urunIlkGrubu, urunAnaGrubu, urunAltGrubu, nUrtMTBolumID, activeParam)
|
||||
}
|
||||
|
||||
func UpsertProductionProductCostingParcaMapping(ctx context.Context, uretimDB *sql.DB, urunIlkGrubu string, urunAnaGrubu string, urunAltGrubu string, nUrtMTBolumID int, nHammaddeTurleri []int, bAktif bool, user string) (mappingID int, err error) {
|
||||
urunIlkGrubu = strings.TrimSpace(urunIlkGrubu)
|
||||
urunAnaGrubu = strings.TrimSpace(urunAnaGrubu)
|
||||
urunAltGrubu = strings.TrimSpace(urunAltGrubu)
|
||||
user = strings.TrimSpace(user)
|
||||
activeVal := 0
|
||||
if bAktif {
|
||||
activeVal = 1
|
||||
}
|
||||
|
||||
tx, err := uretimDB.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
// 1) Upsert header row and get mapping id
|
||||
sqlText := `
|
||||
DECLARE @id INT;
|
||||
|
||||
SELECT TOP 1 @id = id
|
||||
FROM dbo.mk_MaliyetParcaEslestirme WITH (UPDLOCK, HOLDLOCK)
|
||||
WHERE LTRIM(RTRIM(UrunIlkGrubu)) = @p1
|
||||
AND LTRIM(RTRIM(UrunAnaGrubu)) = @p2
|
||||
AND LTRIM(RTRIM(UrunAltGrubu)) = @p3
|
||||
AND nUrtMTBolumID = @p4;
|
||||
|
||||
IF @id IS NULL
|
||||
BEGIN
|
||||
INSERT INTO dbo.mk_MaliyetParcaEslestirme
|
||||
(UrunIlkGrubu, UrunAnaGrubu, UrunAltGrubu, nUrtMTBolumID, bAktif, sKullaniciAdi, dteIslemTarihi)
|
||||
VALUES
|
||||
(@p1, @p2, @p3, @p4, @p5, NULLIF(@p6, ''), GETDATE());
|
||||
SET @id = SCOPE_IDENTITY();
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
UPDATE dbo.mk_MaliyetParcaEslestirme
|
||||
SET bAktif = @p5,
|
||||
sKullaniciAdiDeg = NULLIF(@p6, ''),
|
||||
dteIslemTarihiDeg = GETDATE()
|
||||
WHERE id = @id;
|
||||
END
|
||||
|
||||
SELECT @id;
|
||||
`
|
||||
if err = tx.QueryRowContext(ctx, sqlText, urunIlkGrubu, urunAnaGrubu, urunAltGrubu, nUrtMTBolumID, activeVal, user).Scan(&mappingID); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 2) Replace child rows
|
||||
if _, err = tx.ExecContext(ctx, `DELETE FROM dbo.mk_MaliyetParcaEslestirme_HammaddeTuru WHERE mapping_id = @p1;`, mappingID); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
insertChild := `INSERT INTO dbo.mk_MaliyetParcaEslestirme_HammaddeTuru (mapping_id, nHammaddeTuruNo) VALUES (@p1, @p2);`
|
||||
seen := make(map[int]bool, len(nHammaddeTurleri))
|
||||
for _, n := range nHammaddeTurleri {
|
||||
if n <= 0 {
|
||||
continue
|
||||
}
|
||||
if seen[n] {
|
||||
continue
|
||||
}
|
||||
seen[n] = true
|
||||
if _, err = tx.ExecContext(ctx, insertChild, mappingID, n); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
if err = tx.Commit(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return mappingID, nil
|
||||
}
|
||||
|
||||
func SetProductionProductCostingParcaMappingActive(ctx context.Context, uretimDB *sql.DB, id int, bAktif bool, user string) error {
|
||||
user = strings.TrimSpace(user)
|
||||
activeVal := 0
|
||||
if bAktif {
|
||||
activeVal = 1
|
||||
}
|
||||
sqlText := `
|
||||
UPDATE dbo.mk_MaliyetParcaEslestirme
|
||||
SET bAktif = @p2,
|
||||
sKullaniciAdiDeg = NULLIF(@p3, ''),
|
||||
dteIslemTarihiDeg = GETDATE()
|
||||
WHERE id = @p1;
|
||||
`
|
||||
_, err := uretimDB.ExecContext(ctx, sqlText, id, activeVal, user)
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteProductionProductCostingParcaMapping(ctx context.Context, uretimDB *sql.DB, id int) error {
|
||||
tx, err := uretimDB.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err = tx.ExecContext(ctx, `DELETE FROM dbo.mk_MaliyetParcaEslestirme_HammaddeTuru WHERE mapping_id = @p1;`, id); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tx.ExecContext(ctx, `DELETE FROM dbo.mk_MaliyetParcaEslestirme WHERE id = @p1;`, id); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func GetProductionNoCostProducts(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
fromDate string,
|
||||
search string,
|
||||
) (*sql.Rows, error) {
|
||||
fromDate = strings.TrimSpace(fromDate)
|
||||
if fromDate == "" {
|
||||
fromDate = "2025-06-01"
|
||||
}
|
||||
search = strings.TrimSpace(search)
|
||||
|
||||
sqlText := `
|
||||
SELECT
|
||||
CASE
|
||||
WHEN LEFT(LTRIM(RTRIM(R.sMModelKodu)), 1) IN ('N','X','S','O','I','K')
|
||||
THEN N'BAGGI URUN TARAFINDAN URETIME VERILEN'
|
||||
WHEN LEFT(LTRIM(RTRIM(R.sMModelKodu)), 1) IN ('P','F','M')
|
||||
THEN N'FASON ICIN URETILEN'
|
||||
ELSE N'Tanimsiz'
|
||||
END AS UretimSekli,
|
||||
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(SonIsEmri.nUrtSiparisNo, 0))) AS nUrtSiparisNo,
|
||||
CONVERT(VARCHAR(10), SonIsEmri.dteIslemTarihi, 23) AS dteIslemTarihi,
|
||||
ISNULL(SonIsEmri.FirmaKodu, '') AS FirmaKodu,
|
||||
ISNULL(SonIsEmri.FirmaAdi, '') AS FirmaAdi,
|
||||
ISNULL(SonIsEmri.sVeren, '') AS SonIsEmriVeren,
|
||||
ISNULL(SonIsEmri.lMMiktar_G, 0) AS lMMiktar_G,
|
||||
LTRIM(RTRIM(R.sMModelKodu)) AS sMModelKodu,
|
||||
ISNULL(R.sKodu, '') AS sKodu,
|
||||
ISNULL(R.sAdi, '') AS sAdi,
|
||||
ISNULL(R.sKullaniciAdi, '') AS sKullaniciAdi,
|
||||
ISNULL(R.sKullaniciAdiGunc, '') AS sKullaniciAdiGunc
|
||||
|
||||
FROM dbo.spUrtRecete R
|
||||
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1
|
||||
SD.nUrtSiparisID,
|
||||
SM.nUrtSiparisNo,
|
||||
SD.dteIslemTarihi,
|
||||
SD.lMMiktar_G,
|
||||
SM.sVeren,
|
||||
F.nFirmaID,
|
||||
F.sKodu AS FirmaKodu,
|
||||
F.sAciklama AS FirmaAdi
|
||||
FROM dbo.spUrtSiparisDet SD
|
||||
INNER JOIN dbo.spUrtSiparis SM
|
||||
ON SM.nUrtSiparisID = SD.nUrtSiparisID
|
||||
LEFT JOIN dbo.tbFirma F
|
||||
ON F.nFirmaID = SM.nFirmaID
|
||||
WHERE SD.nUrtReceteID = R.nUrtReceteID
|
||||
ORDER BY SD.dteIslemTarihi DESC, SD.nUrtSiparisID DESC
|
||||
) SonIsEmri
|
||||
|
||||
WHERE LTRIM(RTRIM(R.sMModelKodu)) <> ''
|
||||
AND LEN(LTRIM(RTRIM(R.sMModelKodu))) = 13
|
||||
AND R.dteIslemTarihi > @p1
|
||||
AND (
|
||||
@p2 = ''
|
||||
OR LTRIM(RTRIM(R.sMModelKodu)) LIKE '%' + @p2 + '%'
|
||||
OR ISNULL(SonIsEmri.FirmaKodu, '') LIKE '%' + @p2 + '%'
|
||||
OR ISNULL(SonIsEmri.FirmaAdi, '') LIKE '%' + @p2 + '%'
|
||||
OR ISNULL(SonIsEmri.sVeren, '') LIKE '%' + @p2 + '%'
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM dbo.spUrtOnMLMas M
|
||||
WHERE LTRIM(RTRIM(M.UrunKodu)) = LTRIM(RTRIM(R.sMModelKodu))
|
||||
)
|
||||
ORDER BY SonIsEmri.dteIslemTarihi DESC, LTRIM(RTRIM(R.sMModelKodu)) ASC
|
||||
`
|
||||
|
||||
return uretimDB.QueryContext(ctx, sqlText, fromDate, search)
|
||||
}
|
||||
|
||||
func GetProductionHasCostProducts(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
search string,
|
||||
offset int,
|
||||
limit int,
|
||||
) (*sql.Rows, error) {
|
||||
search = strings.TrimSpace(search)
|
||||
|
||||
sqlText := `
|
||||
WITH SonOnMaliyet AS (
|
||||
SELECT
|
||||
M.*,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY LTRIM(RTRIM(M.UrunKodu))
|
||||
ORDER BY
|
||||
M.Tarihi DESC,
|
||||
M.dteGuncellemeTarihi DESC,
|
||||
M.nOnMLNo DESC
|
||||
) AS rn
|
||||
FROM dbo.spUrtOnMLMas M
|
||||
WHERE LTRIM(RTRIM(M.UrunKodu)) <> ''
|
||||
),
|
||||
SonSiparis AS (
|
||||
SELECT
|
||||
LTRIM(RTRIM(sMModelKodu)) AS UrunKodu,
|
||||
MAX(dteIslemTarihi) AS SonSiparisTarihi
|
||||
FROM dbo.spUrtSiparisDet
|
||||
GROUP BY LTRIM(RTRIM(sMModelKodu))
|
||||
)
|
||||
SELECT
|
||||
CASE
|
||||
WHEN LEFT(LTRIM(RTRIM(OM.UrunKodu)), 1) IN ('N','X','S','O','I','K')
|
||||
THEN N'BAGGI URUN TARAFINDAN URETIME VERILEN'
|
||||
WHEN LEFT(LTRIM(RTRIM(OM.UrunKodu)), 1) IN ('P','F','M')
|
||||
THEN N'FASON ICIN URETILEN'
|
||||
ELSE N'Tanimsiz'
|
||||
END AS UretimSekli,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(OM.nOnMLNo, 0))) AS nOnMLNo,
|
||||
LTRIM(RTRIM(ISNULL(OM.UrunKodu, ''))) AS UrunKodu,
|
||||
ISNULL(OM.UrunAdi, '') AS UrunAdi,
|
||||
CONVERT(VARCHAR(10), OM.Tarihi, 23) AS Tarihi,
|
||||
CONVERT(VARCHAR(10), OM.dteKayitTarihi, 23) AS dteKayitTarihi,
|
||||
ISNULL(OM.sKullaniciAdi, '') AS sKullaniciAdi,
|
||||
ISNULL(OM.lTutarTL, 0) AS lTutarTL,
|
||||
ISNULL(OM.lTutarUSD, 0) AS lTutarUSD,
|
||||
ISNULL(OM.lTutarEURO, 0) AS lTutarEURO,
|
||||
CONVERT(VARCHAR(10), OM.dteGuncellemeTarihi, 23) AS dteGuncellemeTarihi,
|
||||
ISNULL(OM.sGuncellemeKullaniciAdi, '') AS sGuncellemeKullaniciAdi,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(OM.nUrtReceteID, 0))) AS nUrtReceteID,
|
||||
ISNULL(OM.sAciklama, '') AS sAciklama,
|
||||
ISNULL(CONVERT(VARCHAR(10), SS.SonSiparisTarihi, 23), '') AS SonSiparisTarihi,
|
||||
CASE
|
||||
WHEN ISNULL(OM.lTutarUSD, 0) = 0 THEN N'GUNCELLEME GEREKIYOR'
|
||||
WHEN SS.SonSiparisTarihi IS NULL THEN N'SIPARIS YOK'
|
||||
WHEN SS.SonSiparisTarihi > OM.Tarihi THEN N'GUNCELLEME GEREKIYOR'
|
||||
ELSE N'GUNCEL'
|
||||
END AS MaliyetDurumu
|
||||
FROM SonOnMaliyet OM
|
||||
LEFT JOIN SonSiparis SS
|
||||
ON SS.UrunKodu = LTRIM(RTRIM(OM.UrunKodu))
|
||||
WHERE OM.rn = 1
|
||||
AND (
|
||||
@p1 = ''
|
||||
OR RTRIM(CONVERT(VARCHAR(32), ISNULL(OM.nOnMLNo, 0))) LIKE '%' + @p1 + '%'
|
||||
OR LTRIM(RTRIM(OM.UrunKodu)) LIKE '%' + @p1 + '%'
|
||||
OR ISNULL(OM.UrunAdi, '') LIKE '%' + @p1 + '%'
|
||||
OR ISNULL(OM.sAciklama, '') LIKE '%' + @p1 + '%'
|
||||
)
|
||||
ORDER BY
|
||||
SS.SonSiparisTarihi DESC,
|
||||
OM.nOnMLNo DESC
|
||||
OFFSET @p2 ROWS
|
||||
FETCH NEXT @p3 ROWS ONLY
|
||||
`
|
||||
|
||||
return uretimDB.QueryContext(ctx, sqlText, search, offset, limit)
|
||||
}
|
||||
|
||||
func GetProductionHasCostHistoryByProductCode(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
productCode string,
|
||||
) (*sql.Rows, error) {
|
||||
productCode = strings.TrimSpace(productCode)
|
||||
|
||||
sqlText := `
|
||||
SELECT
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(M.nOnMLNo, 0))) AS nOnMLNo,
|
||||
LTRIM(RTRIM(ISNULL(M.UrunKodu, ''))) AS UrunKodu,
|
||||
ISNULL(M.UrunAdi, '') AS UrunAdi,
|
||||
CONVERT(VARCHAR(16), M.Tarihi, 120) AS Tarihi,
|
||||
ISNULL(M.sKullaniciAdi, '') AS sKullaniciAdi,
|
||||
ISNULL(M.lTutarUSD, 0) AS lTutarUSD,
|
||||
ISNULL(M.lTutarTL, 0) AS lTutarTL,
|
||||
ISNULL(M.lTutarEURO, 0) AS lTutarEURO,
|
||||
ISNULL(M.sDovizCinsi, '') AS sDovizCinsi,
|
||||
ISNULL(M.lTutarDoviz, 0) AS lTutarDoviz,
|
||||
CONVERT(VARCHAR(16), M.dteGuncellemeTarihi, 120) AS dteGuncellemeTarihi,
|
||||
ISNULL(M.sGuncellemeKullaniciAdi, '') AS sGuncellemeKullaniciAdi,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(M.nUrtReceteID, 0))) AS nUrtReceteID,
|
||||
ISNULL(M.sAciklama, '') AS sAciklama
|
||||
FROM dbo.spUrtOnMLMas M
|
||||
WHERE LTRIM(RTRIM(M.UrunKodu)) = @p1
|
||||
ORDER BY
|
||||
M.Tarihi DESC,
|
||||
M.dteGuncellemeTarihi DESC,
|
||||
M.nOnMLNo DESC
|
||||
`
|
||||
|
||||
return uretimDB.QueryContext(ctx, sqlText, productCode)
|
||||
}
|
||||
|
||||
func GetProductionHasCostDetailRowsByOnMLNo(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
nOnMLNo int,
|
||||
) (*sql.Rows, error) {
|
||||
sqlText := `
|
||||
SELECT
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(T.sAciklama3)), ''), N'TANIMSIZ') AS sAciklama3,
|
||||
SUM(ISNULL(D.lTutar, 0)) OVER (
|
||||
PARTITION BY ISNULL(NULLIF(LTRIM(RTRIM(T.sAciklama3)), ''), N'TANIMSIZ')
|
||||
) AS GroupTotalTutar,
|
||||
SUM(ISNULL(D.lMiktar, 0) * ISNULL(D.lDovizFiyati, 0)) OVER (
|
||||
PARTITION BY ISNULL(NULLIF(LTRIM(RTRIM(T.sAciklama3)), ''), N'TANIMSIZ')
|
||||
) AS GroupTotalUSDTutar,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(D.nOnMLNo, 0))) AS nOnMLNo,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(D.nOnMLDetNo, 0))) AS nOnMLDetNo,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(D.nHammaddeTuruNo, 0))) AS nHammaddeTuruNo,
|
||||
ISNULL(D.sKodu, '') AS sKodu,
|
||||
ISNULL(D.sAciklama, '') AS sAciklama,
|
||||
ISNULL(D.sRenk, '') AS sRenk,
|
||||
ISNULL(D.sBeden, '') AS sBeden,
|
||||
ISNULL(D.sAciklama2, '') AS sAciklama2,
|
||||
ISNULL(D.lMiktar, 0) AS lMiktar,
|
||||
ISNULL(D.lFiyat, 0) AS lFiyat,
|
||||
ISNULL(D.lTutar, 0) AS lTutar,
|
||||
ISNULL(D.sFiyatTipi, '') AS sFiyatTipi,
|
||||
ISNULL(D.sDovizCinsi, '') AS sDovizCinsi,
|
||||
ISNULL(D.lDovizKuru, 0) AS lDovizKuru,
|
||||
ISNULL(D.lDovizFiyati, 0) AS lDovizFiyati,
|
||||
D.fiyat_girilen AS fiyat_girilen,
|
||||
D.fiyat_doviz AS fiyat_doviz,
|
||||
CAST(CASE WHEN ISNULL(D.Maliyete_dahil, 0) = 1 THEN 1 ELSE 0 END AS bit) AS maliyete_dahil,
|
||||
D.cm_price_type_id AS cm_price_type_id,
|
||||
ISNULL(D.lMiktar, 0) * ISNULL(D.lDovizFiyati, 0) AS usdTutar,
|
||||
0.0 AS eurTutar,
|
||||
0.0 AS gbpTutar,
|
||||
ISNULL(D.sBirim, '') AS sBirim,
|
||||
ISNULL(T.sAciklama, '') AS sHammaddeTuruAdi,
|
||||
ISNULL(B.sAdi, '') AS sParcaAdi
|
||||
FROM dbo.spUrtOnMLMasDet D
|
||||
LEFT JOIN dbo.spUrtOnMLHammaddeTuru T
|
||||
ON T.nHammaddeTuruNo = D.nHammaddeTuruNo
|
||||
LEFT JOIN dbo.spUrtMTBolum B
|
||||
ON B.nUrtMTBolumID = D.nUrtMTBolumID
|
||||
WHERE D.nOnMLNo = @p1
|
||||
ORDER BY
|
||||
GroupTotalTutar DESC,
|
||||
sAciklama3 ASC,
|
||||
ISNULL(D.lTutar, 0) DESC,
|
||||
D.nOnMLDetNo ASC
|
||||
`
|
||||
|
||||
return uretimDB.QueryContext(ctx, sqlText, nOnMLNo)
|
||||
}
|
||||
|
||||
func GetProductionHasCostDetailHeaderByOnMLNo(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
nOnMLNo int,
|
||||
) (*sql.Row, error) {
|
||||
sqlText := `
|
||||
SELECT TOP 1
|
||||
ISNULL(UF.UretimiYapanFirma, '') AS UretimiYapanFirma,
|
||||
ISNULL(UF.SonIsEmriVeren, '') AS SonIsEmriVeren,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(M.nOnMLNo, 0))) AS nOnMLNo,
|
||||
LTRIM(RTRIM(ISNULL(M.UrunKodu, ''))) AS UrunKodu,
|
||||
ISNULL(M.UrunAdi, '') AS UrunAdi,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(M.uretim_sekli_id, 0))) AS uretim_sekli_id,
|
||||
ISNULL(US.aciklama, '') AS uretim_sekli,
|
||||
CONVERT(VARCHAR(16), M.dteKayitTarihi, 120) AS dteKayitTarihi,
|
||||
ISNULL(M.sKullaniciAdi, '') AS sKullaniciAdi,
|
||||
ISNULL(M.lTutarTL, 0) AS lTutarTL,
|
||||
ISNULL(M.lTutarUSD, 0) AS lTutarUSD,
|
||||
ISNULL(M.lTutarEURO, 0) AS lTutarEURO,
|
||||
0.0 AS lTutarGBP,
|
||||
ISNULL(M.sDovizCinsi, '') AS sDovizCinsi,
|
||||
ISNULL(M.lTutarDoviz, 0) AS lTutarDoviz,
|
||||
CONVERT(VARCHAR(16), M.dteGuncellemeTarihi, 120) AS dteGuncellemeTarihi,
|
||||
ISNULL(M.sGuncellemeKullaniciAdi, '') AS sGuncellemeKullaniciAdi,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(M.nUrtReceteID, 0))) AS nUrtReceteID
|
||||
FROM dbo.spUrtOnMLMas M
|
||||
LEFT JOIN dbo.mk_uretim_sekli US
|
||||
ON US.id = M.uretim_sekli_id
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1
|
||||
ISNULL(F.sAciklama, '') AS UretimiYapanFirma,
|
||||
ISNULL(SM.sVeren, '') AS SonIsEmriVeren
|
||||
FROM dbo.spUrtSiparisDet SD
|
||||
INNER JOIN dbo.spUrtSiparis SM
|
||||
ON SM.nUrtSiparisID = SD.nUrtSiparisID
|
||||
LEFT JOIN dbo.tbFirma F
|
||||
ON F.nFirmaID = SM.nFirmaID
|
||||
WHERE LTRIM(RTRIM(SD.sMModelKodu)) = LTRIM(RTRIM(M.UrunKodu))
|
||||
ORDER BY SD.dteIslemTarihi DESC, SD.nUrtSiparisID DESC
|
||||
) UF
|
||||
WHERE M.nOnMLNo = @p1
|
||||
ORDER BY M.nOnMLNo DESC
|
||||
`
|
||||
|
||||
return uretimDB.QueryRowContext(ctx, sqlText, nOnMLNo), nil
|
||||
}
|
||||
|
||||
func GetProductionNoCostDetailHeaderByRecipeCode(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
recipeCode string,
|
||||
productCode string,
|
||||
) (*sql.Row, error) {
|
||||
recipeCode = strings.TrimSpace(recipeCode)
|
||||
productCode = strings.TrimSpace(productCode)
|
||||
utils.SlogFromContext(ctx).With(
|
||||
"query", "production-product-costing.no-cost-detail-header",
|
||||
"recete_kodu", recipeCode,
|
||||
"urun_kodu", productCode,
|
||||
).Info("query dispatch")
|
||||
|
||||
sqlText := `
|
||||
WITH RecipeMatch AS (
|
||||
SELECT TOP 1
|
||||
R.nUrtReceteID,
|
||||
LTRIM(RTRIM(ISNULL(R.sMModelKodu, ''))) AS UrunKodu,
|
||||
ISNULL(R.sAdi, '') AS UrunAdi,
|
||||
CONVERT(VARCHAR(16), R.dteIslemTarihi, 120) AS dteKayitTarihi,
|
||||
ISNULL(R.sKullaniciAdi, '') AS sKullaniciAdi,
|
||||
ISNULL(R.sKullaniciAdiGunc, '') AS sGuncellemeKullaniciAdi,
|
||||
CASE
|
||||
WHEN LEFT(LTRIM(RTRIM(R.sMModelKodu)), 1) IN ('N','X','S','O','I','K')
|
||||
THEN N'BAGGI URUN TARAFINDAN URETIME VERILEN'
|
||||
WHEN LEFT(LTRIM(RTRIM(R.sMModelKodu)), 1) IN ('P','F','M')
|
||||
THEN N'FASON ICIN URETILEN'
|
||||
ELSE N'Tanimsiz'
|
||||
END AS UretimSekli
|
||||
FROM dbo.spUrtRecete R
|
||||
WHERE LTRIM(RTRIM(ISNULL(R.sKodu, ''))) = @p1
|
||||
AND (@p2 = '' OR LTRIM(RTRIM(ISNULL(R.sMModelKodu, ''))) = @p2)
|
||||
ORDER BY
|
||||
R.dteIslemTarihi DESC,
|
||||
R.nUrtReceteID DESC
|
||||
)
|
||||
SELECT TOP 1
|
||||
ISNULL(SonIsEmri.FirmaAdi, '') AS UretimiYapanFirma,
|
||||
ISNULL(SonIsEmri.SonIsEmriVeren, '') AS SonIsEmriVeren,
|
||||
'' AS nOnMLNo,
|
||||
RM.UrunKodu,
|
||||
RM.UrunAdi,
|
||||
'' AS UretimSekliID,
|
||||
RM.UretimSekli,
|
||||
ISNULL(SonIsEmri.dteIslemTarihi, RM.dteKayitTarihi) AS dteKayitTarihi,
|
||||
RM.sKullaniciAdi,
|
||||
0.0 AS lTutarTL,
|
||||
0.0 AS lTutarUSD,
|
||||
0.0 AS lTutarEURO,
|
||||
0.0 AS lTutarGBP,
|
||||
'USD' AS sDovizCinsi,
|
||||
0.0 AS lTutarDoviz,
|
||||
'' AS dteGuncellemeTarihi,
|
||||
RM.sGuncellemeKullaniciAdi,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(RM.nUrtReceteID, 0))) AS nUrtReceteID
|
||||
FROM RecipeMatch RM
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1
|
||||
ISNULL(F.sAciklama, '') AS FirmaAdi,
|
||||
ISNULL(SM.sVeren, '') AS SonIsEmriVeren,
|
||||
CONVERT(VARCHAR(16), SD.dteIslemTarihi, 120) AS dteIslemTarihi
|
||||
FROM dbo.spUrtSiparisDet SD
|
||||
INNER JOIN dbo.spUrtSiparis SM
|
||||
ON SM.nUrtSiparisID = SD.nUrtSiparisID
|
||||
LEFT JOIN dbo.tbFirma F
|
||||
ON F.nFirmaID = SM.nFirmaID
|
||||
WHERE SD.nUrtReceteID = RM.nUrtReceteID
|
||||
ORDER BY SD.dteIslemTarihi DESC, SD.nUrtSiparisID DESC
|
||||
) SonIsEmri
|
||||
`
|
||||
|
||||
return uretimDB.QueryRowContext(ctx, sqlText, recipeCode, productCode), nil
|
||||
}
|
||||
|
||||
func GetProductionNoCostDetailRowsByRecipeCode(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
recipeCode string,
|
||||
productCode string,
|
||||
) (*sql.Rows, error) {
|
||||
recipeCode = strings.TrimSpace(recipeCode)
|
||||
productCode = strings.TrimSpace(productCode)
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"query", "production-product-costing.no-cost-detail-rows",
|
||||
"recete_kodu", recipeCode,
|
||||
"urun_kodu", productCode,
|
||||
)
|
||||
logger.Info("query dispatch")
|
||||
|
||||
sqlText := `
|
||||
WITH RecipeMatch AS (
|
||||
SELECT TOP 1
|
||||
R.nUrtReceteID
|
||||
FROM dbo.spUrtRecete R
|
||||
WHERE LTRIM(RTRIM(ISNULL(R.sKodu, ''))) = @p1
|
||||
AND (@p2 = '' OR LTRIM(RTRIM(ISNULL(R.sMModelKodu, ''))) = @p2)
|
||||
ORDER BY
|
||||
R.dteIslemTarihi DESC,
|
||||
R.nUrtReceteID DESC
|
||||
),
|
||||
HammaddeTekil AS (
|
||||
SELECT
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(HT.sAciklama3)), ''), ISNULL(NULLIF(LTRIM(RTRIM(HT.sAciklama)), ''), N'TANIMSIZ')) AS sAciklama3,
|
||||
ISNULL(HT.nHammaddeTuruNo, 0) AS nHammaddeTuruNoSort,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(HT.nHammaddeTuruNo, 0))) AS nHammaddeTuruNo,
|
||||
-- Match URETIM's sp_pUrtOnMaliyetRecetedenKop behavior: use model code + color code instead of variant stock code.
|
||||
ISNULL(S.sModel, ISNULL(S.sKodu, '')) AS sKodu,
|
||||
ISNULL(S.sAciklama, '') AS sAciklama,
|
||||
ISNULL(S.sRenk, '') AS sRenk,
|
||||
ISNULL(HT.sAciklama, '') AS sHammaddeTuruAdi,
|
||||
ISNULL(S.sBirimCinsi1, '') AS sBirim,
|
||||
ISNULL(RMik.lHMiktar, 0) AS lMiktar,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY HT.nHammaddeTuruNo
|
||||
ORDER BY ISNULL(S.sModel, ISNULL(S.sKodu, ''))
|
||||
) AS rn,
|
||||
ROW_NUMBER() OVER (
|
||||
ORDER BY HT.nHammaddeTuruNo, ISNULL(S.sModel, ISNULL(S.sKodu, ''))
|
||||
) AS rowNo
|
||||
FROM RecipeMatch R
|
||||
INNER JOIN dbo.spUrtRecMBolumMik RMik
|
||||
ON RMik.nUrtReceteID = R.nUrtReceteID
|
||||
LEFT JOIN dbo.tbStok S
|
||||
ON S.nStokID = RMik.nHStokID
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1
|
||||
H.nHammaddeTuruNo,
|
||||
H.sAciklama,
|
||||
H.sAciklama3
|
||||
FROM dbo.spUrtOnMLHammaddeTuru H
|
||||
WHERE H.nUrtMBolumID = RMik.nUrtMBolumID
|
||||
ORDER BY
|
||||
CASE WHEN H.nUrtMTBolumID = RMik.nUrtMTBolumID THEN 0 ELSE 1 END,
|
||||
H.nHammaddeTuruNo
|
||||
) HT
|
||||
WHERE HT.nHammaddeTuruNo IS NOT NULL
|
||||
)
|
||||
SELECT
|
||||
HT.sAciklama3,
|
||||
0.0 AS GroupTotalTutar,
|
||||
0.0 AS GroupTotalUSDTutar,
|
||||
'' AS nOnMLNo,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(HT.rowNo, 0))) AS nOnMLDetNo,
|
||||
HT.nHammaddeTuruNo,
|
||||
HT.sKodu,
|
||||
HT.sAciklama,
|
||||
HT.sRenk AS sRenk,
|
||||
'' AS sBeden,
|
||||
'' AS sAciklama2,
|
||||
HT.lMiktar,
|
||||
0.0 AS lFiyat,
|
||||
0.0 AS lTutar,
|
||||
'' AS sFiyatTipi,
|
||||
'USD' AS sDovizCinsi,
|
||||
0.0 AS lDovizKuru,
|
||||
0.0 AS lDovizFiyati,
|
||||
NULL AS fiyat_girilen,
|
||||
'' AS fiyat_doviz,
|
||||
CAST(1 AS bit) AS maliyete_dahil,
|
||||
NULL AS cm_price_type_id,
|
||||
0.0 AS usdTutar,
|
||||
0.0 AS eurTutar,
|
||||
0.0 AS gbpTutar,
|
||||
HT.sBirim,
|
||||
HT.sHammaddeTuruAdi,
|
||||
HT.sHammaddeTuruAdi AS sParcaAdi
|
||||
FROM HammaddeTekil HT
|
||||
WHERE HT.rn = 1
|
||||
ORDER BY
|
||||
HT.nHammaddeTuruNoSort,
|
||||
HT.sKodu
|
||||
`
|
||||
|
||||
rows, err := uretimDB.QueryContext(ctx, sqlText, recipeCode, productCode)
|
||||
if err != nil {
|
||||
logger.Error("query error", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
func GetProductionTypes(ctx context.Context, uretimDB *sql.DB) (*sql.Rows, error) {
|
||||
sqlText := `SELECT id, aciklama FROM dbo.mk_uretim_sekli ORDER BY id`
|
||||
return uretimDB.QueryContext(ctx, sqlText)
|
||||
}
|
||||
|
||||
func GetProductionHasCostDetailHammaddeTypeOptions(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
search string,
|
||||
limit int,
|
||||
) (*sql.Rows, error) {
|
||||
search = strings.TrimSpace(search)
|
||||
if limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
searchLike := "%" + search + "%"
|
||||
|
||||
sqlText := `
|
||||
SELECT TOP (@p2)
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(T.nHammaddeTuruNo, 0))) AS nHammaddeTuruNo,
|
||||
ISNULL(T.sAciklama, '') AS sHammaddeTuruAdi,
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(T.sAciklama3)), ''), N'TANIMSIZ') AS sAciklama3
|
||||
FROM dbo.spUrtOnMLHammaddeTuru T
|
||||
WHERE
|
||||
ISNULL(T.bAktif, 0) = 1
|
||||
AND (
|
||||
@p1 = ''
|
||||
OR RTRIM(CONVERT(VARCHAR(32), ISNULL(T.nHammaddeTuruNo, 0))) LIKE @p3
|
||||
OR ISNULL(T.sAciklama, '') LIKE @p3
|
||||
OR ISNULL(T.sAciklama3, '') LIKE @p3
|
||||
)
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN @p1 <> '' AND RTRIM(CONVERT(VARCHAR(32), ISNULL(T.nHammaddeTuruNo, 0))) = @p1 THEN 0
|
||||
WHEN @p1 <> '' AND ISNULL(T.sAciklama, '') = @p1 THEN 1
|
||||
ELSE 2
|
||||
END,
|
||||
T.nHammaddeTuruNo
|
||||
`
|
||||
|
||||
return uretimDB.QueryContext(ctx, sqlText, search, limit, searchLike)
|
||||
}
|
||||
|
||||
func buildSQLServerFullTextPrefixQuery(search string) string {
|
||||
terms := strings.Fields(strings.TrimSpace(search))
|
||||
parts := make([]string, 0, len(terms))
|
||||
|
||||
for _, term := range terms {
|
||||
cleaned := strings.Map(func(r rune) rune {
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) {
|
||||
return r
|
||||
}
|
||||
return -1
|
||||
}, term)
|
||||
if len([]rune(cleaned)) < 2 {
|
||||
continue
|
||||
}
|
||||
parts = append(parts, fmt.Sprintf("\"%s*\"", cleaned))
|
||||
}
|
||||
|
||||
return strings.Join(parts, " AND ")
|
||||
}
|
||||
|
||||
func hasProductionHasCostDetailItemFullTextIndex(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
) bool {
|
||||
var exists int
|
||||
err := uretimDB.QueryRowContext(ctx, `
|
||||
SELECT CASE
|
||||
WHEN EXISTS (
|
||||
SELECT 1
|
||||
FROM sys.fulltext_indexes fi
|
||||
INNER JOIN sys.fulltext_index_columns fic
|
||||
ON fic.object_id = fi.object_id
|
||||
INNER JOIN sys.columns c
|
||||
ON c.object_id = fic.object_id
|
||||
AND c.column_id = fic.column_id
|
||||
WHERE fi.object_id = OBJECT_ID('dbo.tbStok')
|
||||
AND c.name = 'sAciklama'
|
||||
) THEN 1 ELSE 0
|
||||
END`).Scan(&exists)
|
||||
return err == nil && exists == 1
|
||||
}
|
||||
|
||||
func GetProductionHasCostDetailItemOptions(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
search string,
|
||||
limit int,
|
||||
) (*sql.Rows, error) {
|
||||
search = strings.TrimSpace(search)
|
||||
if limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
if search == "" {
|
||||
return uretimDB.QueryContext(ctx, `
|
||||
SELECT TOP (0)
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(S.nStokID, 0))) AS nStokID,
|
||||
LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sKodu, '')))) AS sKodu,
|
||||
LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sAciklama, '')))) AS sAciklama,
|
||||
LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sModel, '')))) AS sModel,
|
||||
LTRIM(RTRIM(CONVERT(NVARCHAR(64), ISNULL(S.sBirimCinsi1, '')))) AS sBirim
|
||||
FROM dbo.tbStok S`)
|
||||
}
|
||||
|
||||
searchExact := search
|
||||
searchPrefix := search + "%"
|
||||
searchLike := "%" + search + "%"
|
||||
searchLen := len([]rune(search))
|
||||
numericStokID, numericErr := strconv.Atoi(search)
|
||||
hasNumericStokID := numericErr == nil
|
||||
fullTextSearch := buildSQLServerFullTextPrefixQuery(search)
|
||||
useFullText := searchLen >= 3 && fullTextSearch != "" && hasProductionHasCostDetailItemFullTextIndex(ctx, uretimDB)
|
||||
|
||||
baseSelect := `
|
||||
SELECT TOP (@p2)
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(S.nStokID, 0))) AS nStokID,
|
||||
LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sKodu, '')))) AS sKodu,
|
||||
LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sAciklama, '')))) AS sAciklama,
|
||||
LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sModel, '')))) AS sModel,
|
||||
LTRIM(RTRIM(CONVERT(NVARCHAR(64), ISNULL(S.sBirimCinsi1, '')))) AS sBirim
|
||||
FROM dbo.tbStok S
|
||||
WHERE
|
||||
(ISNULL(S.IsBlocked, 0) = 0)
|
||||
AND S.sModel LIKE '_.%%'
|
||||
AND (
|
||||
(@p5 = 1 AND S.nStokID = @p6)
|
||||
OR S.sKodu = @p1
|
||||
OR S.sKodu LIKE @p3
|
||||
OR %s
|
||||
)
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN S.sKodu = @p1 THEN 0
|
||||
WHEN (@p5 = 1 AND S.nStokID = @p6) THEN 1
|
||||
WHEN S.sKodu LIKE @p3 THEN 2
|
||||
ELSE 3
|
||||
END,
|
||||
S.sKodu
|
||||
OPTION (RECOMPILE)
|
||||
`
|
||||
|
||||
if useFullText {
|
||||
sqlText := fmt.Sprintf(baseSelect, `CONTAINS(S.sAciklama, @p4)`)
|
||||
return uretimDB.QueryContext(ctx, sqlText, searchExact, limit, searchPrefix, fullTextSearch, hasNumericStokID, numericStokID)
|
||||
}
|
||||
|
||||
sqlText := fmt.Sprintf(baseSelect, `(@p4 >= 3 AND S.sAciklama LIKE @p7)`)
|
||||
return uretimDB.QueryContext(ctx, sqlText, searchExact, limit, searchPrefix, searchLen, hasNumericStokID, numericStokID, searchLike)
|
||||
}
|
||||
|
||||
func GetProductionHasCostDetailColorOptions(
|
||||
ctx context.Context,
|
||||
mssqlDB *sql.DB,
|
||||
modelCode string,
|
||||
search string,
|
||||
limit int,
|
||||
) (*sql.Rows, error) {
|
||||
modelCode = strings.TrimSpace(modelCode)
|
||||
search = strings.TrimSpace(search)
|
||||
if limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
searchLike := "%" + search + "%"
|
||||
|
||||
sqlText := `
|
||||
WITH ColorSource AS (
|
||||
SELECT DISTINCT
|
||||
LTRIM(RTRIM(CONVERT(NVARCHAR(64), ISNULL(T.sRenk, '')))) AS ColorCode
|
||||
FROM dbo.tbStok T
|
||||
WHERE ISNULL(T.IsBlocked, 0) = 0
|
||||
AND LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(T.sModel, '')))) = @p1
|
||||
AND LTRIM(RTRIM(CONVERT(NVARCHAR(64), ISNULL(T.sRenk, '')))) <> ''
|
||||
)
|
||||
SELECT TOP (@p2)
|
||||
LTRIM(RTRIM(ISNULL(S.ColorCode, ''))) AS colorCode,
|
||||
ISNULL(C.ColorDescription, '') AS colorDescription
|
||||
FROM (
|
||||
SELECT ColorCode
|
||||
FROM ColorSource
|
||||
) S
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ColorDescription
|
||||
FROM dbo.cdColorDesc CD
|
||||
WHERE CD.LangCode = 'TR'
|
||||
AND LTRIM(RTRIM(ISNULL(CD.ColorCode, ''))) = S.ColorCode
|
||||
) C
|
||||
WHERE @p1 <> ''
|
||||
AND (
|
||||
@p3 = ''
|
||||
OR LTRIM(RTRIM(ISNULL(S.ColorCode, ''))) LIKE @p4
|
||||
OR ISNULL(C.ColorDescription, '') LIKE @p4
|
||||
)
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN @p3 <> '' AND LTRIM(RTRIM(ISNULL(S.ColorCode, ''))) = @p3 THEN 0
|
||||
WHEN @p3 <> '' AND ISNULL(C.ColorDescription, '') = @p3 THEN 1
|
||||
ELSE 2
|
||||
END,
|
||||
LTRIM(RTRIM(ISNULL(S.ColorCode, '')))
|
||||
`
|
||||
|
||||
return mssqlDB.QueryContext(ctx, sqlText, modelCode, limit, search, searchLike)
|
||||
}
|
||||
|
||||
func GetProductionHasCostDetailExchangeRatesByDate(
|
||||
ctx context.Context,
|
||||
mssqlDB *sql.DB,
|
||||
costDate string,
|
||||
) (*sql.Row, error) {
|
||||
costDate = strings.TrimSpace(costDate)
|
||||
|
||||
sqlText := `
|
||||
DECLARE @targetDate date = ISNULL(CONVERT(date, NULLIF(@p1, ''), 23), CONVERT(date, GETDATE()))
|
||||
|
||||
SELECT
|
||||
CONVERT(VARCHAR(10), @targetDate, 23) AS rateDate,
|
||||
ISNULL((
|
||||
SELECT TOP 1 Rate
|
||||
FROM dbo.AllExchangeRates
|
||||
WHERE CurrencyCode = 'USD'
|
||||
AND RelationCurrencyCode = 'TRY'
|
||||
AND ExchangeTypeCode = 6
|
||||
AND Rate > 0
|
||||
AND CONVERT(date, [Date]) <= @targetDate
|
||||
ORDER BY
|
||||
CASE WHEN CONVERT(date, [Date]) = @targetDate THEN 0 ELSE 1 END,
|
||||
[Date] DESC
|
||||
), 0) AS usdRate,
|
||||
ISNULL((
|
||||
SELECT TOP 1 Rate
|
||||
FROM dbo.AllExchangeRates
|
||||
WHERE CurrencyCode = 'EUR'
|
||||
AND RelationCurrencyCode = 'TRY'
|
||||
AND ExchangeTypeCode = 6
|
||||
AND Rate > 0
|
||||
AND CONVERT(date, [Date]) <= @targetDate
|
||||
ORDER BY
|
||||
CASE WHEN CONVERT(date, [Date]) = @targetDate THEN 0 ELSE 1 END,
|
||||
[Date] DESC
|
||||
), 0) AS eurRate,
|
||||
ISNULL((
|
||||
SELECT TOP 1 Rate
|
||||
FROM dbo.AllExchangeRates
|
||||
WHERE CurrencyCode = 'GBP'
|
||||
AND RelationCurrencyCode = 'TRY'
|
||||
AND ExchangeTypeCode = 6
|
||||
AND Rate > 0
|
||||
AND CONVERT(date, [Date]) <= @targetDate
|
||||
ORDER BY
|
||||
CASE WHEN CONVERT(date, [Date]) = @targetDate THEN 0 ELSE 1 END,
|
||||
[Date] DESC
|
||||
), 0) AS gbpRate
|
||||
`
|
||||
|
||||
return mssqlDB.QueryRowContext(ctx, sqlText, costDate), nil
|
||||
}
|
||||
|
||||
func GetProductionHasCostLatestPurchasePriceForItem(
|
||||
ctx context.Context,
|
||||
mssqlDB *sql.DB,
|
||||
sKodu string,
|
||||
colorCode string,
|
||||
itemDim1Code string,
|
||||
costDate string,
|
||||
) (*sql.Row, error) {
|
||||
sKodu = strings.TrimSpace(sKodu)
|
||||
colorCode = strings.TrimSpace(colorCode)
|
||||
itemDim1Code = strings.TrimSpace(itemDim1Code)
|
||||
costDate = strings.TrimSpace(costDate)
|
||||
|
||||
sqlText := `
|
||||
WITH BASE AS (
|
||||
SELECT
|
||||
A.InvoiceDate,
|
||||
A.InvoiceNumber,
|
||||
A.ProcessCode,
|
||||
A.CurrAccTypeCode,
|
||||
A.CurrAccCode,
|
||||
A.ItemTypeCode,
|
||||
A.ItemCode,
|
||||
A.ColorCode,
|
||||
A.ItemDim1Code,
|
||||
A.Qty1,
|
||||
A.Doc_Price,
|
||||
A.Doc_Amount,
|
||||
A.Doc_CurrencyCode
|
||||
FROM AllInvoicesWithAttributes A
|
||||
WHERE A.ProcessCode IN ('BP')
|
||||
AND A.ATAtt01 IN (1, 2)
|
||||
AND A.CompanyCode IN (1, 2, 5)
|
||||
AND A.IsCompleted = 1
|
||||
AND YEAR(A.InvoiceDate) >= 2022
|
||||
AND LTRIM(RTRIM(A.ItemCode)) = @p1
|
||||
AND (NULLIF(@p2, '') IS NULL OR CONVERT(date, A.InvoiceDate) < CONVERT(date, NULLIF(@p2, ''), 23))
|
||||
)
|
||||
SELECT TOP 1
|
||||
'MAN' AS priceType,
|
||||
CONVERT(VARCHAR(16), B.InvoiceDate, 120) AS Tarih,
|
||||
ISNULL(B.InvoiceNumber, '') AS FaturaKodu,
|
||||
LTRIM(RTRIM(ISNULL(B.ItemCode, ''))) AS MasrafKodu,
|
||||
ISNULL(ID.ItemDescription, '') AS MasrafDetay,
|
||||
ISNULL(B.ColorCode, '') AS ColorCode,
|
||||
ISNULL(COL.ColorDescription, '') AS ColorDescription,
|
||||
ISNULL(B.ItemDim1Code, '') AS ItemDim1Code,
|
||||
ISNULL(DIM1.ItemDim1Description, '') AS ItemDim1Description,
|
||||
ISNULL(B.Doc_Price, 0) AS EvrakFiyat,
|
||||
ISNULL(B.Doc_CurrencyCode, '') AS EvrakDoviz
|
||||
FROM BASE B
|
||||
LEFT JOIN cdItem CI
|
||||
ON CI.ItemTypeCode = B.ItemTypeCode
|
||||
AND CI.ItemCode = B.ItemCode
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ItemDescription
|
||||
FROM cdItemDesc
|
||||
WHERE ItemTypeCode = B.ItemTypeCode
|
||||
AND ItemCode = B.ItemCode
|
||||
AND LangCode = 'TR'
|
||||
) ID
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ItemDim1Description
|
||||
FROM cdItemDim1Desc
|
||||
WHERE ItemDim1Code = B.ItemDim1Code
|
||||
AND LangCode = 'TR'
|
||||
) DIM1
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ColorDescription
|
||||
FROM cdColorDesc
|
||||
WHERE ColorCode = B.ColorCode
|
||||
AND LangCode = 'TR'
|
||||
) COL
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN @p3 <> '' AND LTRIM(RTRIM(ISNULL(B.ColorCode, ''))) = @p3 THEN 0
|
||||
WHEN @p3 = '' THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
CASE
|
||||
WHEN @p4 <> '' AND LTRIM(RTRIM(ISNULL(B.ItemDim1Code, ''))) = @p4 THEN 0
|
||||
WHEN @p4 = '' THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
B.InvoiceDate DESC,
|
||||
B.InvoiceNumber DESC
|
||||
`
|
||||
|
||||
return mssqlDB.QueryRowContext(ctx, sqlText, sKodu, costDate, colorCode, itemDim1Code), nil
|
||||
}
|
||||
|
||||
func GetProductionHasCostPurchaseHistoryByExpenseCode(
|
||||
ctx context.Context,
|
||||
mssqlDB *sql.DB,
|
||||
sKodu string,
|
||||
costDate string,
|
||||
limit int,
|
||||
) (*sql.Rows, error) {
|
||||
sKodu = strings.TrimSpace(sKodu)
|
||||
costDate = strings.TrimSpace(costDate)
|
||||
if limit <= 0 {
|
||||
limit = 250
|
||||
}
|
||||
|
||||
sqlText := `
|
||||
WITH BASE AS (
|
||||
SELECT
|
||||
A.InvoiceDate,
|
||||
A.InvoiceNumber,
|
||||
A.ProcessCode,
|
||||
A.CurrAccTypeCode,
|
||||
A.CurrAccCode,
|
||||
A.ItemTypeCode,
|
||||
A.ItemCode,
|
||||
A.ColorCode,
|
||||
A.ItemDim1Code,
|
||||
A.Qty1,
|
||||
A.Doc_Price,
|
||||
A.Doc_Amount,
|
||||
A.Doc_CurrencyCode
|
||||
FROM AllInvoicesWithAttributes A
|
||||
WHERE A.ProcessCode IN ('BP')
|
||||
AND A.ATAtt01 IN (1, 2)
|
||||
AND A.CompanyCode IN (1, 2, 5)
|
||||
AND A.IsCompleted = 1
|
||||
AND YEAR(A.InvoiceDate) >= 2022
|
||||
AND LTRIM(RTRIM(A.ItemCode)) = @p1
|
||||
AND (ISNULL(A.Doc_Price, 0) > 0 OR ISNULL(A.Doc_Amount, 0) > 0)
|
||||
AND (NULLIF(@p2, '') IS NULL OR CONVERT(date, A.InvoiceDate) < CONVERT(date, NULLIF(@p2, ''), 23))
|
||||
)
|
||||
SELECT TOP (@p3)
|
||||
'purchase' AS sourceType,
|
||||
'MAN' AS priceType,
|
||||
CONVERT(VARCHAR(16), B.InvoiceDate, 120) AS Tarih,
|
||||
ISNULL(B.InvoiceNumber, '') AS FaturaKodu,
|
||||
ISNULL(B.CurrAccCode, '') AS FirmaKodu,
|
||||
ISNULL(CAD.CurrAccDescription, '') AS FirmaAciklama,
|
||||
LTRIM(RTRIM(ISNULL(B.ItemCode, ''))) AS MasrafKodu,
|
||||
ISNULL(ID.ItemDescription, '') AS MasrafDetay,
|
||||
ISNULL(B.ColorCode, '') AS ColorCode,
|
||||
ISNULL(COL.ColorDescription, '') AS ColorDescription,
|
||||
ISNULL(B.ItemDim1Code, '') AS ItemDim1Code,
|
||||
ISNULL(DIM1.ItemDim1Description, '') AS ItemDim1Description,
|
||||
ISNULL(B.Qty1, 0) AS Miktar,
|
||||
CASE
|
||||
WHEN B.ProcessCode = 'EP' THEN ''
|
||||
ELSE ISNULL(CI.UnitOfMeasureCode1, '')
|
||||
END AS BIRIM,
|
||||
ISNULL(B.Doc_Price, 0) AS EvrakFiyat,
|
||||
ISNULL(B.Doc_Amount, 0) AS EvrakTutar,
|
||||
ISNULL(B.Doc_CurrencyCode, '') AS EvrakDoviz
|
||||
FROM BASE B
|
||||
LEFT JOIN cdItem CI
|
||||
ON CI.ItemTypeCode = B.ItemTypeCode
|
||||
AND CI.ItemCode = B.ItemCode
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ItemDescription
|
||||
FROM cdItemDesc
|
||||
WHERE ItemTypeCode = B.ItemTypeCode
|
||||
AND ItemCode = B.ItemCode
|
||||
AND LangCode = 'TR'
|
||||
) ID
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ItemDim1Description
|
||||
FROM cdItemDim1Desc
|
||||
WHERE ItemDim1Code = B.ItemDim1Code
|
||||
AND LangCode = 'TR'
|
||||
) DIM1
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ColorDescription
|
||||
FROM cdColorDesc
|
||||
WHERE ColorCode = B.ColorCode
|
||||
AND LangCode = 'TR'
|
||||
) COL
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 CurrAccDescription
|
||||
FROM cdCurrAccDesc
|
||||
WHERE CurrAccTypeCode = B.CurrAccTypeCode
|
||||
AND CurrAccCode = B.CurrAccCode
|
||||
AND LangCode = 'TR'
|
||||
) CAD
|
||||
ORDER BY
|
||||
B.InvoiceDate DESC,
|
||||
B.InvoiceNumber DESC
|
||||
`
|
||||
|
||||
return mssqlDB.QueryContext(ctx, sqlText, sKodu, costDate, limit)
|
||||
}
|
||||
|
||||
func GetProductionHasCostRecipeHistoryByExpenseCode(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
currentOnMLNo int,
|
||||
sKodu string,
|
||||
colorCode string,
|
||||
costDate string,
|
||||
limit int,
|
||||
) (*sql.Rows, error) {
|
||||
sKodu = strings.TrimSpace(sKodu)
|
||||
colorCode = strings.TrimSpace(colorCode)
|
||||
costDate = strings.TrimSpace(costDate)
|
||||
if limit <= 0 {
|
||||
limit = 250
|
||||
}
|
||||
|
||||
sqlText := `
|
||||
SELECT TOP (@p5)
|
||||
'recipe' AS sourceType,
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(D.sFiyatTipi)), ''), 'SAF') AS priceType,
|
||||
CONVERT(VARCHAR(16), COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi), 120) AS dteIslemTarihi,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(D.nOnMLNo, 0))) AS nOnMLNo,
|
||||
ISNULL(UF.FirmaKodu, '') AS FirmaKodu,
|
||||
ISNULL(UF.FirmaAciklama, '') AS FirmaAciklama,
|
||||
ISNULL(D.sKodu, '') AS sKodu,
|
||||
ISNULL(D.sAciklama, '') AS sAciklama,
|
||||
ISNULL(D.sRenk, '') AS sRenk,
|
||||
ISNULL(D.lMiktar, 0) AS lMiktar,
|
||||
ISNULL(D.sBirim, '') AS sBirim,
|
||||
CASE
|
||||
WHEN ISNULL(D.fiyat_girilen, 0) > 0 THEN ISNULL(D.fiyat_girilen, 0)
|
||||
ELSE ISNULL(D.lDovizFiyati, 0)
|
||||
END AS lDovizFiyati,
|
||||
CASE
|
||||
WHEN ISNULL(D.lDovizTutari, 0) > 0 THEN ISNULL(D.lDovizTutari, 0)
|
||||
WHEN ISNULL(D.fiyat_girilen, 0) > 0 THEN ISNULL(D.fiyat_girilen, 0) * ISNULL(D.lMiktar, 0)
|
||||
ELSE ISNULL(D.lDovizFiyati, 0) * ISNULL(D.lMiktar, 0)
|
||||
END AS lDovizTutari,
|
||||
CASE
|
||||
WHEN LTRIM(RTRIM(ISNULL(D.fiyat_doviz, ''))) <> '' THEN LTRIM(RTRIM(D.fiyat_doviz))
|
||||
WHEN LTRIM(RTRIM(ISNULL(D.sDovizCinsi, ''))) <> '' THEN LTRIM(RTRIM(D.sDovizCinsi))
|
||||
WHEN LTRIM(RTRIM(ISNULL(M.sDovizCinsi, ''))) <> '' THEN LTRIM(RTRIM(M.sDovizCinsi))
|
||||
ELSE 'USD'
|
||||
END AS USD,
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(T.sAciklama3)), ''), N'DUMMY') AS DUMMY
|
||||
FROM dbo.spUrtOnMLMasDet D
|
||||
INNER JOIN dbo.spUrtOnMLMas M
|
||||
ON M.nOnMLNo = D.nOnMLNo
|
||||
LEFT JOIN dbo.spUrtOnMLHammaddeTuru T
|
||||
ON T.nHammaddeTuruNo = D.nHammaddeTuruNo
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1
|
||||
ISNULL(F.sKodu, '') AS FirmaKodu,
|
||||
ISNULL(F.sAciklama, '') AS FirmaAciklama
|
||||
FROM dbo.spUrtSiparisDet SD
|
||||
INNER JOIN dbo.spUrtSiparis SM
|
||||
ON SM.nUrtSiparisID = SD.nUrtSiparisID
|
||||
LEFT JOIN dbo.tbFirma F
|
||||
ON F.nFirmaID = SM.nFirmaID
|
||||
WHERE (
|
||||
(ISNULL(M.nUrtReceteID, 0) > 0 AND SD.nUrtReceteID = M.nUrtReceteID)
|
||||
OR (ISNULL(M.nUrtReceteID, 0) <= 0 AND LTRIM(RTRIM(ISNULL(SD.sMModelKodu, ''))) = LTRIM(RTRIM(ISNULL(M.UrunKodu, ''))))
|
||||
)
|
||||
AND SD.dteIslemTarihi <= COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi)
|
||||
ORDER BY SD.dteIslemTarihi DESC, SD.nUrtSiparisID DESC
|
||||
) UF
|
||||
WHERE LTRIM(RTRIM(D.sKodu)) = @p1
|
||||
AND (@p2 <= 0 OR D.nOnMLNo <> @p2)
|
||||
AND (
|
||||
ISNULL(D.fiyat_girilen, 0) > 0
|
||||
OR ISNULL(D.lDovizFiyati, 0) > 0
|
||||
OR ISNULL(D.lDovizTutari, 0) > 0
|
||||
)
|
||||
AND (
|
||||
NULLIF(@p3, '') IS NULL
|
||||
OR CONVERT(date, COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi)) < CONVERT(date, NULLIF(@p3, ''), 23)
|
||||
)
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN @p4 <> '' AND LTRIM(RTRIM(ISNULL(D.sRenk, ''))) = @p4 THEN 0
|
||||
WHEN @p4 = '' THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi) DESC,
|
||||
D.nOnMLNo DESC,
|
||||
D.nOnMLDetNo DESC
|
||||
`
|
||||
|
||||
return uretimDB.QueryContext(ctx, sqlText, sKodu, currentOnMLNo, costDate, colorCode, limit)
|
||||
}
|
||||
|
||||
func BuildProductionHasCostSimilarCodePrefix(sKodu string) string {
|
||||
normalizedCode := strings.ToUpper(strings.TrimSpace(sKodu))
|
||||
if normalizedCode == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
runes := []rune(normalizedCode)
|
||||
if len(runes) <= 4 {
|
||||
return normalizedCode
|
||||
}
|
||||
if len(runes) >= 5 && len(runes) > 1 && runes[1] == '.' {
|
||||
return string(runes[:5])
|
||||
}
|
||||
|
||||
return string(runes[:4])
|
||||
}
|
||||
|
||||
func GetProductionHasCostPurchaseHistoryByCodePrefix(
|
||||
ctx context.Context,
|
||||
mssqlDB *sql.DB,
|
||||
sKoduPrefix string,
|
||||
costDate string,
|
||||
limit int,
|
||||
) (*sql.Rows, error) {
|
||||
sKoduPrefix = strings.TrimSpace(sKoduPrefix)
|
||||
costDate = strings.TrimSpace(costDate)
|
||||
if limit <= 0 {
|
||||
limit = 250
|
||||
}
|
||||
|
||||
sqlText := `
|
||||
WITH BASE AS (
|
||||
SELECT
|
||||
A.InvoiceDate,
|
||||
A.InvoiceNumber,
|
||||
A.ProcessCode,
|
||||
A.CurrAccTypeCode,
|
||||
A.CurrAccCode,
|
||||
A.ItemTypeCode,
|
||||
A.ItemCode,
|
||||
A.ColorCode,
|
||||
A.ItemDim1Code,
|
||||
A.Qty1,
|
||||
A.Doc_Price,
|
||||
A.Doc_Amount,
|
||||
A.Doc_CurrencyCode
|
||||
FROM AllInvoicesWithAttributes A
|
||||
WHERE A.ProcessCode IN ('BP')
|
||||
AND A.ATAtt01 IN (1, 2)
|
||||
AND A.CompanyCode IN (1, 2, 5)
|
||||
AND A.IsCompleted = 1
|
||||
AND YEAR(A.InvoiceDate) >= 2022
|
||||
AND NULLIF(@p1, '') IS NOT NULL
|
||||
AND LTRIM(RTRIM(A.ItemCode)) LIKE @p1 + '%'
|
||||
AND (ISNULL(A.Doc_Price, 0) > 0 OR ISNULL(A.Doc_Amount, 0) > 0)
|
||||
AND (NULLIF(@p2, '') IS NULL OR CONVERT(date, A.InvoiceDate) < CONVERT(date, NULLIF(@p2, ''), 23))
|
||||
)
|
||||
SELECT TOP (@p3)
|
||||
'purchase' AS sourceType,
|
||||
'BNZ' AS priceType,
|
||||
CONVERT(VARCHAR(16), B.InvoiceDate, 120) AS Tarih,
|
||||
ISNULL(B.InvoiceNumber, '') AS FaturaKodu,
|
||||
ISNULL(B.CurrAccCode, '') AS FirmaKodu,
|
||||
ISNULL(CAD.CurrAccDescription, '') AS FirmaAciklama,
|
||||
LTRIM(RTRIM(ISNULL(B.ItemCode, ''))) AS MasrafKodu,
|
||||
ISNULL(ID.ItemDescription, '') AS MasrafDetay,
|
||||
ISNULL(B.ColorCode, '') AS ColorCode,
|
||||
ISNULL(COL.ColorDescription, '') AS ColorDescription,
|
||||
ISNULL(B.ItemDim1Code, '') AS ItemDim1Code,
|
||||
ISNULL(DIM1.ItemDim1Description, '') AS ItemDim1Description,
|
||||
ISNULL(B.Qty1, 0) AS Miktar,
|
||||
CASE
|
||||
WHEN B.ProcessCode = 'EP' THEN ''
|
||||
ELSE ISNULL(CI.UnitOfMeasureCode1, '')
|
||||
END AS BIRIM,
|
||||
ISNULL(B.Doc_Price, 0) AS EvrakFiyat,
|
||||
ISNULL(B.Doc_Amount, 0) AS EvrakTutar,
|
||||
ISNULL(B.Doc_CurrencyCode, '') AS EvrakDoviz
|
||||
FROM BASE B
|
||||
LEFT JOIN cdItem CI
|
||||
ON CI.ItemTypeCode = B.ItemTypeCode
|
||||
AND CI.ItemCode = B.ItemCode
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ItemDescription
|
||||
FROM cdItemDesc
|
||||
WHERE ItemTypeCode = B.ItemTypeCode
|
||||
AND ItemCode = B.ItemCode
|
||||
AND LangCode = 'TR'
|
||||
) ID
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ItemDim1Description
|
||||
FROM cdItemDim1Desc
|
||||
WHERE ItemDim1Code = B.ItemDim1Code
|
||||
AND LangCode = 'TR'
|
||||
) DIM1
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ColorDescription
|
||||
FROM cdColorDesc
|
||||
WHERE ColorCode = B.ColorCode
|
||||
AND LangCode = 'TR'
|
||||
) COL
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 CurrAccDescription
|
||||
FROM cdCurrAccDesc
|
||||
WHERE CurrAccTypeCode = B.CurrAccTypeCode
|
||||
AND CurrAccCode = B.CurrAccCode
|
||||
AND LangCode = 'TR'
|
||||
) CAD
|
||||
ORDER BY
|
||||
B.InvoiceDate DESC,
|
||||
B.InvoiceNumber DESC
|
||||
`
|
||||
|
||||
return mssqlDB.QueryContext(ctx, sqlText, sKoduPrefix, costDate, limit)
|
||||
}
|
||||
|
||||
func GetProductionHasCostOnMLHistoryByCodePrefix(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
sKoduPrefix string,
|
||||
costDate string,
|
||||
limit int,
|
||||
) (*sql.Rows, error) {
|
||||
sKoduPrefix = strings.TrimSpace(sKoduPrefix)
|
||||
costDate = strings.TrimSpace(costDate)
|
||||
if limit <= 0 {
|
||||
limit = 250
|
||||
}
|
||||
|
||||
sqlText := `
|
||||
SELECT TOP (@p3)
|
||||
'recipe' AS sourceType,
|
||||
'BNZ' AS priceType,
|
||||
CONVERT(VARCHAR(16), COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi), 120) AS dteIslemTarihi,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(D.nOnMLNo, 0))) AS nOnMLNo,
|
||||
ISNULL(UF.FirmaKodu, '') AS FirmaKodu,
|
||||
ISNULL(UF.FirmaAciklama, '') AS FirmaAciklama,
|
||||
ISNULL(D.sKodu, '') AS sKodu,
|
||||
ISNULL(D.sAciklama, '') AS sAciklama,
|
||||
ISNULL(D.sRenk, '') AS sRenk,
|
||||
ISNULL(D.lMiktar, 0) AS lMiktar,
|
||||
ISNULL(D.sBirim, '') AS sBirim,
|
||||
CASE
|
||||
WHEN ISNULL(D.fiyat_girilen, 0) > 0 THEN ISNULL(D.fiyat_girilen, 0)
|
||||
ELSE ISNULL(D.lDovizFiyati, 0)
|
||||
END AS lDovizFiyati,
|
||||
CASE
|
||||
WHEN ISNULL(D.lDovizTutari, 0) > 0 THEN ISNULL(D.lDovizTutari, 0)
|
||||
WHEN ISNULL(D.fiyat_girilen, 0) > 0 THEN ISNULL(D.fiyat_girilen, 0) * ISNULL(D.lMiktar, 0)
|
||||
ELSE ISNULL(D.lDovizFiyati, 0) * ISNULL(D.lMiktar, 0)
|
||||
END AS lDovizTutari,
|
||||
CASE
|
||||
WHEN LTRIM(RTRIM(ISNULL(D.fiyat_doviz, ''))) <> '' THEN LTRIM(RTRIM(D.fiyat_doviz))
|
||||
WHEN LTRIM(RTRIM(ISNULL(D.sDovizCinsi, ''))) <> '' THEN LTRIM(RTRIM(D.sDovizCinsi))
|
||||
WHEN LTRIM(RTRIM(ISNULL(M.sDovizCinsi, ''))) <> '' THEN LTRIM(RTRIM(M.sDovizCinsi))
|
||||
ELSE 'USD'
|
||||
END AS USD,
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(D.sAciklama3)), ''), N'DUMMY') AS DUMMY
|
||||
FROM dbo.spUrtOnMLMasDet D
|
||||
INNER JOIN dbo.spUrtOnMLMas M
|
||||
ON M.nOnMLNo = D.nOnMLNo
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1
|
||||
ISNULL(F.sKodu, '') AS FirmaKodu,
|
||||
ISNULL(F.sAciklama, '') AS FirmaAciklama
|
||||
FROM dbo.spUrtSiparisDet SD
|
||||
INNER JOIN dbo.spUrtSiparis SM
|
||||
ON SM.nUrtSiparisID = SD.nUrtSiparisID
|
||||
LEFT JOIN dbo.tbFirma F
|
||||
ON F.nFirmaID = SM.nFirmaID
|
||||
WHERE (
|
||||
(ISNULL(M.nUrtReceteID, 0) > 0 AND SD.nUrtReceteID = M.nUrtReceteID)
|
||||
OR (ISNULL(M.nUrtReceteID, 0) <= 0 AND LTRIM(RTRIM(ISNULL(SD.sMModelKodu, ''))) = LTRIM(RTRIM(ISNULL(M.UrunKodu, ''))))
|
||||
)
|
||||
AND SD.dteIslemTarihi <= COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi)
|
||||
ORDER BY SD.dteIslemTarihi DESC, SD.nUrtSiparisID DESC
|
||||
) UF
|
||||
WHERE NULLIF(@p1, '') IS NOT NULL
|
||||
AND LTRIM(RTRIM(ISNULL(D.sKodu, ''))) LIKE @p1 + '%'
|
||||
AND (
|
||||
ISNULL(D.fiyat_girilen, 0) > 0
|
||||
OR ISNULL(D.lDovizFiyati, 0) > 0
|
||||
OR ISNULL(D.lDovizTutari, 0) > 0
|
||||
)
|
||||
AND (
|
||||
NULLIF(@p2, '') IS NULL
|
||||
OR CONVERT(date, COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi)) < CONVERT(date, NULLIF(@p2, ''), 23)
|
||||
)
|
||||
ORDER BY
|
||||
COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi) DESC,
|
||||
D.nOnMLNo DESC,
|
||||
D.nOnMLDetNo DESC
|
||||
`
|
||||
|
||||
return uretimDB.QueryContext(ctx, sqlText, sKoduPrefix, costDate, limit)
|
||||
}
|
||||
|
||||
func GetProductionHasCostOnMLHistoryByHammaddeTuruNo(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
nHammaddeTuruNo string,
|
||||
costDate string,
|
||||
limit int,
|
||||
) (*sql.Rows, error) {
|
||||
nHammaddeTuruNo = strings.TrimSpace(nHammaddeTuruNo)
|
||||
costDate = strings.TrimSpace(costDate)
|
||||
if limit <= 0 {
|
||||
limit = 250
|
||||
}
|
||||
|
||||
sqlText := `
|
||||
SELECT TOP (@p3)
|
||||
'recipe' AS sourceType,
|
||||
'BNZ' AS priceType,
|
||||
CONVERT(VARCHAR(16), COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi), 120) AS dteIslemTarihi,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(D.nOnMLNo, 0))) AS nOnMLNo,
|
||||
ISNULL(UF.FirmaKodu, '') AS FirmaKodu,
|
||||
ISNULL(UF.FirmaAciklama, '') AS FirmaAciklama,
|
||||
ISNULL(D.sKodu, '') AS sKodu,
|
||||
ISNULL(D.sAciklama, '') AS sAciklama,
|
||||
ISNULL(D.sRenk, '') AS sRenk,
|
||||
ISNULL(D.lMiktar, 0) AS lMiktar,
|
||||
ISNULL(D.sBirim, '') AS sBirim,
|
||||
CASE
|
||||
WHEN ISNULL(D.fiyat_girilen, 0) > 0 THEN ISNULL(D.fiyat_girilen, 0)
|
||||
ELSE ISNULL(D.lDovizFiyati, 0)
|
||||
END AS lDovizFiyati,
|
||||
CASE
|
||||
WHEN ISNULL(D.lDovizTutari, 0) > 0 THEN ISNULL(D.lDovizTutari, 0)
|
||||
WHEN ISNULL(D.fiyat_girilen, 0) > 0 THEN ISNULL(D.fiyat_girilen, 0) * ISNULL(D.lMiktar, 0)
|
||||
ELSE ISNULL(D.lDovizFiyati, 0) * ISNULL(D.lMiktar, 0)
|
||||
END AS lDovizTutari,
|
||||
CASE
|
||||
WHEN LTRIM(RTRIM(ISNULL(D.fiyat_doviz, ''))) <> '' THEN LTRIM(RTRIM(D.fiyat_doviz))
|
||||
WHEN LTRIM(RTRIM(ISNULL(D.sDovizCinsi, ''))) <> '' THEN LTRIM(RTRIM(D.sDovizCinsi))
|
||||
WHEN LTRIM(RTRIM(ISNULL(M.sDovizCinsi, ''))) <> '' THEN LTRIM(RTRIM(M.sDovizCinsi))
|
||||
ELSE 'USD'
|
||||
END AS USD,
|
||||
ISNULL(NULLIF(LTRIM(RTRIM(D.sAciklama3)), ''), N'DUMMY') AS DUMMY
|
||||
FROM dbo.spUrtOnMLMasDet D
|
||||
INNER JOIN dbo.spUrtOnMLMas M
|
||||
ON M.nOnMLNo = D.nOnMLNo
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1
|
||||
ISNULL(F.sKodu, '') AS FirmaKodu,
|
||||
ISNULL(F.sAciklama, '') AS FirmaAciklama
|
||||
FROM dbo.spUrtSiparisDet SD
|
||||
INNER JOIN dbo.spUrtSiparis SM
|
||||
ON SM.nUrtSiparisID = SD.nUrtSiparisID
|
||||
LEFT JOIN dbo.tbFirma F
|
||||
ON F.nFirmaID = SM.nFirmaID
|
||||
WHERE (
|
||||
(ISNULL(M.nUrtReceteID, 0) > 0 AND SD.nUrtReceteID = M.nUrtReceteID)
|
||||
OR (ISNULL(M.nUrtReceteID, 0) <= 0 AND LTRIM(RTRIM(ISNULL(SD.sMModelKodu, ''))) = LTRIM(RTRIM(ISNULL(M.UrunKodu, ''))))
|
||||
)
|
||||
AND SD.dteIslemTarihi <= COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi)
|
||||
ORDER BY SD.dteIslemTarihi DESC, SD.nUrtSiparisID DESC
|
||||
) UF
|
||||
WHERE D.nHammaddeTuruNo = @p1
|
||||
AND ISNULL(D.fiyat_girilen, 0) > 0
|
||||
AND (
|
||||
NULLIF(@p2, '') IS NULL
|
||||
OR CONVERT(date, COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi)) < CONVERT(date, NULLIF(@p2, ''), 23)
|
||||
)
|
||||
ORDER BY
|
||||
COALESCE(D.dteIslemTarihiDeg, D.dteIslemTarihi, M.Tarihi, M.dteKayitTarihi) DESC,
|
||||
D.nOnMLNo DESC,
|
||||
D.nOnMLDetNo DESC
|
||||
`
|
||||
|
||||
return uretimDB.QueryContext(ctx, sqlText, nHammaddeTuruNo, costDate, limit)
|
||||
}
|
||||
|
||||
func GetProductionHasCostSimilarItemHistory(
|
||||
ctx context.Context,
|
||||
mssqlDB *sql.DB,
|
||||
uretimDB *sql.DB,
|
||||
nHammaddeTuruNo string,
|
||||
costDate string,
|
||||
limit int,
|
||||
) ([]any, error) {
|
||||
if limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
|
||||
// 1. Satinalma (V3) tarafini sorgula - Simdilik V3 tarafi icin hammadde turu eslestirmesi belirsiz oldugundan pasif
|
||||
/*
|
||||
v3Sql := `
|
||||
SELECT TOP (@p2)
|
||||
'purchase' AS sourceType,
|
||||
'BNZ' AS priceType,
|
||||
CONVERT(VARCHAR(16), A.InvoiceDate, 120) AS Tarih,
|
||||
ISNULL(A.InvoiceNumber, '') AS FaturaKodu,
|
||||
LTRIM(RTRIM(ISNULL(A.ItemCode, ''))) AS MasrafKodu,
|
||||
ISNULL(ID.ItemDescription, '') AS MasrafDetay,
|
||||
ISNULL(A.ColorCode, '') AS ColorCode,
|
||||
ISNULL(A.Qty1, 0) AS Miktar,
|
||||
ISNULL(CI.UnitOfMeasureCode1, '') AS BIRIM,
|
||||
ISNULL(A.Doc_Price, 0) AS EvrakFiyat,
|
||||
ISNULL(A.Doc_CurrencyCode, '') AS EvrakDoviz
|
||||
FROM AllInvoicesWithAttributes A
|
||||
LEFT JOIN cdItem CI ON CI.ItemTypeCode = A.ItemTypeCode AND CI.ItemCode = A.ItemCode
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 ItemDescription FROM cdItemDesc
|
||||
WHERE ItemTypeCode = A.ItemTypeCode AND ItemCode = A.ItemCode AND LangCode = 'TR'
|
||||
) ID
|
||||
WHERE A.ProcessCode IN ('BP')
|
||||
AND A.ATAtt01 IN (1, 2)
|
||||
AND A.CompanyCode IN (1, 2, 5)
|
||||
AND A.IsCompleted = 1
|
||||
AND YEAR(A.InvoiceDate) >= 2023
|
||||
AND (NULLIF(@p1, '') IS NULL OR CONVERT(date, A.InvoiceDate) < CONVERT(date, NULLIF(@p1, ''), 23))
|
||||
AND EXISTS (
|
||||
-- Hammadde turu eslestirmesi (V3 tarafindaki karsiligi varsa)
|
||||
SELECT 1 FROM cdItem WHERE ItemCode = A.ItemCode
|
||||
)
|
||||
ORDER BY A.InvoiceDate DESC
|
||||
`
|
||||
*/
|
||||
|
||||
// 2. Uretim (Recete) tarafini sorgula
|
||||
uretimSql := `
|
||||
SELECT TOP (@p3)
|
||||
'recipe' AS sourceType,
|
||||
'BNZ' AS priceType,
|
||||
CONVERT(VARCHAR(16), ISNULL(M.Tarihi, M.dteKayitTarihi), 120) AS dteIslemTarihi,
|
||||
RTRIM(CONVERT(VARCHAR(32), ISNULL(D.nOnMLNo, 0))) AS nOnMLNo,
|
||||
ISNULL(D.sKodu, '') AS sKodu,
|
||||
ISNULL(D.sAciklama, '') AS sAciklama,
|
||||
ISNULL(D.sRenk, '') AS sRenk,
|
||||
ISNULL(D.lMiktar, 0) AS lMiktar,
|
||||
ISNULL(D.sBirim, '') AS sBirim,
|
||||
ISNULL(D.lDovizFiyati, 0) AS lDovizFiyati,
|
||||
CASE
|
||||
WHEN LTRIM(RTRIM(ISNULL(D.fiyat_doviz, ''))) <> '' THEN LTRIM(RTRIM(D.fiyat_doviz))
|
||||
WHEN LTRIM(RTRIM(ISNULL(M.sDovizCinsi, ''))) <> '' THEN LTRIM(RTRIM(M.sDovizCinsi))
|
||||
ELSE 'USD'
|
||||
END AS USD
|
||||
FROM dbo.spUrtOnMLMasDet D
|
||||
INNER JOIN dbo.spUrtOnMLMas M ON M.nOnMLNo = D.nOnMLNo
|
||||
WHERE D.nHammaddeTuruNo = @p1
|
||||
AND (NULLIF(@p2, '') IS NULL OR CONVERT(date, ISNULL(M.Tarihi, M.dteKayitTarihi)) < CONVERT(date, NULLIF(@p2, ''), 23))
|
||||
ORDER BY ISNULL(M.Tarihi, M.dteKayitTarihi) DESC
|
||||
`
|
||||
|
||||
// Not: nHammaddeTuruNo parametresine gore sadece Reçete tarafı şu an doğrudan filtrelenebiliyor.
|
||||
// V3 tarafı için ItemTypeCode veya özel bir grup kodu gerekebilir.
|
||||
// Kullanıcının talebi üzerine Reçete (URETIM) odaklı sorguyu önceliklendiriyoruz.
|
||||
|
||||
rows, err := uretimDB.QueryContext(ctx, uretimSql, nHammaddeTuruNo, costDate, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var results []any
|
||||
for rows.Next() {
|
||||
// Basit bir map veya struct ile dondurebiliriz
|
||||
var row struct {
|
||||
SourceType string `json:"sourceType"`
|
||||
PriceType string `json:"priceType"`
|
||||
Tarih string `json:"Tarih"`
|
||||
EvrakKodu string `json:"EvrakKodu"`
|
||||
Kod string `json:"Kod"`
|
||||
Aciklama string `json:"Aciklama"`
|
||||
Renk string `json:"Renk"`
|
||||
Miktar float64 `json:"Miktar"`
|
||||
Birim string `json:"Birim"`
|
||||
Fiyat float64 `json:"Fiyat"`
|
||||
Doviz string `json:"Doviz"`
|
||||
}
|
||||
if err := rows.Scan(
|
||||
&row.SourceType, &row.PriceType, &row.Tarih, &row.EvrakKodu,
|
||||
&row.Kod, &row.Aciklama, &row.Renk, &row.Miktar, &row.Birim,
|
||||
&row.Fiyat, &row.Doviz,
|
||||
); err == nil {
|
||||
results = append(results, row)
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
@@ -760,7 +760,16 @@ func getOrderLinesFromDB(db *sql.DB, orderID string) ([]OrderLineRaw, error) {
|
||||
P.ProductAtt01Desc,
|
||||
P.ProductAtt02Desc,
|
||||
P.ProductAtt44Desc,
|
||||
L.IsClosed,
|
||||
CASE
|
||||
WHEN ISNULL(L.IsClosed, 0) = 1
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM BAGGI_V3.dbo.trInvoiceLine il WITH (NOLOCK)
|
||||
WHERE il.OrderLineID = L.OrderLineID
|
||||
)
|
||||
THEN CAST(1 AS bit)
|
||||
ELSE CAST(0 AS bit)
|
||||
END AS IsClosed,
|
||||
L.WithHoldingTaxTypeCode,
|
||||
L.DOVCode,
|
||||
L.PlannedDateOfLading,
|
||||
|
||||
2048
svc/routes/production_product_costing.go
Normal file
2048
svc/routes/production_product_costing.go
Normal file
@@ -0,0 +1,2048 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"bssapp-backend/auth"
|
||||
"bssapp-backend/db"
|
||||
"bssapp-backend/models"
|
||||
"bssapp-backend/queries"
|
||||
"bssapp-backend/utils"
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func logProductionHasCostDetailEditorOptionItemDiagnostics(ctx context.Context, uretimDB *sql.DB, search string, limit int) {
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"handler", "production-product-costing.detail-editor-options.diagnostics",
|
||||
"search", search,
|
||||
"limit", limit,
|
||||
)
|
||||
expectedColumns := []string{
|
||||
"nStokID",
|
||||
"sKodu",
|
||||
"sAciklama",
|
||||
"sModel",
|
||||
"sBirimCinsi1",
|
||||
"IsBlocked",
|
||||
}
|
||||
probes := []struct {
|
||||
name string
|
||||
sqlText string
|
||||
}{
|
||||
{
|
||||
name: "projection:nStokID",
|
||||
sqlText: `SELECT TOP 1 RTRIM(CONVERT(VARCHAR(32), ISNULL(S.nStokID, 0))) FROM dbo.tbStok S`,
|
||||
},
|
||||
{
|
||||
name: "projection:sKodu",
|
||||
sqlText: `SELECT TOP 1 LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sKodu, '')))) FROM dbo.tbStok S`,
|
||||
},
|
||||
{
|
||||
name: "projection:sAciklama",
|
||||
sqlText: `SELECT TOP 1 LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sAciklama, '')))) FROM dbo.tbStok S`,
|
||||
},
|
||||
{
|
||||
name: "projection:sModel",
|
||||
sqlText: `SELECT TOP 1 LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sModel, '')))) FROM dbo.tbStok S`,
|
||||
},
|
||||
{
|
||||
name: "projection:sBirimCinsi1",
|
||||
sqlText: `SELECT TOP 1 LTRIM(RTRIM(CONVERT(NVARCHAR(64), ISNULL(S.sBirimCinsi1, '')))) FROM dbo.tbStok S`,
|
||||
},
|
||||
{
|
||||
name: "projection:IsBlocked",
|
||||
sqlText: `SELECT TOP 1 RTRIM(CONVERT(VARCHAR(32), ISNULL(S.IsBlocked, 0))) FROM dbo.tbStok S`,
|
||||
},
|
||||
{
|
||||
name: "filter:model_like_count",
|
||||
sqlText: `SELECT RTRIM(CONVERT(VARCHAR(32), COUNT(1))) FROM dbo.tbStok S WHERE LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sModel, '')))) LIKE '_.%'`,
|
||||
},
|
||||
{
|
||||
name: "filter:isblocked_count",
|
||||
sqlText: `SELECT RTRIM(CONVERT(VARCHAR(32), COUNT(1))) FROM dbo.tbStok S WHERE ISNULL(S.IsBlocked, 0) = 0`,
|
||||
},
|
||||
{
|
||||
name: "filter:final_count",
|
||||
sqlText: `SELECT RTRIM(CONVERT(VARCHAR(32), COUNT(1))) FROM dbo.tbStok S WHERE ISNULL(S.IsBlocked, 0) = 0 AND LTRIM(RTRIM(CONVERT(NVARCHAR(255), ISNULL(S.sModel, '')))) LIKE '_.%'`,
|
||||
},
|
||||
}
|
||||
|
||||
log.Printf("[ProductionHasCostDetailEditorOptions] item diagnostics start search=%q limit=%d", search, limit)
|
||||
|
||||
for _, columnName := range expectedColumns {
|
||||
var exists int
|
||||
err := uretimDB.QueryRowContext(
|
||||
ctx,
|
||||
`SELECT COUNT(1)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'dbo'
|
||||
AND TABLE_NAME = 'tbStok'
|
||||
AND COLUMN_NAME = @p1`,
|
||||
columnName,
|
||||
).Scan(&exists)
|
||||
if err != nil {
|
||||
logger.Error("query error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] item diagnostics column check error column=%s err=%v", columnName, err)
|
||||
continue
|
||||
}
|
||||
log.Printf("[ProductionHasCostDetailEditorOptions] item diagnostics column=%s exists=%t", columnName, exists > 0)
|
||||
}
|
||||
|
||||
for _, probe := range probes {
|
||||
var sample sql.NullString
|
||||
err := uretimDB.QueryRowContext(ctx, probe.sqlText).Scan(&sample)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] item diagnostics probe=%s err=%v", probe.name, err)
|
||||
continue
|
||||
}
|
||||
log.Printf("[ProductionHasCostDetailEditorOptions] item diagnostics probe=%s sample=%q", probe.name, strings.TrimSpace(sample.String))
|
||||
}
|
||||
|
||||
log.Printf("[ProductionHasCostDetailEditorOptions] item diagnostics end search=%q limit=%d", search, limit)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/no-cost-products
|
||||
func GetProductionNoCostProductsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||||
fromDate := strings.TrimSpace(r.URL.Query().Get("from_date"))
|
||||
|
||||
rows, err := queries.GetProductionNoCostProducts(r.Context(), uretimDB, fromDate, search)
|
||||
if err != nil {
|
||||
log.Printf("❌ [ProductionNoCost] query error: %v", err)
|
||||
http.Error(w, "Veritabanı hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
list := make([]models.ProductionNoCostProductRow, 0, 200)
|
||||
for rows.Next() {
|
||||
var item models.ProductionNoCostProductRow
|
||||
if err := rows.Scan(
|
||||
&item.UretimSekli,
|
||||
&item.UrtSiparisNo,
|
||||
&item.IslemTarihi,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAdi,
|
||||
&item.SonIsEmriVeren,
|
||||
&item.MMiktarG,
|
||||
&item.MModelKodu,
|
||||
&item.Kodu,
|
||||
&item.ModelAdi,
|
||||
&item.SKullaniciAdi,
|
||||
&item.SKullaniciGunc,
|
||||
); err != nil {
|
||||
log.Printf("⚠️ [ProductionNoCost] scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
log.Printf("⚠️ [ProductionNoCost] rows error: %v", err)
|
||||
http.Error(w, "Veritabanı satır hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
_ = json.NewEncoder(w).Encode(list)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/has-cost-products
|
||||
func GetProductionHasCostProductsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||||
offset := parsePositiveIntOrDefault(r.URL.Query().Get("offset"), 0)
|
||||
limit := parsePositiveIntOrDefault(r.URL.Query().Get("limit"), 300)
|
||||
if limit > 1000 {
|
||||
limit = 1000
|
||||
}
|
||||
|
||||
rows, err := queries.GetProductionHasCostProducts(r.Context(), uretimDB, search, offset, limit)
|
||||
if err != nil {
|
||||
log.Printf("❌ [ProductionHasCost] query error: %v", err)
|
||||
http.Error(w, "Veritabanı hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
list := make([]models.ProductionHasCostProductRow, 0, 200)
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostProductRow
|
||||
if err := rows.Scan(
|
||||
&item.UretimSekli,
|
||||
&item.NOnMLNo,
|
||||
&item.UrunKodu,
|
||||
&item.UrunAdi,
|
||||
&item.Tarihi,
|
||||
&item.DteKayitTarihi,
|
||||
&item.SKullaniciAdi,
|
||||
&item.LTutarTL,
|
||||
&item.LTutarUSD,
|
||||
&item.LTutarEURO,
|
||||
&item.DteGuncellemeTarihi,
|
||||
&item.SGuncellemeKullaniciAdi,
|
||||
&item.NUrtReceteID,
|
||||
&item.SAciklama,
|
||||
&item.SonSiparisTarihi,
|
||||
&item.MaliyetDurumu,
|
||||
); err != nil {
|
||||
log.Printf("⚠️ [ProductionHasCost] scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
log.Printf("⚠️ [ProductionHasCost] rows error: %v", err)
|
||||
http.Error(w, "Veritabanı satır hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
_ = json.NewEncoder(w).Encode(list)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/has-cost-history
|
||||
func GetProductionHasCostHistoryHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
productCode := strings.TrimSpace(r.URL.Query().Get("urun_kodu"))
|
||||
if productCode == "" {
|
||||
http.Error(w, "urun_kodu zorunlu", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
rows, err := queries.GetProductionHasCostHistoryByProductCode(r.Context(), uretimDB, productCode)
|
||||
if err != nil {
|
||||
log.Printf("⌠[ProductionHasCostHistory] query error: %v", err)
|
||||
http.Error(w, "Veritabanı hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
list := make([]models.ProductionHasCostHistoryRow, 0, 100)
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.NOnMLNo,
|
||||
&item.UrunKodu,
|
||||
&item.UrunAdi,
|
||||
&item.Tarihi,
|
||||
&item.SKullaniciAdi,
|
||||
&item.LTutarUSD,
|
||||
&item.LTutarTL,
|
||||
&item.LTutarEURO,
|
||||
&item.SDovizCinsi,
|
||||
&item.LTutarDoviz,
|
||||
&item.DteGuncellemeTarihi,
|
||||
&item.SGuncellemeKullaniciAdi,
|
||||
&item.NUrtReceteID,
|
||||
&item.SAciklama,
|
||||
); err != nil {
|
||||
log.Printf("âš ï¸ [ProductionHasCostHistory] scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
log.Printf("âš ï¸ [ProductionHasCostHistory] rows error: %v", err)
|
||||
http.Error(w, "Veritabanı satır hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
_ = json.NewEncoder(w).Encode(list)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/has-cost-detail-groups
|
||||
func GetProductionHasCostDetailGroupsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
detailSource := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("detail_source")))
|
||||
recipeCode := strings.TrimSpace(r.URL.Query().Get("recete_kodu"))
|
||||
productCode := strings.TrimSpace(r.URL.Query().Get("urun_kodu"))
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"handler", "production-product-costing.detail-groups",
|
||||
"detail_source", detailSource,
|
||||
"urun_kodu", productCode,
|
||||
"recete_kodu", recipeCode,
|
||||
)
|
||||
|
||||
if detailSource == "no-cost" || recipeCode != "" {
|
||||
if recipeCode == "" {
|
||||
logger.Warn("request invalid", "reason", "missing recete_kodu")
|
||||
http.Error(w, "recete_kodu zorunlu", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
logger.Info("request start")
|
||||
|
||||
rows, err := queries.GetProductionNoCostDetailRowsByRecipeCode(ctx, uretimDB, recipeCode, productCode)
|
||||
if err != nil {
|
||||
logger.Error("query error", "err", err)
|
||||
log.Printf("❌ [ProductionNoCostDetailGroups] query error: %v", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
groups := make([]models.ProductionHasCostDetailGroup, 0, 16)
|
||||
groupIndexByName := map[string]int{}
|
||||
scannedRows := 0
|
||||
scanErrors := 0
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
groupName string
|
||||
groupTotal float64
|
||||
groupTotalUSD float64
|
||||
fiyatGirilen sql.NullFloat64
|
||||
fiyatDoviz sql.NullString
|
||||
maliyeteDahil sql.NullBool
|
||||
cmPriceTypeID sql.NullInt64
|
||||
item models.ProductionHasCostDetailGroupItem
|
||||
)
|
||||
|
||||
if err := rows.Scan(
|
||||
&groupName,
|
||||
&groupTotal,
|
||||
&groupTotalUSD,
|
||||
&item.NOnMLNo,
|
||||
&item.NOnMLDetNo,
|
||||
&item.NHammaddeTuruNo,
|
||||
&item.SKodu,
|
||||
&item.SAciklama,
|
||||
&item.SRenk,
|
||||
&item.SBeden,
|
||||
&item.SAciklama2,
|
||||
&item.LMiktar,
|
||||
&item.LFiyat,
|
||||
&item.LTutar,
|
||||
&item.SFiyatTipi,
|
||||
&item.SDovizCinsi,
|
||||
&item.LDovizKuru,
|
||||
&item.LDovizFiyati,
|
||||
&fiyatGirilen,
|
||||
&fiyatDoviz,
|
||||
&maliyeteDahil,
|
||||
&cmPriceTypeID,
|
||||
&item.USDTutar,
|
||||
&item.EURTutar,
|
||||
&item.GBPTutar,
|
||||
&item.SBirim,
|
||||
&item.SHammaddeTuruAdi,
|
||||
&item.SParcaAdi,
|
||||
); err != nil {
|
||||
scanErrors += 1
|
||||
logger.Warn("scan error", "scan_index", scannedRows+scanErrors+1, "err", err)
|
||||
log.Printf("⚠️ [ProductionNoCostDetailGroups] scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
scannedRows += 1
|
||||
|
||||
if fiyatGirilen.Valid {
|
||||
item.FiyatGirilen = new(float64)
|
||||
*item.FiyatGirilen = fiyatGirilen.Float64
|
||||
}
|
||||
if fiyatDoviz.Valid {
|
||||
item.FiyatDoviz = strings.TrimSpace(fiyatDoviz.String)
|
||||
}
|
||||
item.MaliyeteDahil = !maliyeteDahil.Valid || maliyeteDahil.Bool
|
||||
if cmPriceTypeID.Valid {
|
||||
value := int(cmPriceTypeID.Int64)
|
||||
item.CMPriceTypeID = &value
|
||||
}
|
||||
|
||||
idx, ok := groupIndexByName[groupName]
|
||||
if !ok {
|
||||
groups = append(groups, models.ProductionHasCostDetailGroup{
|
||||
SAciklama3: groupName,
|
||||
TotalTutar: groupTotal,
|
||||
TotalUSDTutar: groupTotalUSD,
|
||||
Items: make([]models.ProductionHasCostDetailGroupItem, 0, 8),
|
||||
})
|
||||
idx = len(groups) - 1
|
||||
groupIndexByName[groupName] = idx
|
||||
}
|
||||
|
||||
groups[idx].Items = append(groups[idx].Items, item)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("rows error", "err", err)
|
||||
log.Printf("⚠️ [ProductionNoCostDetailGroups] rows error: %v", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "group_count", len(groups), "row_count", scannedRows, "scan_errors", scanErrors)
|
||||
log.Printf("[ProductionNoCostDetailGroups] done recete_kodu=%s groups=%d", recipeCode, len(groups))
|
||||
_ = json.NewEncoder(w).Encode(groups)
|
||||
return
|
||||
}
|
||||
|
||||
rawOnMLNo := strings.TrimSpace(r.URL.Query().Get("n_onml_no"))
|
||||
nOnMLNo, err := strconv.Atoi(rawOnMLNo)
|
||||
if err != nil || nOnMLNo <= 0 {
|
||||
logger.Warn("request invalid", "reason", "invalid n_onml_no", "raw_n_onml_no", rawOnMLNo)
|
||||
http.Error(w, "n_onml_no zorunlu ve pozitif sayi olmali", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
logger = logger.With("n_onml_no", nOnMLNo)
|
||||
logger.Info("request start")
|
||||
log.Printf("[ProductionHasCostDetailGroups] start n_onml_no=%d", nOnMLNo)
|
||||
|
||||
rows, err := queries.GetProductionHasCostDetailRowsByOnMLNo(ctx, uretimDB, nOnMLNo)
|
||||
if err != nil {
|
||||
logger.Error("query error", "err", err)
|
||||
log.Printf("⌠[ProductionHasCostDetailGroups] query error: %v", err)
|
||||
http.Error(w, "Veritabanı hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
groups := make([]models.ProductionHasCostDetailGroup, 0, 16)
|
||||
groupIndexByName := map[string]int{}
|
||||
scannedRows := 0
|
||||
scanErrors := 0
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
groupName string
|
||||
groupTotal float64
|
||||
groupTotalUSD float64
|
||||
fiyatGirilen sql.NullFloat64
|
||||
fiyatDoviz sql.NullString
|
||||
maliyeteDahil sql.NullBool
|
||||
cmPriceTypeID sql.NullInt64
|
||||
item models.ProductionHasCostDetailGroupItem
|
||||
)
|
||||
|
||||
if err := rows.Scan(
|
||||
&groupName,
|
||||
&groupTotal,
|
||||
&groupTotalUSD,
|
||||
&item.NOnMLNo,
|
||||
&item.NOnMLDetNo,
|
||||
&item.NHammaddeTuruNo,
|
||||
&item.SKodu,
|
||||
&item.SAciklama,
|
||||
&item.SRenk,
|
||||
&item.SBeden,
|
||||
&item.SAciklama2,
|
||||
&item.LMiktar,
|
||||
&item.LFiyat,
|
||||
&item.LTutar,
|
||||
&item.SFiyatTipi,
|
||||
&item.SDovizCinsi,
|
||||
&item.LDovizKuru,
|
||||
&item.LDovizFiyati,
|
||||
&fiyatGirilen,
|
||||
&fiyatDoviz,
|
||||
&maliyeteDahil,
|
||||
&cmPriceTypeID,
|
||||
&item.USDTutar,
|
||||
&item.EURTutar,
|
||||
&item.GBPTutar,
|
||||
&item.SBirim,
|
||||
&item.SHammaddeTuruAdi,
|
||||
&item.SParcaAdi,
|
||||
); err != nil {
|
||||
log.Printf("âš ï¸ [ProductionHasCostDetailGroups] scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
scannedRows += 1
|
||||
|
||||
if fiyatGirilen.Valid {
|
||||
item.FiyatGirilen = new(float64)
|
||||
*item.FiyatGirilen = fiyatGirilen.Float64
|
||||
}
|
||||
if fiyatDoviz.Valid {
|
||||
item.FiyatDoviz = strings.TrimSpace(fiyatDoviz.String)
|
||||
}
|
||||
item.MaliyeteDahil = maliyeteDahil.Valid && maliyeteDahil.Bool
|
||||
if cmPriceTypeID.Valid {
|
||||
value := int(cmPriceTypeID.Int64)
|
||||
item.CMPriceTypeID = &value
|
||||
}
|
||||
|
||||
idx, ok := groupIndexByName[groupName]
|
||||
if !ok {
|
||||
groups = append(groups, models.ProductionHasCostDetailGroup{
|
||||
SAciklama3: groupName,
|
||||
TotalTutar: groupTotal,
|
||||
TotalUSDTutar: groupTotalUSD,
|
||||
Items: make([]models.ProductionHasCostDetailGroupItem, 0, 24),
|
||||
})
|
||||
idx = len(groups) - 1
|
||||
groupIndexByName[groupName] = idx
|
||||
}
|
||||
|
||||
groups[idx].Items = append(groups[idx].Items, item)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
log.Printf("âš ï¸ [ProductionHasCostDetailGroups] rows error: %v", err)
|
||||
http.Error(w, "Veritabanı satır hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "group_count", len(groups), "row_count", scannedRows, "scan_errors", scanErrors)
|
||||
log.Printf("[ProductionHasCostDetailGroups] done n_onml_no=%d groups=%d rows=%d scan_errors=%d", nOnMLNo, len(groups), scannedRows, scanErrors)
|
||||
_ = json.NewEncoder(w).Encode(groups)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/has-cost-detail-header
|
||||
func GetProductionHasCostDetailHeaderHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
mssqlDB := db.GetDB()
|
||||
|
||||
detailSource := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("detail_source")))
|
||||
recipeCode := strings.TrimSpace(r.URL.Query().Get("recete_kodu"))
|
||||
productCode := strings.TrimSpace(r.URL.Query().Get("urun_kodu"))
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"handler", "production-product-costing.detail-header",
|
||||
"detail_source", detailSource,
|
||||
"urun_kodu", productCode,
|
||||
"recete_kodu", recipeCode,
|
||||
)
|
||||
|
||||
if detailSource == "no-cost" || recipeCode != "" {
|
||||
if recipeCode == "" {
|
||||
logger.Warn("request invalid", "reason", "missing recete_kodu")
|
||||
http.Error(w, "recete_kodu zorunlu", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
logger.Info("request start")
|
||||
|
||||
row, err := queries.GetProductionNoCostDetailHeaderByRecipeCode(ctx, uretimDB, recipeCode, productCode)
|
||||
if err != nil {
|
||||
logger.Error("query prepare error", "err", err)
|
||||
log.Printf("❌ [ProductionNoCostDetailHeader] query prepare error: %v", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var item models.ProductionHasCostDetailHeader
|
||||
if err := row.Scan(
|
||||
&item.UretimiYapanFirma,
|
||||
&item.SonIsEmriVeren,
|
||||
&item.NOnMLNo,
|
||||
&item.UrunKodu,
|
||||
&item.UrunAdi,
|
||||
&item.UretimSekliID,
|
||||
&item.UretimSekli,
|
||||
&item.DteKayitTarihi,
|
||||
&item.SKullaniciAdi,
|
||||
&item.LTutarTL,
|
||||
&item.LTutarUSD,
|
||||
&item.LTutarEURO,
|
||||
&item.LTutarGBP,
|
||||
&item.SDovizCinsi,
|
||||
&item.LTutarDoviz,
|
||||
&item.DteGuncellemeTarihi,
|
||||
&item.SGuncellemeKullaniciAdi,
|
||||
&item.NUrtReceteID,
|
||||
); err != nil {
|
||||
logger.Warn("scan or not found", "err", err)
|
||||
if err == sql.ErrNoRows {
|
||||
logger.Warn("row not found")
|
||||
http.Error(w, "Kayit bulunamadi", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
log.Printf("❌ [ProductionNoCostDetailHeader] scan error: %v", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "n_urt_recete_id", item.NUrtReceteID, "urun_kodu", item.UrunKodu)
|
||||
if mssqlDB != nil {
|
||||
ana, alt, err := queries.GetProductAnaAltGrupByUrunKodu(ctx, mssqlDB, item.UrunKodu)
|
||||
if err != nil {
|
||||
logger.Warn("product group query error", "err", err)
|
||||
} else {
|
||||
item.UrunAnaGrubu = ana
|
||||
item.UrunAltGrubu = alt
|
||||
}
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(item)
|
||||
return
|
||||
}
|
||||
|
||||
rawOnMLNo := strings.TrimSpace(r.URL.Query().Get("n_onml_no"))
|
||||
nOnMLNo, err := strconv.Atoi(rawOnMLNo)
|
||||
if err != nil || nOnMLNo <= 0 {
|
||||
logger.Warn("request invalid", "reason", "invalid n_onml_no", "raw_n_onml_no", rawOnMLNo)
|
||||
http.Error(w, "n_onml_no zorunlu ve pozitif sayi olmali", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
logger = logger.With("n_onml_no", nOnMLNo)
|
||||
logger.Info("request start")
|
||||
|
||||
row, err := queries.GetProductionHasCostDetailHeaderByOnMLNo(ctx, uretimDB, nOnMLNo)
|
||||
if err != nil {
|
||||
logger.Error("query prepare error", "err", err)
|
||||
log.Printf("❌ [ProductionHasCostDetailHeader] query prepare error: %v", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var item models.ProductionHasCostDetailHeader
|
||||
if err := row.Scan(
|
||||
&item.UretimiYapanFirma,
|
||||
&item.SonIsEmriVeren,
|
||||
&item.NOnMLNo,
|
||||
&item.UrunKodu,
|
||||
&item.UrunAdi,
|
||||
&item.UretimSekliID,
|
||||
&item.UretimSekli,
|
||||
&item.DteKayitTarihi,
|
||||
&item.SKullaniciAdi,
|
||||
&item.LTutarTL,
|
||||
&item.LTutarUSD,
|
||||
&item.LTutarEURO,
|
||||
&item.LTutarGBP,
|
||||
&item.SDovizCinsi,
|
||||
&item.LTutarDoviz,
|
||||
&item.DteGuncellemeTarihi,
|
||||
&item.SGuncellemeKullaniciAdi,
|
||||
&item.NUrtReceteID,
|
||||
); err != nil {
|
||||
logger.Warn("scan or not found", "err", err)
|
||||
if err == sql.ErrNoRows {
|
||||
http.Error(w, "Kayit bulunamadi", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
log.Printf("❌ [ProductionHasCostDetailHeader] scan error: %v", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "n_onml_no", item.NOnMLNo, "urun_kodu", item.UrunKodu, "n_urt_recete_id", item.NUrtReceteID)
|
||||
if mssqlDB != nil {
|
||||
ana, alt, err := queries.GetProductAnaAltGrupByUrunKodu(ctx, mssqlDB, item.UrunKodu)
|
||||
if err != nil {
|
||||
logger.Warn("product group query error", "err", err)
|
||||
} else {
|
||||
item.UrunAnaGrubu = ana
|
||||
item.UrunAltGrubu = alt
|
||||
}
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(item)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/production-types
|
||||
func GetProductionTypesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With("handler", "production-product-costing.production-types")
|
||||
logger.Info("request start")
|
||||
|
||||
rows, err := queries.GetProductionTypes(ctx, uretimDB)
|
||||
if err != nil {
|
||||
logger.Error("query error", "err", err)
|
||||
log.Printf("❌ [ProductionTypes] query error: %v", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var types []models.ProductionType
|
||||
for rows.Next() {
|
||||
var t models.ProductionType
|
||||
if err := rows.Scan(&t.ID, &t.Aciklama); err != nil {
|
||||
logger.Warn("scan error", "err", err)
|
||||
log.Printf("⚠️ [ProductionTypes] scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
types = append(types, t)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("rows error", "err", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "row_count", len(types))
|
||||
_ = json.NewEncoder(w).Encode(types)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/detail-editor-options
|
||||
func GetProductionHasCostDetailEditorOptionsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
kind := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("kind")))
|
||||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||||
limit := parsePositiveIntOrDefault(r.URL.Query().Get("limit"), 100)
|
||||
if limit > 200 {
|
||||
limit = 200
|
||||
}
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"handler", "production-product-costing.detail-editor-options",
|
||||
"kind", kind,
|
||||
"search", search,
|
||||
"limit", limit,
|
||||
)
|
||||
logger.Info("request start")
|
||||
|
||||
switch kind {
|
||||
case "hammadde":
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
rows, err := queries.GetProductionHasCostDetailHammaddeTypeOptions(ctx, uretimDB, search, limit)
|
||||
if err != nil {
|
||||
logger.Error("hammadde query error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] hammadde query error: %v", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if columns, columnErr := rows.Columns(); columnErr != nil {
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] item columns read error search=%q limit=%d err=%v", search, limit, columnErr)
|
||||
} else {
|
||||
log.Printf("[ProductionHasCostDetailEditorOptions] item columns=%v", columns)
|
||||
}
|
||||
|
||||
list := make([]models.ProductionHasCostDetailEditorOption, 0, limit)
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailEditorOption
|
||||
if err := rows.Scan(&item.NHammaddeTuruNo, &item.SHammaddeTuruAdi, &item.SAciklama3); err != nil {
|
||||
logger.Warn("hammadde scan error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] hammadde scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
item.Kind = "hammadde"
|
||||
item.Value = item.NHammaddeTuruNo
|
||||
item.Label = strings.TrimSpace(item.NHammaddeTuruNo + " - " + item.SHammaddeTuruAdi)
|
||||
item.SParcaAdi = item.SAciklama3
|
||||
list = append(list, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("hammadde rows error", "err", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
logger.Info("request done", "kind", "hammadde", "row_count", len(list))
|
||||
_ = json.NewEncoder(w).Encode(list)
|
||||
return
|
||||
|
||||
case "item":
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[ProductionHasCostDetailEditorOptions] item start search=%q limit=%d", search, limit)
|
||||
rows, err := queries.GetProductionHasCostDetailItemOptions(ctx, uretimDB, search, limit)
|
||||
if err != nil {
|
||||
logger.Error("item query error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] item query error search=%q limit=%d err=%v", search, limit, err)
|
||||
logProductionHasCostDetailEditorOptionItemDiagnostics(ctx, uretimDB, search, limit)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if columns, columnErr := rows.Columns(); columnErr != nil {
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] item columns read error search=%q limit=%d err=%v", search, limit, columnErr)
|
||||
} else {
|
||||
log.Printf("[ProductionHasCostDetailEditorOptions] item columns=%v", columns)
|
||||
}
|
||||
|
||||
list := make([]models.ProductionHasCostDetailEditorOption, 0, limit)
|
||||
scanErrors := 0
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailEditorOption
|
||||
if err := rows.Scan(&item.NStokID, &item.SKodu, &item.SAciklama, &item.SModel, &item.SBirim); err != nil {
|
||||
scanErrors += 1
|
||||
logger.Warn("item scan error", "scan_index", len(list)+scanErrors, "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] item scan error scan_index=%d err=%v", len(list)+scanErrors, err)
|
||||
continue
|
||||
}
|
||||
item.Kind = "item"
|
||||
item.Value = item.SKodu
|
||||
item.Label = strings.TrimSpace(item.SKodu + " - " + item.SAciklama)
|
||||
list = append(list, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("item rows error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] item rows error search=%q limit=%d err=%v", search, limit, err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
logger.Info("request done", "kind", "item", "row_count", len(list), "scan_errors", scanErrors)
|
||||
log.Printf("[ProductionHasCostDetailEditorOptions] item done search=%q limit=%d row_count=%d scan_errors=%d", search, limit, len(list), scanErrors)
|
||||
_ = json.NewEncoder(w).Encode(list)
|
||||
return
|
||||
|
||||
case "color":
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
modelCode := strings.TrimSpace(r.URL.Query().Get("model_code"))
|
||||
if modelCode == "" {
|
||||
_ = json.NewEncoder(w).Encode([]models.ProductionHasCostDetailEditorOption{})
|
||||
return
|
||||
}
|
||||
|
||||
rows, err := queries.GetProductionHasCostDetailColorOptions(ctx, uretimDB, modelCode, search, limit)
|
||||
if err != nil {
|
||||
logger.Error("color query error", "model_code", modelCode, "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] color query error: %v", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
list := make([]models.ProductionHasCostDetailEditorOption, 0, limit)
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailEditorOption
|
||||
if err := rows.Scan(&item.ColorCode, &item.ColorDescription); err != nil {
|
||||
logger.Warn("color scan error", "model_code", modelCode, "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailEditorOptions] color scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
item.Kind = "color"
|
||||
item.Value = item.ColorCode
|
||||
item.Label = strings.TrimSpace(item.ColorCode + " - " + item.ColorDescription)
|
||||
list = append(list, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("color rows error", "model_code", modelCode, "err", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
logger.Info("request done", "kind", "color", "model_code", modelCode, "row_count", len(list))
|
||||
_ = json.NewEncoder(w).Encode(list)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Warn("request invalid", "reason", "invalid kind")
|
||||
http.Error(w, "kind hammadde, item veya color olmali", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates
|
||||
func GetProductionHasCostDetailExchangeRatesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
mssqlDB := db.GetDB()
|
||||
if mssqlDB == nil {
|
||||
http.Error(w, "MSSQL veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With("handler", "production-product-costing.exchange-rates")
|
||||
|
||||
rawCostDate := strings.TrimSpace(r.URL.Query().Get("maliyet_tarihi"))
|
||||
costDate := ""
|
||||
if rawCostDate != "" {
|
||||
parsedDate, err := time.Parse("2006-01-02", rawCostDate)
|
||||
if err != nil {
|
||||
logger.Warn("request invalid", "reason", "invalid maliyet_tarihi", "maliyet_tarihi", rawCostDate)
|
||||
http.Error(w, "maliyet_tarihi YYYY-MM-DD formatinda olmali", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
costDate = parsedDate.Format("2006-01-02")
|
||||
}
|
||||
|
||||
logger.Info("request start", "maliyet_tarihi", costDate)
|
||||
log.Printf("[ProductionHasCostDetailExchangeRates] start maliyet_tarihi=%s", costDate)
|
||||
|
||||
row, err := queries.GetProductionHasCostDetailExchangeRatesByDate(ctx, mssqlDB, costDate)
|
||||
if err != nil {
|
||||
logger.Error("query prepare error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailExchangeRates] query prepare error: %v", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
item := models.ProductionHasCostDetailExchangeRates{
|
||||
TRYRate: 1,
|
||||
}
|
||||
if err := row.Scan(
|
||||
&item.RateDate,
|
||||
&item.USDRate,
|
||||
&item.EURRate,
|
||||
&item.GBPRate,
|
||||
); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
item.RateDate = costDate
|
||||
logger.Info("request done", "rate_date", item.RateDate, "fallback", true)
|
||||
_ = json.NewEncoder(w).Encode(item)
|
||||
return
|
||||
}
|
||||
log.Printf("⚠️ [ProductionHasCostDetailExchangeRates] scan error: %v", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "rate_date", item.RateDate, "usd_rate", item.USDRate, "eur_rate", item.EURRate, "gbp_rate", item.GBPRate)
|
||||
log.Printf("[ProductionHasCostDetailExchangeRates] done maliyet_tarihi=%s rate_date=%s usd=%.4f eur=%.4f", costDate, item.RateDate, item.USDRate, item.EURRate)
|
||||
_ = json.NewEncoder(w).Encode(item)
|
||||
}
|
||||
|
||||
// POST /api/pricing/production-product-costing/has-cost-detail-bulk-prices
|
||||
func PostProductionHasCostDetailBulkPricesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
mssqlDB := db.GetDB()
|
||||
if mssqlDB == nil {
|
||||
http.Error(w, "MSSQL veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With("handler", "production-product-costing.bulk-prices")
|
||||
|
||||
var req models.ProductionHasCostDetailBulkPriceRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
logger.Warn("request invalid", "reason", "invalid request body", "err", err)
|
||||
http.Error(w, "Gecersiz istek govdesi", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
costDate := strings.TrimSpace(req.MaliyetTarihi)
|
||||
itemsCount := len(req.Items)
|
||||
responseChan := make(chan *models.ProductionHasCostDetailBulkPriceRow, itemsCount)
|
||||
|
||||
logger.Info("request start",
|
||||
"n_onml_no", strings.TrimSpace(req.NOnMLNo),
|
||||
"urun_kodu", strings.TrimSpace(req.UrunKodu),
|
||||
"maliyet_tarihi", costDate,
|
||||
"item_count", itemsCount,
|
||||
)
|
||||
log.Printf("[ProductionHasCostDetailBulkPrices] start n_onml_no=%s urun_kodu=%s maliyet_tarihi=%s item_count=%d", strings.TrimSpace(req.NOnMLNo), strings.TrimSpace(req.UrunKodu), costDate, itemsCount)
|
||||
|
||||
for _, item := range req.Items {
|
||||
go func(item models.ProductionHasCostDetailPriceLookupItem) {
|
||||
sKodu := normalizeLookupValue(item.SKodu)
|
||||
if sKodu == "" {
|
||||
responseChan <- nil
|
||||
return
|
||||
}
|
||||
|
||||
colorCode := firstNonEmptyString(
|
||||
normalizeLookupValue(item.ColorCode),
|
||||
normalizeLookupValue(item.SRenk),
|
||||
)
|
||||
itemDim1Code := firstNonEmptyString(
|
||||
normalizeLookupValue(item.ItemDim1Code),
|
||||
)
|
||||
|
||||
row, err := queries.GetProductionHasCostLatestPurchasePriceForItem(
|
||||
ctx,
|
||||
mssqlDB,
|
||||
sKodu,
|
||||
colorCode,
|
||||
itemDim1Code,
|
||||
costDate,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Warn("item lookup error", "s_kodu", sKodu, "color_code", colorCode, "item_dim1_code", itemDim1Code, "err", err)
|
||||
responseChan <- nil
|
||||
return
|
||||
}
|
||||
|
||||
var result models.ProductionHasCostDetailBulkPriceRow
|
||||
if err := row.Scan(
|
||||
&result.PriceType,
|
||||
&result.Tarih,
|
||||
&result.FaturaKodu,
|
||||
&result.MasrafKodu,
|
||||
&result.MasrafDetay,
|
||||
&result.ColorCode,
|
||||
&result.ColorDescription,
|
||||
&result.ItemDim1Code,
|
||||
&result.ItemDim1Description,
|
||||
&result.FiyatGirilen,
|
||||
&result.FiyatDoviz,
|
||||
); err != nil {
|
||||
logger.Warn("item scan error", "s_kodu", sKodu, "color_code", colorCode, "item_dim1_code", itemDim1Code, "err", err)
|
||||
responseChan <- nil
|
||||
return
|
||||
}
|
||||
|
||||
result.RowKey = strings.TrimSpace(item.RowKey)
|
||||
result.NOnMLDetNo = strings.TrimSpace(item.NOnMLDetNo)
|
||||
result.NHammaddeTuruNo = strings.TrimSpace(item.NHammaddeTuruNo)
|
||||
result.SKodu = sKodu
|
||||
|
||||
if strings.TrimSpace(result.ColorCode) == "" {
|
||||
result.ColorCode = colorCode
|
||||
}
|
||||
if strings.TrimSpace(result.ItemDim1Code) == "" {
|
||||
result.ItemDim1Code = itemDim1Code
|
||||
}
|
||||
|
||||
responseChan <- &result
|
||||
}(item)
|
||||
}
|
||||
|
||||
response := make([]models.ProductionHasCostDetailBulkPriceRow, 0, itemsCount)
|
||||
for i := 0; i < itemsCount; i++ {
|
||||
res := <-responseChan
|
||||
if res != nil {
|
||||
response = append(response, *res)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("request done", "item_count", itemsCount, "matched_count", len(response))
|
||||
log.Printf("[ProductionHasCostDetailBulkPrices] done item_count=%d matched=%d", itemsCount, len(response))
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"items": response,
|
||||
})
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/has-cost-detail-line-history
|
||||
func GetProductionHasCostDetailLineHistoryHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
mssqlDB := db.GetDB()
|
||||
if uretimDB == nil && mssqlDB == nil {
|
||||
http.Error(w, "Veritabani baglantilari aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With("handler", "production-product-costing.line-history")
|
||||
|
||||
rawOnMLNo := strings.TrimSpace(r.URL.Query().Get("n_onml_no"))
|
||||
currentOnMLNo, _ := strconv.Atoi(rawOnMLNo)
|
||||
nHammaddeTuruNo := strings.TrimSpace(r.URL.Query().Get("n_hammadde_turu_no"))
|
||||
sKodu := normalizeLookupValue(r.URL.Query().Get("s_kodu"))
|
||||
colorCode := firstNonEmptyString(
|
||||
normalizeLookupValue(r.URL.Query().Get("color_code")),
|
||||
normalizeLookupValue(r.URL.Query().Get("s_renk")),
|
||||
)
|
||||
costDate := strings.TrimSpace(r.URL.Query().Get("maliyet_tarihi"))
|
||||
|
||||
if sKodu == "" {
|
||||
logger.Warn("request invalid", "reason", "missing s_kodu")
|
||||
http.Error(w, "s_kodu zorunlu", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
logger.Info("request start", "n_onml_no", currentOnMLNo, "n_hammadde_turu_no", nHammaddeTuruNo, "s_kodu", sKodu, "color_code", colorCode, "maliyet_tarihi", costDate)
|
||||
log.Printf("[ProductionHasCostDetailLineHistory] start n_onml_no=%d n_hammadde_turu_no=%s s_kodu=%s color=%s maliyet_tarihi=%s", currentOnMLNo, nHammaddeTuruNo, sKodu, colorCode, costDate)
|
||||
|
||||
const LINE_HISTORY_ROW_LIMIT = 500
|
||||
|
||||
response := models.ProductionHasCostDetailLineHistoryResponse{
|
||||
PurchaseRows: make([]models.ProductionHasCostDetailPurchaseHistoryRow, 0, LINE_HISTORY_ROW_LIMIT),
|
||||
RecipeRows: make([]models.ProductionHasCostDetailRecipeHistoryRow, 0, LINE_HISTORY_ROW_LIMIT),
|
||||
}
|
||||
allowLegacyAutoFallback := true
|
||||
|
||||
if mssqlDB != nil {
|
||||
rows, err := queries.GetProductionHasCostPurchaseHistoryByExpenseCode(
|
||||
ctx,
|
||||
mssqlDB,
|
||||
sKodu,
|
||||
costDate,
|
||||
LINE_HISTORY_ROW_LIMIT,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Warn("purchase query error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] purchase query error: %v", err)
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailPurchaseHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.SourceType,
|
||||
&item.PriceType,
|
||||
&item.Tarih,
|
||||
&item.FaturaKodu,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAciklama,
|
||||
&item.MasrafKodu,
|
||||
&item.MasrafDetay,
|
||||
&item.ColorCode,
|
||||
&item.ColorDescription,
|
||||
&item.ItemDim1Code,
|
||||
&item.ItemDim1Description,
|
||||
&item.Miktar,
|
||||
&item.BIRIM,
|
||||
&item.EvrakFiyat,
|
||||
&item.EvrakTutar,
|
||||
&item.EvrakDoviz,
|
||||
); err != nil {
|
||||
logger.Warn("purchase scan error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] purchase scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
response.PurchaseRows = append(response.PurchaseRows, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Warn("purchase rows error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] purchase rows error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if allowLegacyAutoFallback && mssqlDB != nil && len(response.PurchaseRows) == 0 {
|
||||
similarPrefix := queries.BuildProductionHasCostSimilarCodePrefix(sKodu)
|
||||
if similarPrefix != "" {
|
||||
logger.Info("purchase fallback start", "s_kodu", sKodu, "similar_prefix", similarPrefix, "maliyet_tarihi", costDate)
|
||||
rows, err := queries.GetProductionHasCostPurchaseHistoryByCodePrefix(
|
||||
ctx,
|
||||
mssqlDB,
|
||||
similarPrefix,
|
||||
costDate,
|
||||
LINE_HISTORY_ROW_LIMIT,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Warn("purchase fallback query error", "err", err)
|
||||
log.Printf("âš ï¸ [ProductionHasCostDetailLineHistory] purchase fallback query error: %v", err)
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailPurchaseHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.SourceType,
|
||||
&item.PriceType,
|
||||
&item.Tarih,
|
||||
&item.FaturaKodu,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAciklama,
|
||||
&item.MasrafKodu,
|
||||
&item.MasrafDetay,
|
||||
&item.ColorCode,
|
||||
&item.ColorDescription,
|
||||
&item.ItemDim1Code,
|
||||
&item.ItemDim1Description,
|
||||
&item.Miktar,
|
||||
&item.BIRIM,
|
||||
&item.EvrakFiyat,
|
||||
&item.EvrakTutar,
|
||||
&item.EvrakDoviz,
|
||||
); err != nil {
|
||||
logger.Warn("purchase fallback scan error", "err", err)
|
||||
log.Printf("âš ï¸ [ProductionHasCostDetailLineHistory] purchase fallback scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
response.PurchaseRows = append(response.PurchaseRows, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Warn("purchase fallback rows error", "err", err)
|
||||
log.Printf("âš ï¸ [ProductionHasCostDetailLineHistory] purchase fallback rows error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if uretimDB != nil {
|
||||
rows, err := queries.GetProductionHasCostRecipeHistoryByExpenseCode(
|
||||
ctx,
|
||||
uretimDB,
|
||||
currentOnMLNo,
|
||||
sKodu,
|
||||
colorCode,
|
||||
costDate,
|
||||
LINE_HISTORY_ROW_LIMIT,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Warn("recipe query error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] recipe query error: %v", err)
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailRecipeHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.SourceType,
|
||||
&item.PriceType,
|
||||
&item.DteIslemTarihi,
|
||||
&item.NOnMLNo,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAciklama,
|
||||
&item.SKodu,
|
||||
&item.SAciklama,
|
||||
&item.SRenk,
|
||||
&item.LMiktar,
|
||||
&item.SBirim,
|
||||
&item.LDovizFiyati,
|
||||
&item.LDovizTutari,
|
||||
&item.USD,
|
||||
&item.DUMMY,
|
||||
); err != nil {
|
||||
logger.Warn("recipe scan error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] recipe scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
response.RecipeRows = append(response.RecipeRows, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Warn("recipe rows error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] recipe rows error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if allowLegacyAutoFallback && uretimDB != nil && len(response.RecipeRows) == 0 {
|
||||
similarPrefix := queries.BuildProductionHasCostSimilarCodePrefix(sKodu)
|
||||
if similarPrefix != "" {
|
||||
logger.Info("recipe fallback prefix start", "s_kodu", sKodu, "similar_prefix", similarPrefix, "maliyet_tarihi", costDate)
|
||||
rows, err := queries.GetProductionHasCostOnMLHistoryByCodePrefix(
|
||||
ctx,
|
||||
uretimDB,
|
||||
similarPrefix,
|
||||
costDate,
|
||||
LINE_HISTORY_ROW_LIMIT,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Warn("recipe fallback prefix query error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] recipe fallback prefix query error: %v", err)
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailRecipeHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.SourceType,
|
||||
&item.PriceType,
|
||||
&item.DteIslemTarihi,
|
||||
&item.NOnMLNo,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAciklama,
|
||||
&item.SKodu,
|
||||
&item.SAciklama,
|
||||
&item.SRenk,
|
||||
&item.LMiktar,
|
||||
&item.SBirim,
|
||||
&item.LDovizFiyati,
|
||||
&item.LDovizTutari,
|
||||
&item.USD,
|
||||
&item.DUMMY,
|
||||
); err != nil {
|
||||
logger.Warn("recipe fallback prefix scan error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] recipe fallback prefix scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
response.RecipeRows = append(response.RecipeRows, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Warn("recipe fallback prefix rows error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] recipe fallback prefix rows error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if allowLegacyAutoFallback && uretimDB != nil && len(response.RecipeRows) == 0 && nHammaddeTuruNo != "" {
|
||||
logger.Info("recipe fallback hammadde-turu start", "n_hammadde_turu_no", nHammaddeTuruNo, "maliyet_tarihi", costDate)
|
||||
rows, err := queries.GetProductionHasCostOnMLHistoryByHammaddeTuruNo(
|
||||
ctx,
|
||||
uretimDB,
|
||||
nHammaddeTuruNo,
|
||||
costDate,
|
||||
LINE_HISTORY_ROW_LIMIT,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Warn("recipe fallback hammadde-turu query error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] recipe fallback hammadde-turu query error: %v", err)
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailRecipeHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.SourceType,
|
||||
&item.PriceType,
|
||||
&item.DteIslemTarihi,
|
||||
&item.NOnMLNo,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAciklama,
|
||||
&item.SKodu,
|
||||
&item.SAciklama,
|
||||
&item.SRenk,
|
||||
&item.LMiktar,
|
||||
&item.SBirim,
|
||||
&item.LDovizFiyati,
|
||||
&item.LDovizTutari,
|
||||
&item.USD,
|
||||
&item.DUMMY,
|
||||
); err != nil {
|
||||
logger.Warn("recipe fallback hammadde-turu scan error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] recipe fallback hammadde-turu scan error: %v", err)
|
||||
continue
|
||||
}
|
||||
response.RecipeRows = append(response.RecipeRows, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Warn("recipe fallback hammadde-turu rows error", "err", err)
|
||||
log.Printf("⚠️ [ProductionHasCostDetailLineHistory] recipe fallback hammadde-turu rows error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("request done", "s_kodu", sKodu, "purchase_count", len(response.PurchaseRows), "recipe_count", len(response.RecipeRows))
|
||||
log.Printf("[ProductionHasCostDetailLineHistory] done s_kodu=%s purchase_rows=%d recipe_rows=%d", sKodu, len(response.PurchaseRows), len(response.RecipeRows))
|
||||
_ = json.NewEncoder(w).Encode(response)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/has-cost-detail-similar-history
|
||||
func GetProductionHasCostDetailSimilarHistoryHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
mssqlDB := db.GetDB()
|
||||
uretimDB := db.GetUretimDB()
|
||||
if mssqlDB == nil || uretimDB == nil {
|
||||
http.Error(w, "Veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With("handler", "production-product-costing.similar-history")
|
||||
|
||||
q := r.URL.Query()
|
||||
nHammaddeTuruNo := strings.TrimSpace(q.Get("n_hammadde_turu_no"))
|
||||
sKodu := normalizeLookupValue(q.Get("s_kodu"))
|
||||
costDate := strings.TrimSpace(q.Get("maliyet_tarihi"))
|
||||
limit := parsePositiveIntOrDefault(q.Get("limit"), 500)
|
||||
searchMode := strings.ToLower(strings.TrimSpace(q.Get("search_mode")))
|
||||
if searchMode == "" || searchMode == "exact" {
|
||||
searchMode = "prefix"
|
||||
}
|
||||
similarPrefix := queries.BuildProductionHasCostSimilarCodePrefix(sKodu)
|
||||
|
||||
if nHammaddeTuruNo == "" && sKodu == "" {
|
||||
http.Error(w, "n_hammadde_turu_no veya s_kodu parametresi zorunludur", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request start", "search_mode", searchMode, "n_hammadde_turu_no", nHammaddeTuruNo, "s_kodu", sKodu, "similar_prefix", similarPrefix, "maliyet_tarihi", costDate, "limit", limit)
|
||||
|
||||
response := models.ProductionHasCostDetailLineHistoryResponse{
|
||||
PurchaseRows: make([]models.ProductionHasCostDetailPurchaseHistoryRow, 0, limit),
|
||||
RecipeRows: make([]models.ProductionHasCostDetailRecipeHistoryRow, 0, limit),
|
||||
}
|
||||
purchaseMatchStage := searchMode
|
||||
recipeMatchStage := searchMode
|
||||
allowRecipeAutoFallback := false
|
||||
|
||||
if searchMode == "alternative" {
|
||||
purchaseMatchStage = "skipped"
|
||||
if nHammaddeTuruNo != "" && uretimDB != nil {
|
||||
rows, err := queries.GetProductionHasCostOnMLHistoryByHammaddeTuruNo(ctx, uretimDB, nHammaddeTuruNo, costDate, limit)
|
||||
if err != nil {
|
||||
logger.Warn("alternative onml query error", "err", err)
|
||||
http.Error(w, "Sorgu calistirilirken hata olustu", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailRecipeHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.SourceType,
|
||||
&item.PriceType,
|
||||
&item.DteIslemTarihi,
|
||||
&item.NOnMLNo,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAciklama,
|
||||
&item.SKodu,
|
||||
&item.SAciklama,
|
||||
&item.SRenk,
|
||||
&item.LMiktar,
|
||||
&item.SBirim,
|
||||
&item.LDovizFiyati,
|
||||
&item.LDovizTutari,
|
||||
&item.USD,
|
||||
&item.DUMMY,
|
||||
); err != nil {
|
||||
logger.Warn("alternative onml scan error", "err", err)
|
||||
continue
|
||||
}
|
||||
response.RecipeRows = append(response.RecipeRows, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Warn("alternative onml rows error", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(response.PurchaseRows) == 0 {
|
||||
purchaseMatchStage = "empty"
|
||||
}
|
||||
if len(response.RecipeRows) == 0 {
|
||||
recipeMatchStage = "empty"
|
||||
}
|
||||
|
||||
logger.Info("request done",
|
||||
"search_mode", searchMode,
|
||||
"purchase_match_stage", purchaseMatchStage,
|
||||
"recipe_match_stage", recipeMatchStage,
|
||||
"similar_prefix", similarPrefix,
|
||||
"purchase_count", len(response.PurchaseRows),
|
||||
"recipe_count", len(response.RecipeRows),
|
||||
)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"purchaseRows": response.PurchaseRows,
|
||||
"recipeRows": response.RecipeRows,
|
||||
"purchase_match_stage": purchaseMatchStage,
|
||||
"recipe_match_stage": recipeMatchStage,
|
||||
"similar_code_prefix": similarPrefix,
|
||||
"search_mode": searchMode,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if similarPrefix != "" {
|
||||
if mssqlDB != nil {
|
||||
rows, err := queries.GetProductionHasCostPurchaseHistoryByCodePrefix(ctx, mssqlDB, similarPrefix, costDate, limit)
|
||||
if err != nil {
|
||||
logger.Warn("prefix purchase query error", "err", err)
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailPurchaseHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.SourceType,
|
||||
&item.PriceType,
|
||||
&item.Tarih,
|
||||
&item.FaturaKodu,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAciklama,
|
||||
&item.MasrafKodu,
|
||||
&item.MasrafDetay,
|
||||
&item.ColorCode,
|
||||
&item.ColorDescription,
|
||||
&item.ItemDim1Code,
|
||||
&item.ItemDim1Description,
|
||||
&item.Miktar,
|
||||
&item.BIRIM,
|
||||
&item.EvrakFiyat,
|
||||
&item.EvrakTutar,
|
||||
&item.EvrakDoviz,
|
||||
); err != nil {
|
||||
logger.Warn("prefix purchase scan error", "err", err)
|
||||
continue
|
||||
}
|
||||
response.PurchaseRows = append(response.PurchaseRows, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Warn("prefix purchase rows error", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if uretimDB != nil {
|
||||
rows, err := queries.GetProductionHasCostOnMLHistoryByCodePrefix(ctx, uretimDB, similarPrefix, costDate, limit)
|
||||
if err != nil {
|
||||
logger.Warn("prefix onml query error", "err", err)
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailRecipeHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.SourceType,
|
||||
&item.PriceType,
|
||||
&item.DteIslemTarihi,
|
||||
&item.NOnMLNo,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAciklama,
|
||||
&item.SKodu,
|
||||
&item.SAciklama,
|
||||
&item.SRenk,
|
||||
&item.LMiktar,
|
||||
&item.SBirim,
|
||||
&item.LDovizFiyati,
|
||||
&item.LDovizTutari,
|
||||
&item.USD,
|
||||
&item.DUMMY,
|
||||
); err != nil {
|
||||
logger.Warn("prefix onml scan error", "err", err)
|
||||
continue
|
||||
}
|
||||
response.RecipeRows = append(response.RecipeRows, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Warn("prefix onml rows error", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if allowRecipeAutoFallback && len(response.RecipeRows) == 0 && nHammaddeTuruNo != "" && uretimDB != nil {
|
||||
recipeMatchStage = "hammadde-turu-fallback"
|
||||
rows, err := queries.GetProductionHasCostOnMLHistoryByHammaddeTuruNo(ctx, uretimDB, nHammaddeTuruNo, costDate, limit)
|
||||
if err != nil {
|
||||
logger.Warn("fallback onml query error", "err", err)
|
||||
http.Error(w, "Sorgu calistirilirken hata olustu", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item models.ProductionHasCostDetailRecipeHistoryRow
|
||||
if err := rows.Scan(
|
||||
&item.SourceType,
|
||||
&item.PriceType,
|
||||
&item.DteIslemTarihi,
|
||||
&item.NOnMLNo,
|
||||
&item.FirmaKodu,
|
||||
&item.FirmaAciklama,
|
||||
&item.SKodu,
|
||||
&item.SAciklama,
|
||||
&item.SRenk,
|
||||
&item.LMiktar,
|
||||
&item.SBirim,
|
||||
&item.LDovizFiyati,
|
||||
&item.LDovizTutari,
|
||||
&item.USD,
|
||||
&item.DUMMY,
|
||||
); err != nil {
|
||||
logger.Warn("fallback onml scan error", "err", err)
|
||||
continue
|
||||
}
|
||||
response.RecipeRows = append(response.RecipeRows, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Warn("fallback onml rows error", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(response.PurchaseRows) == 0 {
|
||||
purchaseMatchStage = "empty"
|
||||
}
|
||||
if len(response.RecipeRows) == 0 {
|
||||
recipeMatchStage = "empty"
|
||||
}
|
||||
|
||||
logger.Info("request done",
|
||||
"search_mode", searchMode,
|
||||
"purchase_match_stage", purchaseMatchStage,
|
||||
"recipe_match_stage", recipeMatchStage,
|
||||
"similar_prefix", similarPrefix,
|
||||
"purchase_count", len(response.PurchaseRows),
|
||||
"recipe_count", len(response.RecipeRows),
|
||||
)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"purchaseRows": response.PurchaseRows,
|
||||
"recipeRows": response.RecipeRows,
|
||||
"purchase_match_stage": purchaseMatchStage,
|
||||
"recipe_match_stage": recipeMatchStage,
|
||||
"similar_code_prefix": similarPrefix,
|
||||
"search_mode": searchMode,
|
||||
})
|
||||
}
|
||||
|
||||
func parsePositiveIntOrDefault(raw string, fallback int) int {
|
||||
v, err := strconv.Atoi(strings.TrimSpace(raw))
|
||||
if err != nil || v < 0 {
|
||||
return fallback
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func normalizeLookupValue(raw string) string {
|
||||
return strings.ToUpper(strings.TrimSpace(raw))
|
||||
}
|
||||
|
||||
func firstNonEmptyString(values ...string) string {
|
||||
for _, value := range values {
|
||||
value = strings.TrimSpace(value)
|
||||
if value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// MT BOLUM MAPPING (URETIM DB)
|
||||
// ============================================================
|
||||
|
||||
// GET /api/pricing/production-product-costing/options/urun-ana-grup
|
||||
func GetProductionProductCostingUrunAnaGrupOptionsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
mssqlDB := db.GetDB()
|
||||
if mssqlDB == nil {
|
||||
http.Error(w, "MSSQL veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||||
limit := parsePositiveIntOrDefault(r.URL.Query().Get("limit"), 50)
|
||||
if limit > 500 {
|
||||
limit = 500
|
||||
}
|
||||
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"handler", "production-product-costing.options.urun-ana-grup",
|
||||
"search", search,
|
||||
"limit", limit,
|
||||
)
|
||||
logger.Info("request start")
|
||||
|
||||
rows, err := queries.GetProductionProductCostingAnaGrupOptions(ctx, mssqlDB, search, limit)
|
||||
if err != nil {
|
||||
logger.Error("query error", "err", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]models.ProductionProductCostingLookupOption, 0, limit)
|
||||
for rows.Next() {
|
||||
var v string
|
||||
if err := rows.Scan(&v); err != nil {
|
||||
logger.Warn("scan error", "err", err)
|
||||
continue
|
||||
}
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
out = append(out, models.ProductionProductCostingLookupOption{Value: v, Label: v})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("rows error", "err", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
logger.Info("request done", "row_count", len(out))
|
||||
_ = json.NewEncoder(w).Encode(out)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/options/urun-alt-grup
|
||||
func GetProductionProductCostingUrunAltGrupOptionsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
mssqlDB := db.GetDB()
|
||||
if mssqlDB == nil {
|
||||
http.Error(w, "MSSQL veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
urunAnaGrubu := strings.TrimSpace(r.URL.Query().Get("urun_ana_grubu"))
|
||||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||||
limit := parsePositiveIntOrDefault(r.URL.Query().Get("limit"), 50)
|
||||
if limit > 500 {
|
||||
limit = 500
|
||||
}
|
||||
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"handler", "production-product-costing.options.urun-alt-grup",
|
||||
"urun_ana_grubu", urunAnaGrubu,
|
||||
"search", search,
|
||||
"limit", limit,
|
||||
)
|
||||
logger.Info("request start")
|
||||
|
||||
rows, err := queries.GetProductionProductCostingAltGrupOptions(ctx, mssqlDB, urunAnaGrubu, search, limit)
|
||||
if err != nil {
|
||||
logger.Error("query error", "err", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]models.ProductionProductCostingLookupOption, 0, limit)
|
||||
for rows.Next() {
|
||||
var v string
|
||||
if err := rows.Scan(&v); err != nil {
|
||||
logger.Warn("scan error", "err", err)
|
||||
continue
|
||||
}
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
out = append(out, models.ProductionProductCostingLookupOption{Value: v, Label: v})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("rows error", "err", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
logger.Info("request done", "row_count", len(out))
|
||||
_ = json.NewEncoder(w).Encode(out)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/options/urun-ana-alt-combos
|
||||
func GetProductionProductCostingUrunAnaAltCombosHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
mssqlDB := db.GetDB()
|
||||
if mssqlDB == nil {
|
||||
http.Error(w, "MSSQL veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||||
limit := parsePositiveIntOrDefault(r.URL.Query().Get("limit"), 2000)
|
||||
if limit > 5000 {
|
||||
limit = 5000
|
||||
}
|
||||
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"handler", "production-product-costing.options.urun-ana-alt-combos",
|
||||
"search", search,
|
||||
"limit", limit,
|
||||
)
|
||||
logger.Info("request start")
|
||||
|
||||
rows, err := queries.GetProductionProductCostingAnaAltComboRows(ctx, mssqlDB, search, limit)
|
||||
if err != nil {
|
||||
// Keep the response generic, but log the underlying SQL driver error for diagnostics.
|
||||
logger.Error("query error", "err", err, "search", search, "limit", limit, "trace_id", traceID)
|
||||
log.Printf("❌ [ProductionProductCostingAnaAltCombos] query error trace_id=%s search=%q limit=%d err=%v", traceID, search, limit, err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]models.ProductionProductCostingAnaAltComboRow, 0, 1024)
|
||||
for rows.Next() {
|
||||
var item models.ProductionProductCostingAnaAltComboRow
|
||||
if err := rows.Scan(&item.UrunIlkGrubu, &item.UrunAnaGrubu, &item.UrunAltGrubu); err != nil {
|
||||
logger.Warn("scan error", "err", err)
|
||||
continue
|
||||
}
|
||||
item.UrunIlkGrubu = strings.TrimSpace(item.UrunIlkGrubu)
|
||||
item.UrunAnaGrubu = strings.TrimSpace(item.UrunAnaGrubu)
|
||||
item.UrunAltGrubu = strings.TrimSpace(item.UrunAltGrubu)
|
||||
if item.UrunIlkGrubu == "" || item.UrunAnaGrubu == "" || item.UrunAltGrubu == "" {
|
||||
continue
|
||||
}
|
||||
out = append(out, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("rows error", "err", err, "trace_id", traceID)
|
||||
log.Printf("⚠️ [ProductionProductCostingAnaAltCombos] rows error trace_id=%s err=%v", traceID, err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "row_count", len(out))
|
||||
_ = json.NewEncoder(w).Encode(out)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/options/mtbolum
|
||||
func GetProductionProductCostingMTBolumOptionsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||||
limit := parsePositiveIntOrDefault(r.URL.Query().Get("limit"), 50)
|
||||
if limit > 500 {
|
||||
limit = 500
|
||||
}
|
||||
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"handler", "production-product-costing.options.mtbolum",
|
||||
"search", search,
|
||||
"limit", limit,
|
||||
)
|
||||
logger.Info("request start")
|
||||
|
||||
rows, err := queries.GetProductionProductCostingMTBolumOptions(ctx, uretimDB, search, limit)
|
||||
if err != nil {
|
||||
logger.Error("query error", "err", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]models.ProductionProductCostingLookupOption, 0, limit)
|
||||
for rows.Next() {
|
||||
var id int
|
||||
var name string
|
||||
if err := rows.Scan(&id, &name); err != nil {
|
||||
logger.Warn("scan error", "err", err)
|
||||
continue
|
||||
}
|
||||
label := strings.TrimSpace(strconv.Itoa(id) + " - " + strings.TrimSpace(name))
|
||||
out = append(out, models.ProductionProductCostingLookupOption{
|
||||
Value: strconv.Itoa(id),
|
||||
Label: label,
|
||||
})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("rows error", "err", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
logger.Info("request done", "row_count", len(out))
|
||||
_ = json.NewEncoder(w).Encode(out)
|
||||
}
|
||||
|
||||
// GET /api/pricing/production-product-costing/maliyet-parca-eslestirme
|
||||
func GetProductionProductCostingParcaMappingsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
urunIlkGrubu := strings.TrimSpace(r.URL.Query().Get("urun_ilk_grubu"))
|
||||
urunAnaGrubu := strings.TrimSpace(r.URL.Query().Get("urun_ana_grubu"))
|
||||
urunAltGrubu := strings.TrimSpace(r.URL.Query().Get("urun_alt_grubu"))
|
||||
nUrtMTBolumID := parsePositiveIntOrDefault(r.URL.Query().Get("n_urt_mt_bolum_id"), 0)
|
||||
rawOnlyActive := strings.TrimSpace(r.URL.Query().Get("only_active"))
|
||||
var onlyActive *bool = nil
|
||||
if rawOnlyActive != "" {
|
||||
v := rawOnlyActive == "1" || strings.EqualFold(rawOnlyActive, "true")
|
||||
onlyActive = &v
|
||||
}
|
||||
|
||||
logger := utils.SlogFromContext(ctx).With(
|
||||
"handler", "production-product-costing.maliyet-parca-eslestirme.list",
|
||||
"urun_ilk_grubu", urunIlkGrubu,
|
||||
"urun_ana_grubu", urunAnaGrubu,
|
||||
"urun_alt_grubu", urunAltGrubu,
|
||||
"n_urt_mt_bolum_id", nUrtMTBolumID,
|
||||
"only_active", rawOnlyActive,
|
||||
)
|
||||
logger.Info("request start")
|
||||
|
||||
rows, err := queries.ListProductionProductCostingParcaMappings(ctx, uretimDB, urunIlkGrubu, urunAnaGrubu, urunAltGrubu, nUrtMTBolumID, onlyActive)
|
||||
if err != nil {
|
||||
logger.Error("query error", "err", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]models.ProductionProductCostingParcaMappingRow, 0, 200)
|
||||
for rows.Next() {
|
||||
var row models.ProductionProductCostingParcaMappingRow
|
||||
var bAktif sql.NullBool
|
||||
var hammaddeCsv sql.NullString
|
||||
if err := rows.Scan(
|
||||
&row.ID,
|
||||
&row.UrunIlkGrubu,
|
||||
&row.UrunAnaGrubu,
|
||||
&row.UrunAltGrubu,
|
||||
&row.NUrtMTBolumID,
|
||||
&row.ParcaBolumAdi,
|
||||
&hammaddeCsv,
|
||||
&bAktif,
|
||||
&row.DteIslem,
|
||||
&row.SKullaniciAdi,
|
||||
); err != nil {
|
||||
logger.Warn("scan error", "err", err)
|
||||
continue
|
||||
}
|
||||
row.BAktif = bAktif.Valid && bAktif.Bool
|
||||
row.NHammaddeTurleri = make([]string, 0, 8)
|
||||
if hammaddeCsv.Valid {
|
||||
for _, part := range strings.Split(hammaddeCsv.String, ",") {
|
||||
part = strings.TrimSpace(part)
|
||||
if part != "" {
|
||||
row.NHammaddeTurleri = append(row.NHammaddeTurleri, part)
|
||||
}
|
||||
}
|
||||
}
|
||||
out = append(out, row)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
logger.Error("rows error", "err", err)
|
||||
http.Error(w, "Veritabani satir hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
logger.Info("request done", "row_count", len(out))
|
||||
_ = json.NewEncoder(w).Encode(out)
|
||||
}
|
||||
|
||||
// POST /api/pricing/production-product-costing/maliyet-parca-eslestirme/upsert
|
||||
func PostProductionProductCostingParcaMappingUpsertHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
claims, _ := auth.GetClaimsFromContext(r.Context())
|
||||
user := ""
|
||||
if claims != nil {
|
||||
user = strings.TrimSpace(claims.Username)
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With("handler", "production-product-costing.maliyet-parca-eslestirme.upsert")
|
||||
logger.Info("request start")
|
||||
|
||||
var req models.ProductionProductCostingParcaMappingUpsertRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
logger.Warn("invalid json", "err", err)
|
||||
http.Error(w, "Gecersiz JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
req.UrunAnaGrubu = strings.TrimSpace(req.UrunAnaGrubu)
|
||||
req.UrunAltGrubu = strings.TrimSpace(req.UrunAltGrubu)
|
||||
req.UrunIlkGrubu = strings.TrimSpace(req.UrunIlkGrubu)
|
||||
if req.UrunIlkGrubu == "" || req.UrunAnaGrubu == "" || req.UrunAltGrubu == "" || req.NUrtMTBolumID <= 0 {
|
||||
http.Error(w, "urunIlkGrubu, urunAnaGrubu, urunAltGrubu ve nUrtMTBolumID zorunlu", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := queries.UpsertProductionProductCostingParcaMapping(ctx, uretimDB, req.UrunIlkGrubu, req.UrunAnaGrubu, req.UrunAltGrubu, req.NUrtMTBolumID, req.NHammaddeTurleri, req.BAktif, user)
|
||||
if err != nil {
|
||||
logger.Error("exec error", "err", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "id", id, "user", user, "bAktif", req.BAktif)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"ok": true, "id": id})
|
||||
}
|
||||
|
||||
type productionProductCostingSetActiveRequest struct {
|
||||
ID int `json:"id"`
|
||||
BAktif bool `json:"bAktif"`
|
||||
}
|
||||
|
||||
// POST /api/pricing/production-product-costing/maliyet-parca-eslestirme/set-active
|
||||
func PostProductionProductCostingParcaMappingSetActiveHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
claims, _ := auth.GetClaimsFromContext(r.Context())
|
||||
user := ""
|
||||
if claims != nil {
|
||||
user = strings.TrimSpace(claims.Username)
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With("handler", "production-product-costing.maliyet-parca-eslestirme.set-active")
|
||||
logger.Info("request start")
|
||||
|
||||
var req productionProductCostingSetActiveRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
logger.Warn("invalid json", "err", err)
|
||||
http.Error(w, "Gecersiz JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.ID <= 0 {
|
||||
http.Error(w, "id zorunlu", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := queries.SetProductionProductCostingParcaMappingActive(ctx, uretimDB, req.ID, req.BAktif, user); err != nil {
|
||||
logger.Error("exec error", "err", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "id", req.ID, "bAktif", req.BAktif, "user", user)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"ok": true})
|
||||
}
|
||||
|
||||
// DELETE /api/pricing/production-product-costing/maliyet-parca-eslestirme?id=123
|
||||
func DeleteProductionProductCostingParcaMappingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
uretimDB := db.GetUretimDB()
|
||||
if uretimDB == nil {
|
||||
http.Error(w, "URETIM veritabani baglantisi aktif degil", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
traceID := utils.TraceIDFromRequest(r)
|
||||
ctx := utils.ContextWithTraceID(r.Context(), traceID)
|
||||
logger := utils.SlogFromContext(ctx).With("handler", "production-product-costing.maliyet-parca-eslestirme.delete")
|
||||
logger.Info("request start")
|
||||
|
||||
id := parsePositiveIntOrDefault(r.URL.Query().Get("id"), 0)
|
||||
if id <= 0 {
|
||||
http.Error(w, "id zorunlu", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := queries.DeleteProductionProductCostingParcaMapping(ctx, uretimDB, id); err != nil {
|
||||
logger.Error("exec error", "err", err)
|
||||
http.Error(w, "Veritabani hatasi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("request done", "id", id)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"ok": true})
|
||||
}
|
||||
1
svc/tmp_backend.err.log
Normal file
1
svc/tmp_backend.err.log
Normal file
@@ -0,0 +1 @@
|
||||
exit status 1
|
||||
157
svc/tmp_backend.out.log
Normal file
157
svc/tmp_backend.out.log
Normal file
@@ -0,0 +1,157 @@
|
||||
time=2026-05-03T21:39:36.490+03:00 level=INFO msg="backend start" app=bssapp-backend scope=main
|
||||
time=2026-05-03T21:39:36.508+03:00 level=INFO msg="🔥🔥🔥 BSSAPP BACKEND STARTED — LOGIN ROUTE SHOULD EXIST 🔥🔥🔥" app=bssapp-backend
|
||||
time=2026-05-03T21:39:36.509+03:00 level=INFO msg="🔐 JWT_SECRET yüklendi" app=bssapp-backend
|
||||
MSSQL baglantisi basarili (connection timeout=120s, dial timeout=120s)
|
||||
URETIM MSSQL baglantisi basarili (connection timeout=120s, dial timeout=120s)
|
||||
time=2026-05-03T21:39:36.926+03:00 level=INFO msg="PostgreSQL bağlantısı başarılı" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.222+03:00 level=INFO msg="✅ Admin dept permissions seeded" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.223+03:00 level=INFO msg="🟢 auditlog Init called, buffer: 1000" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.224+03:00 level=INFO msg="🕵️ AuditLog sistemi başlatıldı (buffer=1000)" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.224+03:00 level=INFO msg="🟢 auditlog worker STARTED" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.306+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE EXTENSION IF NOT EXISTS pg_trgm\"" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.386+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_t_key_lang ON mk_translator (t_key, lang_code)\"" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.471+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_status_lang_updated ON mk_translator (status, lang_code...\"" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.553+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_manual_status ON mk_translator (is_manual, status)\"" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.635+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_source_type_expr ON mk_translator ((COALESCE(NULLIF(pro...\"" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.717+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_source_text_trgm ON mk_translator USING gin (source_tex...\"" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.799+03:00 level=INFO msg="[TranslationPerf] index_ready sql=\"CREATE INDEX IF NOT EXISTS idx_mk_translator_translated_text_trgm ON mk_translator USING gin (transl...\"" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.799+03:00 level=INFO msg="✉️ Graph Mailer hazır (App-only token) | from=baggiss@baggi.com.tr" app=bssapp-backend
|
||||
time=2026-05-03T21:39:37.799+03:00 level=INFO msg="✉️ Graph Mailer hazır" app=bssapp-backend
|
||||
📋 [DEBUG] İlk 10 kullanıcı:
|
||||
- 1 : ctengiz
|
||||
- 2 : ali.kale
|
||||
- 5 : mehmet.keçeci
|
||||
- 6 : mert.keçeci
|
||||
- 7 : samet.keçeci
|
||||
- 9 : orhan.caliskan
|
||||
- 10 : nilgun.sara
|
||||
- 14 : rustem.kurbanov
|
||||
- 15 : caner.akyol
|
||||
- 16 : kemal.matyakupov
|
||||
time=2026-05-03T21:39:38.702+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/auth/login [auth:login]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:39.525+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/auth/refresh [auth:refresh]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:40.343+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/password/forgot [auth:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:41.180+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/password/reset/validate/{token} [auth:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:41.998+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/password/reset [auth:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:42.815+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/password/change [auth:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:43.636+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/activity-logs [system:read]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:44.451+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/test-mail [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:45.268+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/system/market-mail-mappings/lookups [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:46.088+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/system/market-mail-mappings [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:46.905+03:00 level=INFO msg="✅ Route+Perm registered → PUT /api/system/market-mail-mappings/{marketId} [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:47.722+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/language/translations [language:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:48.540+03:00 level=INFO msg="✅ Route+Perm registered → PUT /api/language/translations/{id} [language:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:49.366+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/upsert-missing [language:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:50.191+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/sync-sources [language:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:51.011+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/translate-selected [language:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:51.827+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/bulk-approve [language:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:52.647+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/language/translations/bulk-update [language:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:53.473+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/roles/{id}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:54.310+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/roles/{id}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:55.165+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/users/{id}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:56.030+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/{id}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:56.877+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/permissions/routes [system:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:57.718+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/permissions/effective [system:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:58.552+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/permissions/matrix [system:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:39:59.385+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/role-dept-permissions/list [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:00.208+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/roles/{roleId}/departments/{deptCode}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:01.043+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/roles/{roleId}/departments/{deptCode}/permissions [system:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:01.861+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/users/list [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:02.685+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users [user:insert]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:03.509+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/users/{id} [user:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:04.357+03:00 level=INFO msg="✅ Route+Perm registered → PUT /api/users/{id} [user:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:05.218+03:00 level=INFO msg="✅ Route+Perm registered → DELETE /api/users/{id} [user:delete]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:06.102+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/{id}/admin-reset-password [user:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:06.946+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/{id}/send-password-mail [user:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:07.760+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/create [user:insert]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:08.577+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/modules [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:09.402+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/roles [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:10.216+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/departments [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:11.051+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/nebim-users [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:11.932+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/piyasalar [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:12.770+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/users-perm [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:13.610+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/roles-perm [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:14.445+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/lookups/departments-perm [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:15.268+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/accounts [customer:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:16.090+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/customer-list [customer:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:16.921+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/today-currency [finance:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:17.735+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/export-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:18.573+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/exportstamentheaderreport-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:19.416+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/customer-balances [finance:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:20.262+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/customer-balances/export-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:21.096+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/customer-balances/export-excel [finance:export]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:21.915+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/account-aging-statement [finance:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:22.770+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/account-aging-statement/export-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:23.607+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/account-aging-statement/export-screen-pdf [finance:export]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:24.427+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/account-aging-statement/export-excel [finance:export]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:25.254+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/finance/aged-customer-balance-list [finance:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:26.082+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/statements [finance:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:26.915+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/statements/{id}/details [finance:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:27.733+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/create [order:insert]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:28.560+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/update [order:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:29.446+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/{id}/bulk-due-date [order:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:30.278+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/order/get/{id} [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:31.103+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/list [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:31.929+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/production-list [order:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:32.753+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/production-items/cditem-lookups [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:33.571+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/production-items/{id} [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:34.385+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/orders/production-items/{id}/insert-missing [order:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:35.206+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/orders/production-items/{id}/validate [order:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:36.027+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/orders/production-items/{id}/apply [order:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:36.841+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/close-ready [order:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:37.670+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/orders/bulk-close [order:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:38.506+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orders/export [order:export]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:39.341+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/order/check/{id} [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:40.201+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/validate [order:insert]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:41.036+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/order/pdf/{id} [order:export]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:41.857+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/order/send-market-mail [order:read]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:42.673+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/order-inventory [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:43.498+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/orderpricelistb2b [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:44.313+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/min-price [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:45.140+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/products [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:45.993+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-detail [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:46.836+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-cditem [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:47.696+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-colors [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:48.557+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-newcolors [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:49.393+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-colorsize [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:50.212+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-secondcolor [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:51.042+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-newsecondcolor [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:51.871+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-attributes [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:52.704+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-item-attributes [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:53.518+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-stock-query [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:54.344+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-stock-attribute-options [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:55.177+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-stock-query-by-attributes [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:56.013+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-images [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:56.845+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-images/{id}/content [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:57.677+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/product-size-match/rules [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:58.502+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/products [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:40:59.343+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/no-cost-products [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:00.155+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-products [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:00.974+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-history [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:01.791+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-groups [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:02.612+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-header [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:03.482+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/production-types [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:04.331+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/detail-editor-options [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:05.183+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-exchange-rates [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:06.013+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-line-history [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:06.839+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/has-cost-detail-similar-history [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:07.662+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/pricing/production-product-costing/has-cost-detail-bulk-prices [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:08.497+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/options/urun-ana-grup [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:09.318+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/options/urun-alt-grup [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:10.135+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/options/urun-ana-alt-combos [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:10.952+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/options/mtbolum [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:11.795+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/pricing/production-product-costing/maliyet-parca-eslestirme [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:12.633+03:00 level=INFO msg="✅ Route+Perm registered → DELETE /api/pricing/production-product-costing/maliyet-parca-eslestirme [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:13.473+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/pricing/production-product-costing/maliyet-parca-eslestirme/upsert [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:14.327+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/pricing/production-product-costing/maliyet-parca-eslestirme/set-active [order:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:15.176+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/roles [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:16.018+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/departments [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:16.855+03:00 level=INFO msg="✅ Route+Perm registered → GET /api/piyasalar [user:view]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:17.674+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/roles/{id}/departments [user:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:18.487+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/roles/{id}/piyasalar [user:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:19.308+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/users/{id}/roles [user:update]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:20.120+03:00 level=INFO msg="✅ Route+Perm registered → POST /api/admin/users/{id}/piyasa-sync [admin:user.update]" app=bssapp-backend
|
||||
time=2026-05-03T21:41:20.120+03:00 level=INFO msg="🌍 CORS Allowed Origin: http://ss.baggi.com.tr/app" app=bssapp-backend
|
||||
time=2026-05-03T21:41:20.121+03:00 level=INFO msg="🚀 Server running at: 0.0.0.0:8080" app=bssapp-backend
|
||||
time=2026-05-03T21:41:20.121+03:00 level=INFO msg="🕓 Translation sync next run at 2026-05-04T04:00:00+03:00 (in 6h18m40s)" app=bssapp-backend
|
||||
time=2026-05-03T21:41:20.122+03:00 level=INFO msg="listen tcp 0.0.0.0:8080: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted." app=bssapp-backend
|
||||
78
svc/utils/slog.go
Normal file
78
svc/utils/slog.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type traceIDContextKey string
|
||||
|
||||
const traceIDKey traceIDContextKey = "trace_id"
|
||||
|
||||
func InitSlog() {
|
||||
level := new(slog.LevelVar)
|
||||
switch strings.ToLower(strings.TrimSpace(os.Getenv("SLOG_LEVEL"))) {
|
||||
case "debug":
|
||||
level.Set(slog.LevelDebug)
|
||||
case "warn":
|
||||
level.Set(slog.LevelWarn)
|
||||
case "error":
|
||||
level.Set(slog.LevelError)
|
||||
default:
|
||||
level.Set(slog.LevelInfo)
|
||||
}
|
||||
|
||||
handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
|
||||
Level: level,
|
||||
AddSource: false,
|
||||
})
|
||||
|
||||
slog.SetDefault(slog.New(handler).With("app", "bssapp-backend"))
|
||||
}
|
||||
|
||||
func TraceIDFromRequest(r *http.Request) string {
|
||||
if r == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
candidates := []string{
|
||||
strings.TrimSpace(r.Header.Get("X-Trace-ID")),
|
||||
strings.TrimSpace(r.URL.Query().Get("trace_id")),
|
||||
strings.TrimSpace(r.Header.Get("X-Request-ID")),
|
||||
}
|
||||
|
||||
for _, candidate := range candidates {
|
||||
if candidate != "" {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func ContextWithTraceID(ctx context.Context, traceID string) context.Context {
|
||||
traceID = strings.TrimSpace(traceID)
|
||||
if ctx == nil || traceID == "" {
|
||||
return ctx
|
||||
}
|
||||
return context.WithValue(ctx, traceIDKey, traceID)
|
||||
}
|
||||
|
||||
func TraceIDFromContext(ctx context.Context) string {
|
||||
if ctx == nil {
|
||||
return ""
|
||||
}
|
||||
value, _ := ctx.Value(traceIDKey).(string)
|
||||
return strings.TrimSpace(value)
|
||||
}
|
||||
|
||||
func SlogFromContext(ctx context.Context) *slog.Logger {
|
||||
traceID := TraceIDFromContext(ctx)
|
||||
if traceID == "" {
|
||||
return slog.Default()
|
||||
}
|
||||
return slog.Default().With("trace_id", traceID)
|
||||
}
|
||||
Reference in New Issue
Block a user