Compare commits

..

2 Commits

Author SHA1 Message Date
MEHMETKECECI
76fa2040b1 Merge remote-tracking branch 'origin/master' 2026-02-14 10:36:50 +03:00
MEHMETKECECI
563bc0a0b6 Merge remote-tracking branch 'origin/master' 2026-02-14 10:23:57 +03:00
8 changed files with 129 additions and 64 deletions

View File

@@ -2,6 +2,8 @@ JWT_SECRET=bssapp_super_secret_key_1234567890
PASSWORD_RESET_SECRET=1dc7d6d52fd0459a8b1f288a6590428e760f54339f8e47beb20db36b6df6070b PASSWORD_RESET_SECRET=1dc7d6d52fd0459a8b1f288a6590428e760f54339f8e47beb20db36b6df6070b
APP_FRONTEND_URL=http://localhost:9000 APP_FRONTEND_URL=http://localhost:9000
API_URL=http://localhost:8080 API_URL=http://localhost:8080
UI_DIR=/opt/bssapp/ui/dist
POSTGRES_CONN=host=127.0.0.1 port=5432 user=postgres password=tayitkan dbname=baggib2b sslmode=disable

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"strings"
"time" "time"
_ "github.com/lib/pq" _ "github.com/lib/pq"
@@ -37,7 +38,32 @@ func ConnectPostgres() (*sql.DB, error) {
// 🔹 Test et // 🔹 Test et
if err = db.Ping(); err != nil { if err = db.Ping(); err != nil {
return nil, fmt.Errorf("PostgreSQL erişilemiyor: %w", err) // Some managed PostgreSQL servers require TLS. If the current DSN uses
// sslmode=disable and server rejects with "no encryption", retry once
// with sslmode=require to avoid startup failure.
if strings.Contains(err.Error(), "no pg_hba.conf entry") &&
strings.Contains(err.Error(), "no encryption") &&
strings.Contains(strings.ToLower(connStr), "sslmode=disable") {
secureConnStr := strings.Replace(connStr, "sslmode=disable", "sslmode=require", 1)
log.Println("⚠️ PostgreSQL requires TLS, retrying with sslmode=require")
_ = db.Close()
db, err = sql.Open("postgres", secureConnStr)
if err != nil {
return nil, fmt.Errorf("PostgreSQL TLS retry open failed: %w", err)
}
db.SetMaxOpenConns(30)
db.SetMaxIdleConns(10)
db.SetConnMaxLifetime(30 * time.Minute)
db.SetConnMaxIdleTime(5 * time.Minute)
if err = db.Ping(); err != nil {
return nil, fmt.Errorf("PostgreSQL erişilemiyor (TLS retry): %w", err)
}
} else {
return nil, fmt.Errorf("PostgreSQL erişilemiyor: %w", err)
}
} }
log.Println("✅ PostgreSQL bağlantısı başarılı!") log.Println("✅ PostgreSQL bağlantısı başarılı!")

1
ui/.env.development Normal file
View File

@@ -0,0 +1 @@
VITE_API_BASE_URL=http://localhost:8080

1
ui/.env.production Normal file
View File

@@ -0,0 +1 @@
VITE_API_BASE_URL=/api

View File

@@ -4,52 +4,89 @@ import { defineConfig } from '#q-app/wrappers'
export default defineConfig(() => { export default defineConfig(() => {
return { return {
// ✅ UYGULAMA KİMLİĞİ (WEB'DE GÖRÜNEN İSİM) /* =====================================================
APP INFO
===================================================== */
productName: 'Baggi BSS', productName: 'Baggi BSS',
productDescription: 'Baggi Tekstil Business Support System', productDescription: 'Baggi Tekstil Business Support System',
// 🔹 Boot dosyaları /* =====================================================
boot: ['axios', 'dayjs'], BOOT FILES
===================================================== */
boot: ['dayjs'],
// 🔹 Global CSS /* =====================================================
GLOBAL CSS
===================================================== */
css: ['app.css'], css: ['app.css'],
// 🔹 Ekstra icon/font setleri /* =====================================================
ICONS / FONTS
===================================================== */
extras: [ extras: [
'roboto-font', 'roboto-font',
'material-icons' 'material-icons'
], ],
// 🔹 Derleme Ayarları /* =====================================================
BUILD (PRODUCTION)
===================================================== */
build: { build: {
vueRouterMode: 'hash', vueRouterMode: 'hash',
env: {
VITE_API_BASE_URL: 'http://localhost:8080/api'
},
esbuildTarget: { esbuildTarget: {
browser: ['es2022', 'firefox115', 'chrome115', 'safari14'], browser: ['es2022', 'firefox115', 'chrome115', 'safari14'],
node: 'node20' node: 'node20'
} },
// Cache & performance
gzip: true,
preloadChunks: true
}, },
// 🔹 Geliştirme Sunucusu /* =====================================================
DEV SERVER (LOCAL)
===================================================== */
devServer: { devServer: {
server: { type: 'http' }, server: { type: 'http' },
port: 9000, port: 9000,
open: true open: true,
// DEV proxy (CORSsuz)
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
secure: false
}
}
}, },
// 🔹 Quasar Framework ayarları /* =====================================================
QUASAR FRAMEWORK
===================================================== */
framework: { framework: {
config: { config: {
notify: { position: 'top', timeout: 2500 } notify: {
position: 'top',
timeout: 2500
}
}, },
lang: 'tr', lang: 'tr',
plugins: ['Loading', 'Dialog', 'Notify']
plugins: [
'Loading',
'Dialog',
'Notify'
]
}, },
animations: [], animations: [],
/* =====================================================
SSR / PWA (DISABLED)
===================================================== */
ssr: { ssr: {
prodPort: 3000, prodPort: 3000,
middlewares: ['render'], middlewares: ['render'],
@@ -60,6 +97,9 @@ export default defineConfig(() => {
workboxMode: 'GenerateSW' workboxMode: 'GenerateSW'
}, },
/* =====================================================
MOBILE / DESKTOP
===================================================== */
capacitor: { capacitor: {
hideSplashscreen: true hideSplashscreen: true
}, },
@@ -68,7 +108,10 @@ export default defineConfig(() => {
preloadScripts: ['electron-preload'], preloadScripts: ['electron-preload'],
inspectPort: 5858, inspectPort: 5858,
bundler: 'packager', bundler: 'packager',
builder: { appId: 'baggisowtfaresystem' }
builder: {
appId: 'baggisowtfaresystem'
}
}, },
bex: { bex: {

View File

@@ -1,21 +0,0 @@
import { boot } from 'quasar/wrappers'
import axios from 'axios'
export const api = axios.create({
baseURL: 'http://localhost:8080/api',
timeout: 180000,
withCredentials: true // refresh cookie kullanıyorsan kalsın
})
export default boot(() => {
api.interceptors.request.use((config) => {
const token = localStorage.getItem('token') // ✅ senin authStore keyin
if (token) {
config.headers = config.headers || {}
config.headers.Authorization = `Bearer ${token}`
}
return config
})
})

View File

@@ -233,6 +233,7 @@ import { useQuasar } from 'quasar'
import { useOrderListStore } from 'src/stores/OrdernewListStore' import { useOrderListStore } from 'src/stores/OrdernewListStore'
import { useAuthStore } from 'src/stores/authStore' import { useAuthStore } from 'src/stores/authStore'
import { usePermission } from 'src/composables/usePermission' import { usePermission } from 'src/composables/usePermission'
import api from 'src/services/api'
const { canRead } = usePermission() const { canRead } = usePermission()
const canReadOrder = canRead('order') const canReadOrder = canRead('order')
@@ -270,22 +271,24 @@ function exportExcel () {
OrderDate: store.filters.OrderDate || '' OrderDate: store.filters.OrderDate || ''
}) })
const url = `http://localhost:8080/api/orders/export?${params.toString()}` api.get(`/orders/export?${params.toString()}`, {
responseType: 'blob'
fetch(url, {
headers: {
Authorization: `Bearer ${auth.token}`
}
}) })
.then(res => res.blob()) .then(res => res.data)
.then(blob => { .then(blob => {
const link = document.createElement('a') const link = document.createElement('a')
link.href = URL.createObjectURL(blob) link.href = URL.createObjectURL(blob)
link.download = 'siparis_listesi.xlsx' link.download = 'siparis_listesi.xlsx'
link.click() link.click()
}) })
.catch(() => {
$q.notify({
type: 'negative',
message: 'Excel dosyasi indirilemedi',
position: 'top-right'
})
})
} }
function formatDate (s) { function formatDate (s) {
if (!s) return '' if (!s) return ''
const [y, m, d] = String(s).split('-') const [y, m, d] = String(s).split('-')
@@ -383,23 +386,16 @@ function selectOrder (row) {
async function printPDF (row) { async function printPDF (row) {
if (!row?.OrderHeaderID) return if (!row?.OrderHeaderID) return
const token = useAuthStore().token
const url = `http://localhost:8080/api/order/pdf/${row.OrderHeaderID}`
try { try {
const res = await fetch(url, { const res = await api.get(`/order/pdf/${row.OrderHeaderID}`, {
headers: { Authorization: `Bearer ${token}` } responseType: 'blob'
}) })
if (!res.ok) throw new Error() window.open(URL.createObjectURL(res.data), '_blank')
const blob = await res.blob()
window.open(URL.createObjectURL(blob), '_blank')
} catch { } catch {
$q.notify({ type: 'negative', message: 'PDF yüklenemedi' }) $q.notify({ type: 'negative', message: 'PDF yüklenemedi' })
} }
} }
function clearFilters () { function clearFilters () {
store.filters.search = '' store.filters.search = ''
store.filters.CurrAccCode = '' store.filters.CurrAccCode = ''
@@ -562,3 +558,4 @@ onMounted(() => {
} }
} }
</style> </style>

View File

@@ -3,14 +3,21 @@ import axios from 'axios'
import qs from 'qs' import qs from 'qs'
import { useAuthStore } from 'stores/authStore' import { useAuthStore } from 'stores/authStore'
// ✅ Vite uyumlu env okuma
export const API_BASE_URL =
import.meta.env.VITE_API_BASE_URL || '/api'
const api = axios.create({ const api = axios.create({
baseURL: 'http://localhost:8080/api', baseURL: API_BASE_URL,
timeout: 180000, timeout: 180000,
paramsSerializer: params => paramsSerializer: params =>
qs.stringify(params, { arrayFormat: 'repeat' }) qs.stringify(params, { arrayFormat: 'repeat' }),
withCredentials: true
}) })
// REQUEST /* ============================
REQUEST INTERCEPTOR
============================ */
api.interceptors.request.use((config) => { api.interceptors.request.use((config) => {
const auth = useAuthStore() const auth = useAuthStore()
const url = config.url || '' const url = config.url || ''
@@ -21,7 +28,6 @@ api.interceptors.request.use((config) => {
url.startsWith('/password/forgot') || url.startsWith('/password/forgot') ||
url.startsWith('/password/reset') url.startsWith('/password/reset')
if (!isPublic && auth?.token) { if (!isPublic && auth?.token) {
config.headers ||= {} config.headers ||= {}
config.headers.Authorization = `Bearer ${auth.token}` config.headers.Authorization = `Bearer ${auth.token}`
@@ -30,8 +36,11 @@ api.interceptors.request.use((config) => {
return config return config
}) })
// RESPONSE /* ============================
RESPONSE INTERCEPTOR
============================ */
let isLoggingOut = false let isLoggingOut = false
api.interceptors.response.use( api.interceptors.response.use(
r => r, r => r,
async (error) => { async (error) => {
@@ -43,11 +52,15 @@ api.interceptors.response.use(
isLoggingOut = false isLoggingOut = false
} }
} }
return Promise.reject(error) return Promise.reject(error)
} }
) )
// HELPERS /* ============================
HELPERS
============================ */
export const get = (u, p = {}, c = {}) => export const get = (u, p = {}, c = {}) =>
api.get(u, { params: p, ...c }).then(r => r.data) api.get(u, { params: p, ...c }).then(r => r.data)
@@ -61,7 +74,10 @@ export const del = (u, p = {}, c = {}) =>
api.delete(u, { params: p, ...c }).then(r => r.data) api.delete(u, { params: p, ...c }).then(r => r.data)
export const download = (u, p = {}, c = {}) => export const download = (u, p = {}, c = {}) =>
api.get(u, { params: p, responseType: 'blob', ...c }) api.get(u, {
.then(r => r.data) params: p,
responseType: 'blob',
...c
}).then(r => r.data)
export default api export default api