Merge remote-tracking branch 'origin/master'
This commit is contained in:
2
svc/.env
2
svc/.env
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
1
ui/.env.development
Normal file
@@ -0,0 +1 @@
|
|||||||
|
VITE_API_BASE_URL=http://localhost:8080
|
||||||
1
ui/.env.production
Normal file
1
ui/.env.production
Normal file
@@ -0,0 +1 @@
|
|||||||
|
VITE_API_BASE_URL=/api
|
||||||
@@ -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 (CORS’suz)
|
||||||
|
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: {
|
||||||
|
|||||||
@@ -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 key’in
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
config.headers = config.headers || {}
|
|
||||||
config.headers.Authorization = `Bearer ${token}`
|
|
||||||
}
|
|
||||||
|
|
||||||
return config
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ import axios from 'axios'
|
|||||||
import qs from 'qs'
|
import qs from 'qs'
|
||||||
import { useAuthStore } from 'stores/authStore'
|
import { useAuthStore } from 'stores/authStore'
|
||||||
|
|
||||||
|
export const API_BASE_URL = process.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
|
||||||
@@ -21,7 +24,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}`
|
||||||
@@ -32,6 +34,7 @@ api.interceptors.request.use((config) => {
|
|||||||
|
|
||||||
// RESPONSE
|
// RESPONSE
|
||||||
let isLoggingOut = false
|
let isLoggingOut = false
|
||||||
|
|
||||||
api.interceptors.response.use(
|
api.interceptors.response.use(
|
||||||
r => r,
|
r => r,
|
||||||
async (error) => {
|
async (error) => {
|
||||||
@@ -47,7 +50,6 @@ api.interceptors.response.use(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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 +63,6 @@ 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, { params: p, responseType: 'blob', ...c }).then(r => r.data)
|
||||||
.then(r => r.data)
|
|
||||||
|
|
||||||
export default api
|
export default api
|
||||||
|
|||||||
Reference in New Issue
Block a user