diff --git a/svc/api/acompany.go b/svc/api/acompany.go
new file mode 100644
index 0000000..350edf4
--- /dev/null
+++ b/svc/api/acompany.go
@@ -0,0 +1,162 @@
+package api
+
+import (
+ "bordro-esleme/model/company"
+ "git.makki.io/makki/libgo/cmn"
+ "git.makki.io/makki/libgo/dbu"
+ "git.makki.io/makki/libgo/mhttp"
+ "git.makki.io/makki/libgo/nauth"
+ "github.com/go-chi/chi/v5"
+ "net/http"
+)
+
+func companyGet(w http.ResponseWriter, r *http.Request) {
+ /*
+ tc := auth.TokenDataFromRequest(r)
+ rbac, err := tc.RBAC(r.Context(), auth.MdCompany)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+ if !rbac.IsGrantedOp(auth.OpRead) && !tc.IsAdmin() {
+ mhttp.Forbidden(w)
+ return
+ }
+ */
+
+ id := cmn.StrToInt64(chi.URLParam(r, "id"))
+ data, err := company.DbRead(r.Context(), id)
+ if err != nil {
+ if dbu.IsNoRowsErr(err) {
+ mhttp.NotFound(w)
+ return
+ } else {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+ }
+
+ mhttp.ResponseSuccess(w, data)
+}
+
+func companyCreate(w http.ResponseWriter, r *http.Request) {
+ tc := nauth.TokenPayloadFromRequest(r)
+ /*
+ rbac, err := tc.RBAC(r.Context(), auth.MdCompany)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+ if !rbac.IsGrantedOp(auth.OpCreate) && !tc.IsAdmin() {
+ mhttp.Forbidden(w)
+ return
+ }
+ */
+
+ data := company.New()
+ err := cmn.BodyToJsonReq(r, &data)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+
+ err = data.DbCreate(r.Context(), true, tc.UsrID())
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+
+ mhttp.ResponseSuccess(w, data.ID)
+}
+
+func companyUpdate(w http.ResponseWriter, r *http.Request) {
+ tc := nauth.TokenPayloadFromRequest(r)
+ /*
+ rbac, err := tc.RBAC(r.Context(), auth.MdCompany)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+ if !rbac.IsGrantedOp(auth.OpUpdate) && !tc.IsAdmin() {
+ mhttp.Forbidden(w)
+ return
+ }
+ */
+
+ data := company.New()
+ err := cmn.BodyToJsonReq(r, &data)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+
+ err = data.DbUpdate(r.Context(), true, tc.UsrID())
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+
+ mhttp.ResponseSuccess(w, true)
+}
+
+func companyDelete(w http.ResponseWriter, r *http.Request) {
+ tc := nauth.TokenPayloadFromRequest(r)
+ /*
+ rbac, err := tc.RBAC(r.Context(), auth.MdCompany)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+ if !rbac.IsGrantedOp(auth.OpDelete) && !tc.IsAdmin() {
+ mhttp.Forbidden(w)
+ return
+ }
+ */
+
+ id := cmn.StrToInt64(chi.URLParam(r, "id"))
+
+ err := company.DbDelete(r.Context(), id, true, tc.UsrID())
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+
+ mhttp.ResponseSuccess(w, true)
+}
+
+func companyList(w http.ResponseWriter, r *http.Request) {
+ /*
+ tc := auth.TokenDataFromRequest(r)
+ rbac, err := tc.RBAC(r.Context(), auth.MdCompany)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+ if !rbac.IsGrantedOp(auth.OpRead) && !tc.IsAdmin() {
+ mhttp.Forbidden(w)
+ return
+ }
+ */
+
+ var data []company.Company
+
+ tr, err := dbu.NewTableRequestFromRequest(r)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+
+ rp, err := dbu.NewRepoWithFile(r.Context(), "company", nil)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+
+ respData, err := rp.MList(tr, &data)
+ if err != nil {
+ mhttp.InternalServerError(w, err)
+ return
+ }
+
+ mhttp.ResponseSuccess(w, respData)
+}
diff --git a/svc/api/public/login.go b/svc/api/public/login.go
index f960e90..3129fd5 100644
--- a/svc/api/public/login.go
+++ b/svc/api/public/login.go
@@ -13,6 +13,6 @@ func login(w http.ResponseWriter, r *http.Request) {
return
}
- clientResp := authResp.GetEndUserReponse()
+ clientResp := authResp.GetEndUserResponse()
mhttp.ResponseSuccess(w, clientResp)
}
diff --git a/svc/api/zhandler.go b/svc/api/zhandler.go
index 6bce11e..68aa576 100644
--- a/svc/api/zhandler.go
+++ b/svc/api/zhandler.go
@@ -62,7 +62,12 @@ func HttpHandler(re enums.TRunEnv) http.Handler {
// Handle valid / invalid tokens.
r.Use(nauth.CheckTokenValidity)
- r.Get("/sy/companies", napi.CompanyList)
+ // company routes
+ r.Get("/company/{id:[0-9]+}", companyGet)
+ r.Get("/company", companyList)
+ r.Put("/company", companyUpdate)
+ r.Post("/company", companyCreate)
+ r.Delete("/company/{id:[0-9]+}", companyDelete)
})
})
diff --git a/svc/go.mod b/svc/go.mod
index 2954a7a..8cfd93f 100644
--- a/svc/go.mod
+++ b/svc/go.mod
@@ -1,6 +1,6 @@
module bordro-esleme
-go 1.22.1
+go 1.22.2
toolchain go1.22.2
@@ -9,5 +9,6 @@ require (
git.notitek.com.tr/common/notgo v0.0.0-20240408194744-d12ce3096580 // indirect
github.com/go-chi/chi/v5 v5.0.12 // indirect
github.com/go-chi/cors v1.2.1 // indirect
+ github.com/guregu/null/v5 v5.0.0 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
)
diff --git a/svc/model/company/company.go b/svc/model/company/company.go
new file mode 100644
index 0000000..acab88b
--- /dev/null
+++ b/svc/model/company/company.go
@@ -0,0 +1,134 @@
+package company
+
+import (
+ "context"
+ "git.makki.io/makki/libgo/dbu"
+ "github.com/guregu/null/v5"
+ "log/slog"
+ "reflect"
+)
+
+type Company struct {
+ Clid int64 `db:"clid" json:"-"`
+ ID int64 `db:"id"`
+ Code string `db:"code"`
+ Title null.String `db:"title"`
+ IsActive bool `db:"is_active"`
+ Notes null.String `db:"notes"`
+
+ Tmpl null.String `db:"tmpl"`
+}
+
+func New() *Company {
+ m := &Company{
+ IsActive: true,
+ }
+
+ // m.__DetailStruct__ = dbu.NewDetailData[*__DetailStruct__]("__sql_filename__", "__sql_masterlink_field__", "__struct_master_field_link__", true)
+
+ return m
+}
+
+func DbRead(ctx context.Context, id int64) (*Company, error) {
+ rp, err := dbu.NewRepoWithFile(ctx, "company", nil)
+ if err != nil {
+ return nil, err
+ }
+ data := New()
+ //rp.AddDetail(data.Auths)
+ err = rp.Read(id, data)
+ return data, err
+}
+
+func (m *Company) GetIDVal() int64 {
+ return m.ID
+}
+
+func (m *Company) SetMasterLinkVal(masterField string, val int64) {
+ reflect.ValueOf(m).Elem().FieldByName(masterField).SetInt(val)
+}
+
+func DbDelete(ctx context.Context, id int64, log bool, usrID *int64) error {
+ tx, err := dbu.DB.Begin(ctx)
+ if err != nil {
+ return err
+ }
+ defer tx.Rollback(ctx)
+
+ rp, err := dbu.NewRepoWithFile(ctx, "company", tx)
+ if err != nil {
+ return err
+ }
+
+ if log {
+ var oldData *Company
+ oldData, err = DbRead(ctx, id)
+ if err != nil {
+ return dbu.ParsedErrSuppressNoRows(err)
+ }
+ err = dbu.DB.LogDMLTx("d", "company", oldData.ID, usrID, "", oldData, nil, tx)
+ if err != nil {
+ slog.Error(err.Error())
+ }
+ }
+
+ err = rp.Delete(id)
+ if err != nil {
+ return err
+ }
+
+ return tx.Commit(ctx)
+}
+
+func (m *Company) DbCreate(ctx context.Context, log bool, usrID *int64) error {
+ rp, err := dbu.NewRepoWithFile(ctx, "company", nil)
+ if err != nil {
+ return err
+ }
+
+ err = rp.Create(m)
+ if err != nil {
+ return err
+ }
+
+ if log {
+ err = dbu.DB.LogDMLTx("c", "company", m.ID, usrID, "", nil, m, nil)
+ if err != nil {
+ slog.Error(err.Error())
+ }
+ }
+
+ return nil
+}
+
+func (m *Company) DbUpdate(ctx context.Context, log bool, usrID *int64) error {
+ tx, err := dbu.DB.Begin(ctx)
+ if err != nil {
+ return err
+ }
+ defer tx.Rollback(ctx)
+
+ rp, err := dbu.NewRepoWithFile(ctx, "company", tx)
+ if err != nil {
+ return err
+ }
+
+ if log {
+ var oldData *Company
+ oldData, err = DbRead(ctx, m.ID)
+ if err != nil {
+ return err
+ }
+ err = dbu.DB.LogDMLTx("u", "company", oldData.ID, usrID, "", oldData, m, tx)
+ if err != nil {
+ slog.Error(err.Error())
+ }
+ }
+
+ err = rp.Update(m.ID, m)
+ if err != nil {
+ return err
+ }
+
+ return tx.Commit(ctx)
+}
diff --git a/ui/package.json b/ui/package.json
index f3b1094..0017fd8 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -13,12 +13,14 @@
"build": "quasar build"
},
"dependencies": {
+ "@intlify/vite-plugin-vue-i18n": "^7.0.0",
"@quasar/extras": "^1.16.4",
"axios": "^1.2.1",
"jwt-decode": "^4.0.0",
"pinia": "^2.0.11",
"quasar": "^2.8.0",
"vue": "^3.4.18",
+ "vue-i18n": "^9.9.0",
"vue-router": "^4.0.12"
},
"devDependencies": {
diff --git a/ui/quasar.config.js b/ui/quasar.config.js
index fc3579a..caf39fb 100644
--- a/ui/quasar.config.js
+++ b/ui/quasar.config.js
@@ -8,9 +8,8 @@
// Configuration for your app
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js
-
-const { configure } = require('quasar/wrappers');
-
+const { configure } = require('quasar/wrappers')
+const path = require('path')
module.exports = configure(function (ctx) {
return {
@@ -23,12 +22,14 @@ module.exports = configure(function (ctx) {
boot: [
'axios',
'version',
+ 'i18n',
'pinia',
+ 'bus',
],
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
css: [
- 'app.scss'
+ 'app.scss',
],
// https://github.com/quasarframework/quasar/tree/dev/extras
@@ -48,8 +49,8 @@ module.exports = configure(function (ctx) {
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
build: {
target: {
- browser: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
- node: 'node20'
+ browser: ['es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1'],
+ node: 'node20',
},
vueRouterMode: 'history', // available values: 'hash', 'history'
@@ -98,19 +99,34 @@ module.exports = configure(function (ctx) {
// viteVuePluginOptions: {},
vitePlugins: [
- ['vite-plugin-checker', {
+ [
+ 'vite-plugin-checker', {
eslint: {
- lintCommand: 'eslint "./**/*.{js,mjs,cjs,vue}"'
- }
- }, { server: false }]
- ]
+ lintCommand: 'eslint "./**/*.{js,mjs,cjs,vue}"',
+ },
+ }, { server: false },
+ ],
+ [
+ '@intlify/vite-plugin-vue-i18n', {
+ // if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false`
+ // compositionOnly: false,
+
+ // if you want to use named tokens in your Vue I18n messages, such as 'Hello {name}',
+ // you need to set `runtimeOnly: false`
+ // runtimeOnly: false,
+
+ // you need to set i18n resource including paths !
+ include: path.resolve(__dirname, './src/i18n/**'),
+ }
+ ],
+ ],
},
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer
devServer: {
// https: true
- port:9400,
- open: true // opens browser window automatically
+ port: 9403,
+ open: true, // opens browser window automatically
},
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework
@@ -132,8 +148,8 @@ module.exports = configure(function (ctx) {
'Notify',
'Loading',
'Dialog',
- 'Meta'
- ]
+ 'Meta',
+ ],
},
// animations: 'all', // --- includes all animations
@@ -155,7 +171,7 @@ module.exports = configure(function (ctx) {
// https://v2.quasar.dev/quasar-cli-vite/developing-ssr/configuring-ssr
ssr: {
// ssrPwaHtmlFilename: 'offline.html', // do NOT use index.html as name!
- // will mess up SSR
+ // will mess up SSR
// extendSSRWebserverConf (esbuildConf) {},
// extendPackageJson (json) {},
@@ -169,8 +185,8 @@ module.exports = configure(function (ctx) {
// (gets superseded if process.env.PORT is specified at runtime)
middlewares: [
- 'render' // keep this as last one
- ]
+ 'render', // keep this as last one
+ ],
},
// https://v2.quasar.dev/quasar-cli-vite/developing-pwa/configuring-pwa
@@ -194,7 +210,7 @@ module.exports = configure(function (ctx) {
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor
capacitor: {
- hideSplashscreen: true
+ hideSplashscreen: true,
},
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/configuring-electron
@@ -223,18 +239,18 @@ module.exports = configure(function (ctx) {
builder: {
// https://www.electron.build/configuration/configuration
- appId: 'tr.com.notitek.bres'
- }
+ appId: 'tr.com.notitek.bres',
+ },
},
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-browser-extensions/configuring-bex
bex: {
contentScripts: [
- 'my-content-script'
+ 'my-content-script',
],
// extendBexScriptsConf (esbuildConf) {}
// extendBexManifestJson (json) {}
- }
+ },
}
-});
+})
diff --git a/ui/src/boot/bus.js b/ui/src/boot/bus.js
new file mode 100644
index 0000000..253f14a
--- /dev/null
+++ b/ui/src/boot/bus.js
@@ -0,0 +1,14 @@
+// a Quasar CLI boot file (let's say /src/boot/bus.js)
+
+import { EventBus } from 'quasar'
+import { boot } from 'quasar/wrappers'
+
+export default boot(({ app }) => {
+ const bus = new EventBus()
+
+ // for Options API
+ app.config.globalProperties.$bus = bus
+
+ // for Composition API
+ app.provide('bus', bus)
+})
diff --git a/ui/src/boot/i18n.js b/ui/src/boot/i18n.js
new file mode 100644
index 0000000..c260391
--- /dev/null
+++ b/ui/src/boot/i18n.js
@@ -0,0 +1,16 @@
+import { boot } from 'quasar/wrappers'
+import { createI18n } from 'vue-i18n'
+import messages from 'src/i18n'
+
+const i18n = createI18n({
+ locale: 'tr',
+ globalInjection: true,
+ messages
+})
+
+export default boot(({ app }) => {
+ // Set i18n instance on app
+ app.use(i18n)
+})
+
+export { i18n }
diff --git a/ui/src/i18n/en.js b/ui/src/i18n/en.js
new file mode 100644
index 0000000..3a6e443
--- /dev/null
+++ b/ui/src/i18n/en.js
@@ -0,0 +1,9 @@
+import base from "src/libjs/i18n/en"
+
+const prjI18n = {
+ menu: {
+ app: 'Applications'
+ },
+}
+
+export default {...base, ...prjI18n}
diff --git a/ui/src/i18n/index.js b/ui/src/i18n/index.js
new file mode 100644
index 0000000..7a4c0c9
--- /dev/null
+++ b/ui/src/i18n/index.js
@@ -0,0 +1,8 @@
+import enUS from './en'
+import trTR from './tr'
+
+export default {
+ 'tr': trTR,
+ 'en-US': enUS,
+ 'en-GB': enUS,
+}
diff --git a/ui/src/i18n/tr.js b/ui/src/i18n/tr.js
new file mode 100644
index 0000000..27a00e6
--- /dev/null
+++ b/ui/src/i18n/tr.js
@@ -0,0 +1,10 @@
+import base from "src/libjs/i18n/tr"
+
+const prjI18n = {
+ menu: {
+ app: 'Uygulamalar'
+ },
+ Usr: {},
+}
+
+export default {...base, ...prjI18n}
diff --git a/ui/src/layouts/panelLayout.vue b/ui/src/layouts/panelLayout.vue
index 3a51ad2..8717514 100644
--- a/ui/src/layouts/panelLayout.vue
+++ b/ui/src/layouts/panelLayout.vue
@@ -1,26 +1,53 @@
-
-
+
+
+
+
+
+
+ Bordro Eşleme
+
+ {{ $VERSION.version }}
+
+ {{ $VERSION.build }}
+
+
-
-
-
-
-
+
+
+
+
+
+
+ {{ m.label }}
+
+
+
+
+
+
+
+
+ {{ c.label }}
+
+
+
+
-
-
-
-
+
+
+
@@ -29,11 +56,23 @@
diff --git a/ui/src/pages/companyList.vue b/ui/src/pages/companyList.vue
new file mode 100644
index 0000000..d456bba
--- /dev/null
+++ b/ui/src/pages/companyList.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/pages/index.vue b/ui/src/pages/index.vue
index a595c2d..69625e5 100644
--- a/ui/src/pages/index.vue
+++ b/ui/src/pages/index.vue
@@ -1,14 +1,15 @@
-
-
+
+