Compare commits

...

10 Commits

Author SHA1 Message Date
51d8f0822f update migration 2025-01-15 14:05:43 +03:00
ctengiz
a2215b9363 upgrade code 2025-01-15 11:50:12 +03:00
ctengiz
20e4a15286 nadmin fixes 2024-06-23 21:09:24 +03:00
ctengiz
29ca0b9965 fix 2024-06-14 17:21:20 +03:00
ctengiz
f54c5660ea comnpany to cm 2024-06-14 17:19:38 +03:00
ctengiz
a28576960e kriter değeri ekleme, hesap kodu kopyalama, excel okuma, kriter güncelleme 2024-04-29 17:21:02 +03:00
ctengiz
a661c06639 maliyet dağıtım fix 2024-04-25 13:51:46 +03:00
ctengiz
b9ed81beb7 maliyet dağıtımı 2024-04-25 12:14:48 +03:00
ctengiz
06f834e8c9 birleşik kriter 2024-04-19 10:57:57 +03:00
ctengiz
945b479309 menu icons 2024-04-19 10:52:53 +03:00
22 changed files with 826 additions and 178 deletions

View File

@@ -0,0 +1,12 @@
alter table company
rename to cm;
alter table cm
rename column title to name;
alter table company_usr
rename to cm_usr;
alter table cm_usr
rename column company_id to cm_id;

View File

@@ -0,0 +1,3 @@
alter table cm_usr drop constraint uq_company_usr;
alter table cm_usr rename cm_id to cmid;
alter table cm_usr add constraint uq_cm_usr unique (cmid, usr_id);

View File

@@ -1,13 +1,13 @@
-- << Create -- << Create
insert into company ( clid insert into cm ( clid
, code , code
, title , name
, is_active , is_active
, notes , notes
, tmpl) , tmpl)
values ( @clid values ( @clid
, @code , @code
, @title , @name
, @is_active , @is_active
, @notes , @notes
, @tmpl) , @tmpl)
@@ -18,20 +18,19 @@ returning id
select clid select clid
, id , id
, code , code
, title , name
, is_active , is_active
, notes , notes
, tmpl , tmpl
from company from cm
where id = $1 where id = $1
-- Read >> -- Read >>
-- << Update -- << Update
update company update cm
set clid = @clid set code = @code
, code = @code , name = @name
, title = @title
, is_active = @is_active , is_active = @is_active
, notes = @notes , notes = @notes
, tmpl = @tmpl , tmpl = @tmpl
@@ -41,7 +40,7 @@ where id = @id
-- << Delete -- << Delete
delete delete
from company from cm
where id = $1 where id = $1
-- Delete >> -- Delete >>
@@ -49,12 +48,12 @@ where id = $1
select clid select clid
, id , id
, code , code
, title , name
, is_active , is_active
, notes , notes
, tmpl , tmpl
from company {{.Where}} from cm {{.Where}}
{{.OrderBy}} {{.OrderBy}}
{{.Rows}} {{.Rows}}
-- List >> -- List >>

Binary file not shown.

View File

@@ -5,7 +5,7 @@ import (
"git.makki.io/makki/libgo/cmn" "git.makki.io/makki/libgo/cmn"
"git.makki.io/makki/libgo/dbu" "git.makki.io/makki/libgo/dbu"
"git.makki.io/makki/libgo/mhttp" "git.makki.io/makki/libgo/mhttp"
"git.makki.io/makki/libgo/nauth" "git.notitek.com.tr/common/notgo/nauth"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"net/http" "net/http"
) )
@@ -146,7 +146,7 @@ func companyList(w http.ResponseWriter, r *http.Request) {
return return
} }
rp, err := dbu.NewRepoWithFile(r.Context(), "company", nil) rp, err := dbu.NewRepoWithFile(r.Context(), "cm", nil)
if err != nil { if err != nil {
mhttp.InternalServerError(w, err) mhttp.InternalServerError(w, err)
return return

View File

@@ -19,7 +19,7 @@ func tmplPost(w http.ResponseWriter, r *http.Request) {
return return
} }
sq := "update company set tmpl = $2 where id = $1" sq := "update cm set tmpl = $2 where id = $1"
_, err = dbu.DB.Exec(r.Context(), sq, companyID, body) _, err = dbu.DB.Exec(r.Context(), sq, companyID, body)
if err != nil { if err != nil {
mhttp.InternalServerError(w, err) mhttp.InternalServerError(w, err)
@@ -33,7 +33,7 @@ func tmplGet(w http.ResponseWriter, r *http.Request) {
companyID := cmn.StrToInt64(chi.URLParam(r, "companyID")) companyID := cmn.StrToInt64(chi.URLParam(r, "companyID"))
var body json.RawMessage var body json.RawMessage
sq := "select tmpl from company where id = $1" sq := "select tmpl from cm where id = $1"
err := dbu.DB.QueryRow(r.Context(), sq, companyID).Scan(&body) err := dbu.DB.QueryRow(r.Context(), sq, companyID).Scan(&body)
if err != nil { if err != nil {
mhttp.InternalServerError(w, err) mhttp.InternalServerError(w, err)

View File

@@ -1,18 +0,0 @@
package public
import (
"git.makki.io/makki/libgo/mhttp"
"git.makki.io/makki/libgo/svc"
"net/http"
)
func login(w http.ResponseWriter, r *http.Request) {
authResp, err := svc.S.Authenticate(r)
if err != nil {
mhttp.InternalServerError(w, err)
return
}
clientResp := authResp.GetEndUserResponse()
mhttp.ResponseSuccess(w, clientResp)
}

View File

@@ -1,14 +0,0 @@
package public
import (
"github.com/go-chi/chi/v5"
"net/http"
)
func Router() http.Handler {
r := chi.NewRouter()
// user authentication
r.Post("/login", login)
return r
}

View File

@@ -1,10 +1,10 @@
package api package api
import ( import (
"bordro-esleme/api/public"
"fmt" "fmt"
"git.makki.io/makki/libgo/napi" "git.makki.io/makki/libgo/mhttp"
"git.makki.io/makki/libgo/nauth" "git.notitek.com.tr/common/notgo/napi"
"git.notitek.com.tr/common/notgo/nauth"
"net/http" "net/http"
"os" "os"
"path" "path"
@@ -20,6 +20,20 @@ import (
) )
func HttpHandler(re enums.TRunEnv) http.Handler { func HttpHandler(re enums.TRunEnv) http.Handler {
lookup := &mhttp.Lookup{
DoClientCheck: true,
Funcs: map[string]mhttp.LookupFunc{
"entegrator": napi.Entegrators,
"invmarket": napi.InvMarket,
"usr": napi.Usr,
"rates": napi.Currency,
},
CompanyCheckQueries: []string{"mmitem", "acchart", "ficomp"},
JwtAuth: svc.S.JWT,
}
mux := chi.NewRouter() mux := chi.NewRouter()
// Gerekli middleware stack // Gerekli middleware stack
@@ -51,17 +65,25 @@ func HttpHandler(re enums.TRunEnv) http.Handler {
mux.Route("/api", func(mr chi.Router) { mux.Route("/api", func(mr chi.Router) {
// Public Route endpoints // Public Route endpoints
mr.Mount("/", public.Router()) mr.Post("/login", napi.Login)
//mr.Mount("/admin", admin.Router())
//protected end points //protected end points
mr.Group(func(r chi.Router) { mr.Group(func(r chi.Router) {
// Seek, verify and validate JWT tokens // Seek, verify and validate JWT tokens
r.Use(jwtauth.Verifier(svc.S.JWT)) r.Use(jwtauth.Verify(svc.S.JWT, jwtauth.TokenFromHeader, jwtauth.TokenFromCookie, jwtauth.TokenFromQuery))
// Handle valid / invalid tokens. // Handle valid / invalid tokens.
r.Use(nauth.CheckTokenValidity) r.Use(nauth.CheckTokenValidity)
// Set clientID
r.Use(nauth.ClientID)
// Handle valid / invalid tokens.
r.Use(nauth.CheckTokenValidity)
// lookup
r.Method("post", "/lookup/{query}", lookup)
// sy routes // sy routes
r.Get("/sy/companies", napi.CompanyList) r.Get("/sy/companies", napi.CompanyList)

View File

@@ -5,6 +5,7 @@ import (
"git.makki.io/makki/libgo/dbu" "git.makki.io/makki/libgo/dbu"
"git.makki.io/makki/libgo/mlog" "git.makki.io/makki/libgo/mlog"
"git.makki.io/makki/libgo/svc" "git.makki.io/makki/libgo/svc"
"git.notitek.com.tr/common/notgo/nauth"
"time" "time"
) )
@@ -35,7 +36,7 @@ func main() {
if svc.S.DevMode() { if svc.S.DevMode() {
expire = time.Hour * 48 expire = time.Hour * 48
} }
err = s.SubscribeToAuthServer(expire) err = nauth.SubscribeToAuthServer(s.Ctx, expire)
if err != nil { if err != nil {
mlog.Fatal(err) mlog.Fatal(err)
} }

View File

@@ -9,10 +9,10 @@ import (
) )
type Company struct { type Company struct {
Clid int64 `db:"clid" json:"-"` ClID int64 `db:"clid" json:"-"`
ID int64 `db:"id"` ID int64 `db:"id"`
Code string `db:"code"` Code string `db:"code"`
Title null.String `db:"title"` Name null.String `db:"name"`
IsActive bool `db:"is_active"` IsActive bool `db:"is_active"`
Notes null.String `db:"notes"` Notes null.String `db:"notes"`
@@ -30,7 +30,7 @@ func New() *Company {
} }
func DbRead(ctx context.Context, id int64) (*Company, error) { func DbRead(ctx context.Context, id int64) (*Company, error) {
rp, err := dbu.NewRepoWithFile(ctx, "company", nil) rp, err := dbu.NewRepoWithFile(ctx, "cm", nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -55,7 +55,7 @@ func DbDelete(ctx context.Context, id int64, log bool, usrID *int64) error {
} }
defer tx.Rollback(ctx) defer tx.Rollback(ctx)
rp, err := dbu.NewRepoWithFile(ctx, "company", tx) rp, err := dbu.NewRepoWithFile(ctx, "cm", tx)
if err != nil { if err != nil {
return err return err
} }
@@ -66,7 +66,7 @@ func DbDelete(ctx context.Context, id int64, log bool, usrID *int64) error {
if err != nil { if err != nil {
return dbu.ParsedErrSuppressNoRows(err) return dbu.ParsedErrSuppressNoRows(err)
} }
err = dbu.DB.LogDMLTx("d", "company", oldData.ID, usrID, "", oldData, nil, tx) err = dbu.DB.LogDMLTx("d", "cm", oldData.ID, usrID, "", oldData, nil, tx)
if err != nil { if err != nil {
slog.Error(err.Error()) slog.Error(err.Error())
} }
@@ -81,9 +81,9 @@ func DbDelete(ctx context.Context, id int64, log bool, usrID *int64) error {
} }
func (m *Company) DbCreate(ctx context.Context, clID int64, log bool, usrID *int64) error { func (m *Company) DbCreate(ctx context.Context, clID int64, log bool, usrID *int64) error {
m.Clid = clID m.ClID = clID
rp, err := dbu.NewRepoWithFile(ctx, "company", nil) rp, err := dbu.NewRepoWithFile(ctx, "cm", nil)
if err != nil { if err != nil {
return err return err
} }
@@ -94,7 +94,7 @@ func (m *Company) DbCreate(ctx context.Context, clID int64, log bool, usrID *int
} }
if log { if log {
err = dbu.DB.LogDMLTx("c", "company", m.ID, usrID, "", nil, m, nil) err = dbu.DB.LogDMLTx("c", "cm", m.ID, usrID, "", nil, m, nil)
if err != nil { if err != nil {
slog.Error(err.Error()) slog.Error(err.Error())
} }
@@ -110,7 +110,7 @@ func (m *Company) DbUpdate(ctx context.Context, log bool, usrID *int64) error {
} }
defer tx.Rollback(ctx) defer tx.Rollback(ctx)
rp, err := dbu.NewRepoWithFile(ctx, "company", tx) rp, err := dbu.NewRepoWithFile(ctx, "cm", tx)
if err != nil { if err != nil {
return err return err
} }
@@ -121,7 +121,7 @@ func (m *Company) DbUpdate(ctx context.Context, log bool, usrID *int64) error {
if err != nil { if err != nil {
return err return err
} }
err = dbu.DB.LogDMLTx("u", "company", oldData.ID, usrID, "", oldData, m, tx) err = dbu.DB.LogDMLTx("u", "cm", oldData.ID, usrID, "", oldData, m, tx)
if err != nil { if err != nil {
slog.Error(err.Error()) slog.Error(err.Error())
} }

View File

@@ -19,6 +19,7 @@
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"pinia": "^2.0.11", "pinia": "^2.0.11",
"quasar": "^2.8.0", "quasar": "^2.8.0",
"reconnecting-websocket": "^4.4.0",
"vue": "^3.4.18", "vue": "^3.4.18",
"vue-i18n": "^9.9.0", "vue-i18n": "^9.9.0",
"vue-router": "^4.0.12", "vue-router": "^4.0.12",

View File

@@ -64,6 +64,7 @@ module.exports = configure(function (ctx) {
// analyze: true, // analyze: true,
env: { env: {
showLangSelect: false, showLangSelect: false,
wsActive: false,
apiAddr: (() => { apiAddr: (() => {
if (process.env.CUSTOM_API) { if (process.env.CUSTOM_API) {
return process.env.CUSTOM_API return process.env.CUSTOM_API
@@ -150,6 +151,8 @@ module.exports = configure(function (ctx) {
'Loading', 'Loading',
'Dialog', 'Dialog',
'Meta', 'Meta',
'LocalStorage',
'SessionStorage'
], ],
}, },

View File

@@ -3,12 +3,14 @@
import { EventBus } from 'quasar' import { EventBus } from 'quasar'
import { boot } from 'quasar/wrappers' import { boot } from 'quasar/wrappers'
export default boot(({ app }) => { const bus = new EventBus()
const bus = new EventBus()
export default boot(({ app }) => {
// for Options API // for Options API
app.config.globalProperties.$bus = bus app.config.globalProperties.$bus = bus
// for Composition API // for Composition API
app.provide('bus', bus) app.provide('bus', bus)
}) })
export { bus }

View File

@@ -5,6 +5,7 @@ const prjI18n = {
app: 'Uygulamalar' app: 'Uygulamalar'
}, },
Company: { Company: {
ID: 'Şirket ID',
Code: 'Şirket Kod', Code: 'Şirket Kod',
Title: 'Şirket Ad', Title: 'Şirket Ad',
IsActive: 'Kullanımda', IsActive: 'Kullanımda',

View File

@@ -12,14 +12,14 @@ const tmenu = [
{ {
label: 'Şablon Tasarımı', label: 'Şablon Tasarımı',
icon: 'business', icon: 'design_services',
grantKey: 'Tmpl', grantKey: 'Tmpl',
to: '/tmpl' to: '/tmpl'
}, },
{ {
label: 'Bordro Eşleme', label: 'Bordro Eşleme',
icon: 'business', icon: 'summarize',
grantKey: 'Map', grantKey: 'Map',
to: '/map' to: '/map'
}, },

View File

@@ -5,14 +5,12 @@ const t = i18n.global.t
class Company extends Model { class Company extends Model {
ID = null ID = null
Code = '' Code = ''
Title = '' Name = ''
IsActive = true IsActive = true
Notes = '' Notes = ''
Tmpl = '' Tmpl = ''
_colOptions = { _colOptions = {
ID: { ID: {
label: t('Company.ID'), label: t('Company.ID'),
@@ -40,7 +38,7 @@ class Company extends Model {
}, },
Title: { Name: {
label: t('Company.Title'), label: t('Company.Title'),
visible: true, visible: true,
dataType: 'text', //numeric, text, date, bool, datetime, time, inet dataType: 'text', //numeric, text, date, bool, datetime, time, inet

View File

@@ -21,7 +21,7 @@
/> />
<q-input class="col-xs-12 col-sm-6" <q-input class="col-xs-12 col-sm-6"
v-model="model.Title" v-model="model.Name"
:label="t('Company.Title')" :label="t('Company.Title')"
bottom-slots bottom-slots
:rules="[]" :rules="[]"

View File

@@ -10,7 +10,7 @@
:label="t('selectCompany')" :label="t('selectCompany')"
:options="ld.companies" :options="ld.companies"
option-value="ID" option-value="ID"
option-label="Title" option-label="Name"
dense dense
options-dense options-dense
outlined outlined
@@ -70,7 +70,7 @@
</template> </template>
<script setup> <script setup>
import { computed, onMounted, reactive, toRaw } from 'vue' import { onMounted, reactive } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { api } from 'boot/axios' import { api } from 'boot/axios'
import { catchAxiosError, showAxiosError } from 'src/libjs/lib/axios' import { catchAxiosError, showAxiosError } from 'src/libjs/lib/axios'
@@ -107,9 +107,9 @@ const tmpl = reactive({
alanlar: [], alanlar: [],
kriterler: {}, kriterler: {},
dagitim: {}
}) })
onMounted(() => { onMounted(() => {
getCompanyList() getCompanyList()
}) })
@@ -145,7 +145,7 @@ const load = function () {
ld.canProcess = false ld.canProcess = false
$q.dialog({ $q.dialog({
title: 'Hata', title: 'Hata',
message: 'Şirket için tanımlı şablon yok' message: 'Şirket için tanımlı şablon yok',
}).onOk(() => { }).onOk(() => {
// console.log('OK') // console.log('OK')
}).onCancel(() => { }).onCancel(() => {
@@ -186,7 +186,6 @@ const load = function () {
}) })
} }
let workbook = null let workbook = null
const loadFile = function () { const loadFile = function () {
@@ -199,7 +198,6 @@ const loadFile = function () {
*/ */
reader.onload = function (e) { reader.onload = function (e) {
const uin = new Uint8Array(e.target.result) const uin = new Uint8Array(e.target.result)
@@ -212,7 +210,7 @@ const loadFile = function () {
$q.loading.show() $q.loading.show()
reader.readAsArrayBuffer(ld.xlsFileName) reader.readAsArrayBuffer(ld.xlsFileName)
} catch (err) { } catch (err) {
showAxiosError(err) console.log(err)
} finally { } finally {
$q.loading.hide() $q.loading.hide()
} }
@@ -223,18 +221,60 @@ const doProcess = function () {
$q.loading.show() $q.loading.show()
processXLS() processXLS()
} catch (err) { } catch (err) {
showAxiosError(err) console.log(err)
} finally { } finally {
$q.loading.hide() $q.loading.hide()
} }
} }
const hesapKodBul = function (row, fieldName) {
// Hesap kodunu bulalım
let hesapKod = ''
Object.keys(tmpl.kriterler).forEach(k => {
const kriter = tmpl.kriterler[k]
let kriterVal = ''
if (kriter.colNro >= 0) {
// sabit kriter alanı
kriterVal = row[kriter.colNro]
} else {
const tmpValues = []
tmpl.kriterler[k].combinedFieldsNro.forEach(cf => {
let tmpKriterVal = row[cf]
if ((tmpKriterVal === null) || (tmpKriterVal === undefined)) {
tmpKriterVal = ''
}
tmpValues.push(tmpKriterVal)
})
kriterVal = tmpValues.join(' ').trim()
}
const map = kriter.mappings[kriterVal]
if ((map !== undefined) && (map !== null)) {
const tmpHesapKod = map[fieldName]
if (tmpHesapKod) {
hesapKod = tmpHesapKod
}
} else {
console.log(kriter)
}
})
return hesapKod
}
const processXLS = function () { const processXLS = function () {
const sheet = workbook.Sheets[ld.bordroSheet] const sheet = workbook.Sheets[ld.bordroSheet]
const rawData = utils.sheet_to_json(sheet, { header: 1 }) const rawData = utils.sheet_to_json(sheet, { header: 1 })
const bordro = [] const bordro = []
const dagitimKeys = Object.keys(tmpl.dagitim)
rawData.forEach((row, ndx) => { rawData.forEach((row, ndx) => {
if (ndx <= tmpl.baslikSatiri - 1 + tmpl.baslikSatirAdedi) { if (ndx <= tmpl.baslikSatiri - 1 + tmpl.baslikSatirAdedi) {
@@ -245,35 +285,62 @@ const processXLS = function () {
const bordroRow = {} const bordroRow = {}
// sabit alanları verelim // sabit alanları verelim
tmpl.alanlar.filter(a=>{return a.showInSlip}).forEach(a=>{ tmpl.alanlar.filter(a => {return a.showInSlip}).forEach(a => {
if (a.colNro >= 0) {
bordroRow[a.fieldName] = row[a.colNro] bordroRow[a.fieldName] = row[a.colNro]
} else {
const tmpValues = []
a.combinedFieldsNro.forEach(cf => {
let tmpVal = row[cf]
if ((tmpVal === null) || (tmpVal === undefined)) {
tmpVal = ''
}
tmpValues.push(tmpVal)
})
bordroRow[a.fieldName] = tmpValues.join(' ').trim()
}
}) })
// veri alanlarını verelim // veri alanlarını verelim
tmpl.alanlar.filter(a=>{return a.colType === 'veri'}).forEach(veri=>{ tmpl.alanlar.filter(a => {return a.colType === 'veri'}).forEach(veri => {
// Hesap kodunu bulalım
let hesapKod = ''
Object.keys(tmpl.kriterler).forEach(k => {
const kriter = tmpl.kriterler[k]
const kriterVal = row[kriter.colNro]
const map = kriter.mappings[kriterVal]
if ((map !== undefined) && (map !== null)) { let dagitimYapildi = false
const tmpHesapKod = map[veri.fieldName] if (dagitimKeys.length > 0) {
if (tmpHesapKod) { dagitimKeys.forEach(bazAlan => {
hesapKod = tmpHesapKod const degerler = Object.keys(tmpl.dagitim[bazAlan].kural)
} degerler.forEach(deger => {
} else { if (deger === row[tmpl.dagitim[bazAlan].bazAlanColNro]) {
console.log(kriter) dagitimYapildi = true
tmpl.dagitim[bazAlan].kural[deger].forEach(oran => {
//row'ın bir kopyasını oluşturalım çünkü hesap kodunu bu yeni row'a göre bulacağız
const tmpRow = [...row]
tmpRow[tmpl.dagitim[bazAlan].hedefAlanColNro] = oran.deger
bordroRow['Hesap'] = hesapKodBul(tmpRow, veri.fieldName)
bordroRow['Masraf Açıklama'] = veri.fieldName
bordroRow['Tutar'] = row[veri.colNro] * (oran.oran / 100)
bordroRow['B/A'] = veri.ba
const hedefAlan = tmpl.dagitim[bazAlan].hedefAlan
if (bordroRow[hedefAlan]) {
bordroRow[hedefAlan] = oran.deger
} }
bordro.push({ ...bordroRow })
}) })
}
})
})
}
bordroRow['Hesap'] = hesapKod if (!dagitimYapildi) {
bordroRow['Hesap'] = hesapKodBul(row, veri.fieldName)
bordroRow['Masraf Açıklama'] = veri.fieldName
bordroRow['Tutar'] = row[veri.colNro] bordroRow['Tutar'] = row[veri.colNro]
bordroRow['B/A'] = veri.ba bordroRow['B/A'] = veri.ba
bordro.push({...bordroRow}) bordro.push({ ...bordroRow })
}
}) })
} }
} }
@@ -281,10 +348,9 @@ const processXLS = function () {
const newSheet = utils.json_to_sheet(bordro) const newSheet = utils.json_to_sheet(bordro)
const newWB = utils.book_new() const newWB = utils.book_new()
utils.book_append_sheet(newWB, newSheet, "veri") utils.book_append_sheet(newWB, newSheet, 'veri')
writeFile(newWB, "bordro.xlsx", { compression: true }) writeFile(newWB, 'bordro.xlsx', { compression: true })
} }
</script> </script>

View File

@@ -15,7 +15,7 @@
:label="t('selectCompany')" :label="t('selectCompany')"
:options="ld.companies" :options="ld.companies"
option-value="ID" option-value="ID"
option-label="Title" option-label="Name"
dense dense
options-dense options-dense
outlined outlined
@@ -89,7 +89,41 @@
<q-markup-table flat bordered> <q-markup-table flat bordered>
<thead> <thead>
<tr> <tr>
<th>Kolon No</th> <th>
<q-btn flat
color="positive"
dense
icon="add"
>
<q-tooltip>Yeni birleşik alan ekle</q-tooltip>
</q-btn>
<q-popup-edit
v-model="ld.combinedFields"
buttons
v-slot="scope"
@update:modelValue="addCombinedField()"
anchor="top start"
style="min-width: 350px; !important;"
persistent
>
<q-select
multiple
use-chips
v-model="scope.value"
:options="fieldOptions"
dense
autofocus
counter
@keyup.enter="scope.set"
style="min-width: 300px; !important;"
map-options
option-label="fieldName"
option-value="colNro"
/>
</q-popup-edit>
Kolon No
</th>
<th>Alan</th> <th>Alan</th>
<th>Kontrol</th> <th>Kontrol</th>
<th>Fişte Göster</th> <th>Fişte Göster</th>
@@ -98,8 +132,21 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="r in tmpl.alanlar" :key="r.fieldName"> <tr v-for="(r, rndx) in tmpl.alanlar" :key="r.fieldName">
<td class="text-center" style="width: 70px;">{{ r.colNro }}</td> <td class="text-center" style="width: 70px;">
{{ r.colNro }}
<q-btn
v-if="r.colNro < 0"
icon="delete"
color="negative"
flat
size="sm"
dense
@click="delCombinedField(rndx)"
/>
</td>
<td>{{ r.fieldName }}</td> <td>{{ r.fieldName }}</td>
<td class="text-center" style="width: 70px;"> <td class="text-center" style="width: 70px;">
<q-radio <q-radio
@@ -138,6 +185,73 @@
</q-card-section> </q-card-section>
<q-card-section v-if="ld.showFields">
<div class="row q-col-gutter-md q-mb-md">
<!--
<div class="col-auto">
<q-btn label="Kriterleri Doldur"
outline
color="pcolor1"
no-caps
@click="fillCriteria"
/>
</div>
-->
<div class="col text-h6 text-pcolor1">
Dağıtım Tanımları
</div>
</div>
<q-markup-table>
<thead>
<tr>
<td>
<q-btn icon="add"
outline
color="positive"
no-caps
size="sm"
@click="ld.showDagitimDlg = true"
/>
</td>
<td>Dağıtım Alanı</td>
<td>Dağıtım Kuralı</td>
</tr>
</thead>
<tbody>
<template v-for="(kv, kk) in tmpl.dagitim" :key="kk">
<template v-for="(khv, khk) in kv.kural" :key="khk">
<tr>
<td>
<q-btn icon="delete"
flat
outline
size="sm"
color="negative"
@click="delDagitim(kk, khk)"
/>
</td>
<td>
{{ kk }} : {{ khk }}
</td>
<td>
{{ kv.hedefAlan }}
<br/>
<template v-for="oran in khv" :key="oran.deger">
%{{ oran.oran }} --> {{ oran.deger }}
<br/>
</template>
</td>
</tr>
</template>
</template>
</tbody>
</q-markup-table>
</q-card-section>
<q-card-section v-if="ld.showFields"> <q-card-section v-if="ld.showFields">
<div class="row q-col-gutter-md q-mb-md"> <div class="row q-col-gutter-md q-mb-md">
<div class="col-auto"> <div class="col-auto">
@@ -165,13 +279,32 @@
<thead> <thead>
<tr> <tr>
<td class="text-weight-bolder"> <td class="text-weight-bolder">
<q-btn icon="add" flat dense>
<q-tooltip>Kriter değeri ekle</q-tooltip>
<q-popup-edit
v-model="ld.mappingVal"
buttons
v-slot="scope"
anchor="top left"
persistent
@update:modelValue="addMappingKey(k)"
>
<q-input
v-model="scope.value"
dense
autofocus
@keyup.enter="scope.set"/>
</q-popup-edit>
</q-btn>
Değer Değer
<q-btn <q-btn
flat flat
icon="add" icon="mdi-table-column-plus-after"
dense dense
color="positive" color="positive"
/> >
<q-tooltip>Veri alanı ekle</q-tooltip>
<q-popup-edit <q-popup-edit
v-model="ld.selectedVal" v-model="ld.selectedVal"
buttons buttons
@@ -186,6 +319,14 @@
counter counter
@keyup.enter="scope.set"/> @keyup.enter="scope.set"/>
</q-popup-edit> </q-popup-edit>
</q-btn>
<q-btn flat icon="content_copy" dense
@click="copyMappingKeys(k)"
>
<q-tooltip>Kriter değerlerini koopyala</q-tooltip>
</q-btn>
</td> </td>
<td v-for="f in v.valFields" :key="f"> <td v-for="f in v.valFields" :key="f">
{{ f }} {{ f }}
@@ -196,6 +337,25 @@
color="negative" color="negative"
@click="delMapping(k, f)" @click="delMapping(k, f)"
/> />
<q-btn flat icon="south" dense>
<q-tooltip>Girilen değeri tüm satırlara kopyala</q-tooltip>
<q-popup-edit
v-model="ld.mappingVal"
buttons
v-slot="scope"
anchor="top left"
persistent
@update:modelValue="fillMappings(k, f)"
>
<q-input
v-model="scope.value"
dense
autofocus
@keyup.enter="scope.set"/>
</q-popup-edit>
</q-btn>
</td> </td>
</tr> </tr>
</thead> </thead>
@@ -207,6 +367,9 @@
v-model="kv[f]" v-model="kv[f]"
dense dense
@update:modelValue="ld.isDirty=true" @update:modelValue="ld.isDirty=true"
:label="f"
stack-label
label-color="primary"
/> />
</td> </td>
@@ -226,22 +389,121 @@
</q-markup-table> </q-markup-table>
</q-expansion-item> </q-expansion-item>
</q-list> </q-list>
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-page> </q-page>
<q-dialog
v-model="ld.showDagitimDlg"
persistent
>
<q-card style="width: 700px; max-width: 80vw;">
<q-card-section>
<div class="row q-col-gutter-md items-center">
<q-select
class="col-5"
v-model="ld.dagitim.bazAlan"
:options="fieldOptionsLabel"
option-label="fieldName"
option-value="colNro"
label="Dağıtım Bazı"
/>
<q-select
class="col-5"
v-model="ld.dagitim.hedefAlan"
:options="fieldOptionsLabel"
map-options
emit-value
label="Dağıtım Hedefi"
/>
<div class="col-2">
<q-btn
label="Kural Ekle"
outline
no-caps
@click="addDagitimKural"
/>
</div>
</div>
<div v-for="(kv, ndx) in ld.dagitim.kural" :key="ndx"
class="row q-col-gutter-md">
<div class="col-5">
<q-input
class="col-5"
label="Baz Değer"
v-model="kv.baz"
dense
>
<template v-slot:after>
<q-btn
label="Oran Ekle"
outline
size="sm"
no-caps
@click="addDagitimKuralOran(ndx)"
/>
</template>
</q-input>
</div>
<div class="col-5">
<div v-for="(hd,hndx) in kv.hedef" :key="hndx"
class="row q-col-gutter-sm"
>
<q-input
class="col"
label="Hedef Değer"
v-model="hd.deger"
dense
/>
<q-input
class="col"
label="Oran"
v-model.number="hd.oran"
type="number"
dense
/>
</div>
</div>
</div>
</q-card-section>
<q-card-actions>
<q-btn
color="positive"
flat label="Tamam"
v-close-popup
no-caps
@click="addDagitim"
/>
<q-btn
color="negative"
flat label="İptal" v-close-popup no-caps
@click="cancelDagitim"
/>
</q-card-actions>
</q-card>
</q-dialog>
</template> </template>
<script setup> <script setup>
import { computed, onMounted, reactive, toRaw } from 'vue' import { computed, onMounted, reactive, toRaw } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { api } from 'boot/axios' import { api } from 'boot/axios'
import { catchAxiosError, showAxiosError } from 'src/libjs/lib/axios' import { catchAxiosError, showAxiosError, showError, showSuccess } from 'src/libjs/lib/axios'
import MEditHeader from 'src/libjs/comp/MEditHeader.vue' import MEditHeader from 'src/libjs/comp/MEditHeader.vue'
import { read, utils } from 'xlsx' import { read, utils } from 'xlsx'
import { useQuasar } from 'quasar' import { copyToClipboard, useQuasar } from 'quasar'
const { t } = useI18n() const { t } = useI18n()
const $q = useQuasar() const $q = useQuasar()
@@ -255,6 +517,19 @@ const ld = reactive({
alreadySelectedValFields: {}, alreadySelectedValFields: {},
showFields: false, showFields: false,
combinedFields: [],
showDagitimDlg: false,
dagitim: {
bazAlan: '',
hedefAlan: '',
kural: [
//{baz: xxx, hedef: [{deger: yyy, oran: zzz}]}
],
},
mappingVal: '',
}) })
const tmpl = reactive({ const tmpl = reactive({
@@ -269,6 +544,19 @@ const tmpl = reactive({
alanlar: [], alanlar: [],
kriterler: {}, kriterler: {},
dagitim: {
/*
'bazAlan': {
bazAlanColNro: 1
hedefAlanColNro: 2
hedefAlan: '',
kural: {
'bazDeger': [{oran: 20, deger: aaaa}}
}
}
*/
},
}) })
let workbook = null let workbook = null
@@ -290,6 +578,33 @@ const valFielOptions = computed(() => {
return opts return opts
}) })
const fieldOptions = computed(() => {
const ls = tmpl.alanlar.filter(f => {return f.colNro >= 0})
const opts = []
ls.forEach(f => {
opts.push({ colNro: f.colNro, fieldName: f.fieldName })
})
return opts
})
const fieldOptionsLabel = computed(() => {
const ls = tmpl.alanlar.filter(f => {return f.colNro >= 0})
const opts = []
ls.forEach(f => {
opts.push(f.fieldName)
})
return opts
})
const getFieldColNumber = function (fieldName) {
const tmpIndex = tmpl.alanlar.findIndex(f => {return f.fieldName === fieldName})
if (tmpIndex >= 0) {
return tmpl.alanlar[tmpIndex].colNro
} else {
return -1
}
}
const getCompanyList = function () { const getCompanyList = function () {
api.get('/sy/companies').then(res => { api.get('/sy/companies').then(res => {
if (res.data.Success) { if (res.data.Success) {
@@ -371,13 +686,6 @@ const load = function () {
const loadFile = function () { const loadFile = function () {
const reader = new FileReader() const reader = new FileReader()
/*
reader.addEventListener('load', (event) => {
console.log(event.target.result)
});
reader.readAsDataURL(ld.xlsFile);
*/
reader.onload = function (e) { reader.onload = function (e) {
const uin = new Uint8Array(e.target.result) const uin = new Uint8Array(e.target.result)
@@ -399,62 +707,132 @@ const processXLS = function () {
const sheet = workbook.Sheets[tmpl.bordroSheet] const sheet = workbook.Sheets[tmpl.bordroSheet]
tmpl.rawData = utils.sheet_to_json(sheet, { header: 1 }) tmpl.rawData = utils.sheet_to_json(sheet, { header: 1 })
/*
tmpl.alanlar.splice(0) tmpl.alanlar.splice(0)
*/
const fieldNames = []
let lastCol = -1 let lastCol = -1
tmpl.rawData[tmpl.baslikSatiri - 1].forEach((val, ndx) => { tmpl.rawData[tmpl.baslikSatiri - 1].forEach((val, ndx) => {
//başlık olmayan kolonlar //başlık olmayan kolonlar
if (ndx - lastCol > 1) { if (ndx - lastCol > 1) {
for (let j = 1; j < ndx - lastCol; j++) { const msg = 'Başlıksız kolonlar var. Dosya işlenemez'
tmpl.alanlar.push({ showError(msg)
colNro: lastCol + 1, throw msg
fieldName: `Kolon ${lastCol + 2}`,
colType: '',
ba: 'B',
showInSlip: false,
})
}
} }
let name = val let name = val
for (let j = 1; j < tmpl.baslikSatirAdedi; j++) { for (let j = 1; j < tmpl.baslikSatirAdedi; j++) {
let addiVal = tmpl.rawData[tmpl.baslikSatiri - 1 + j][ndx] let addiVal = tmpl.rawData[tmpl.baslikSatiri - 1 + j][ndx]
if (!addiVal) { if (addiVal) {
addiVal = ''
}
name = name + ' ' + addiVal name = name + ' ' + addiVal
} }
}
name = name.trim()
fieldNames.push(name)
const alanIndex = tmpl.alanlar.findIndex(f => {return f.fieldName === name})
if (alanIndex < 0) {
tmpl.alanlar.push({ tmpl.alanlar.push({
colNro: ndx, colNro: ndx,
fieldName: name, fieldName: name,
showInSlip: false,
colType: '', colType: '',
ba: 'B', ba: 'B',
showInSlip: false,
combinedFields: [],
combinedFieldsNro: [],
formula: '',
}) })
} else {
if (tmpl.alanlar[alanIndex].colNro !== ndx) {
const oldColNro = tmpl.alanlar[alanIndex].colNro
tmpl.alanlar[alanIndex].colNro = ndx
//kriter kolon no'ları güncelleyelim
Object.keys(tmpl.kriterler).forEach(kr => {
if (tmpl.kriterler[kr].colNro === oldColNro) {
tmpl.kriterler[kr].colNro = ndx
}
for (let j = 0; j < tmpl.kriterler[kr].combinedFieldsNro.length; j++) {
if (tmpl.kriterler[kr].combinedFieldsNro[j] === oldColNro) {
tmpl.kriterler[kr].combinedFieldsNro[j] = ndx
}
}
})
// Dağtım kolon no'ları güncelleyelim
Object.keys(tmpl.dagitim).forEach(dk => {
if (tmpl.dagitim[dk].bazAlanColNro === oldColNro) {
tmpl.dagitim[dk].bazAlanColNro = ndx
}
if (tmpl.dagitim[dk].hedefAlanColNro === oldColNro) {
tmpl.dagitim[dk].hedefAlanColNro = ndx
}
})
// Birleşik kriterleri güncelleyelim
tmpl.alanlar.forEach(af => {
if (af.colNro < 0) {
for (let j = 0; j < af.combinedFieldsNro.length; j++) {
if (af.combinedFieldsNro[j] === oldColNro) {
af.combinedFieldsNro[j] = ndx
}
}
}
})
}
}
lastCol = ndx lastCol = ndx
}) })
// Sıralayalım
tmpl.alanlar.sort((a, b) => {
if (a.colNro < b.colNro) {
return -1
} else {
return 1
}
})
// excelden silinen alanları uçuralım
tmpl.alanlar.forEach((v, n) => {
const tmpIndex = fieldNames.findIndex(el => {return v.fieldName === el})
if (tmpIndex < 0) {
console.log(v.fieldName)
tmpl.alanlar.splice(n, 1)
}
})
ld.showFields = true ld.showFields = true
} }
const fillCriteria = function () { const fillCriteria = function () {
ld.isDirty = true ld.isDirty = true
// kriterleri temizleyelim // kriterleri temizleyelim
/*
Object.keys(ld.alreadySelectedValFields).forEach(k => { Object.keys(ld.alreadySelectedValFields).forEach(k => {
delete ld.alreadySelectedValFields[k] delete ld.alreadySelectedValFields[k]
}) })
tmpl.kriterler = {} tmpl.kriterler = {}
*/
// kriter alanlarını bulup boş kriter nesnelerini oluşturalım // kriter alanlarını bulup boş kriter nesnelerini oluşturalım
const kriterCols = [] const kriterCols = []
tmpl.alanlar.filter(f => {return f.colType === 'kriter'}).forEach(f => { tmpl.alanlar.filter(f => {return f.colType === 'kriter'}).forEach(f => {
if (!tmpl.kriterler.hasOwnProperty(f.fieldName)) {
tmpl.kriterler[f.fieldName] = { tmpl.kriterler[f.fieldName] = {
colNro: f.colNro, colNro: f.colNro,
combinedFields: [...(f.combinedFields || [])],
combinedFieldsNro: [...(f.combinedFieldsNro || [])],
valFields: [], valFields: [],
/* /*
[ [
@@ -468,9 +846,18 @@ const fillCriteria = function () {
mapping['kriter1'] = {xxx: 770.01.001, yyy: 770.01.002} mapping['kriter1'] = {xxx: 770.01.001, yyy: 770.01.002}
*/ */
} }
}
kriterCols.push(f.fieldName) kriterCols.push(f.fieldName)
}) })
// kriter olmayan kolonları silelim
Object.keys(tmpl.kriterler).forEach(k => {
if (kriterCols.indexOf(k) < 0) {
delete tmpl.kriterler[k]
}
})
tmpl.rawData.forEach((row, ndx) => { tmpl.rawData.forEach((row, ndx) => {
if (ndx <= tmpl.baslikSatiri - 1 + tmpl.baslikSatirAdedi) { if (ndx <= tmpl.baslikSatiri - 1 + tmpl.baslikSatirAdedi) {
@@ -478,9 +865,34 @@ const fillCriteria = function () {
const kval = row[tmpl.kontrolKolonu] const kval = row[tmpl.kontrolKolonu]
if ((kval !== null) && (kval !== undefined) && (kval !== '')) { if ((kval !== null) && (kval !== undefined) && (kval !== '')) {
Object.keys(tmpl.kriterler).forEach(k => { Object.keys(tmpl.kriterler).forEach(k => {
const kriterVal = row[tmpl.kriterler[k].colNro]
let kriterVal = ''
if (tmpl.kriterler[k].colNro >= 0) {
// sabit kriter alanı
kriterVal = row[tmpl.kriterler[k].colNro]
} else {
// birleştirilmiş / combine kriter alanı
const tmpValues = []
tmpl.kriterler[k].combinedFieldsNro.forEach(cf => {
let tmpKriterVal = row[cf]
if ((tmpKriterVal === null) || (tmpKriterVal === undefined)) {
tmpKriterVal = ''
}
tmpValues.push(tmpKriterVal)
})
kriterVal = tmpValues.join(' ').trim()
}
if ((kriterVal !== null) && (kriterVal !== undefined) && (kriterVal !== '')) { if ((kriterVal !== null) && (kriterVal !== undefined) && (kriterVal !== '')) {
if (!tmpl.kriterler[k].mappings.hasOwnProperty(kriterVal)) {
tmpl.kriterler[k].mappings[kriterVal] = {} tmpl.kriterler[k].mappings[kriterVal] = {}
tmpl.kriterler[k].valFields.forEach(f => {
tmpl.kriterler[k].mappings[ld.mappingVal][f] = ''
})
}
} }
}) })
} }
@@ -512,6 +924,130 @@ const delMapping = function (k, valField) {
}) })
} }
const fillMappings = function (k, valField) {
ld.isDirty = true
Object.keys(tmpl.kriterler[k].mappings).forEach(vk => {
tmpl.kriterler[k].mappings[vk][valField] = ld.mappingVal
})
ld.mappingVal = ''
}
const addMappingKey = function (k) {
ld.isDirty = true
tmpl.kriterler[k].mappings[ld.mappingVal] = {}
tmpl.kriterler[k].valFields.forEach(f => {
tmpl.kriterler[k].mappings[ld.mappingVal][f] = ''
})
ld.mappingVal = ''
}
const copyMappingKeys = function (k) {
let text = ''
Object.keys(tmpl.kriterler[k].mappings).forEach(vk => {
text += vk + '\n'
})
copyToClipboard(text).then(() => {
showSuccess('Kriter değerleri kopyalandı')
}).catch(() => {
alert('kopyalamada hata')
})
}
const fillMappingsFromExcel = function (k, valField) {
ld.isDirty = true
Object.keys(tmpl.kriterler[k].mappings).forEach(vk => {
tmpl.kriterler[k].mappings[vk][valField] = ld.mappingVal
})
ld.mappingVal = ''
}
const addCombinedField = function () {
ld.isDirty = true
const combinedFields = []
const combinedFieldsNro = []
ld.combinedFields.forEach(f => {
combinedFields.push(f.fieldName)
combinedFieldsNro.push(f.colNro)
})
const fName = combinedFields.join(' : ')
tmpl.alanlar.push({
colNro: -1,
fieldName: fName,
colType: '',
ba: 'B',
showInSlip: false,
combinedFields: [...combinedFields],
combinedFieldsNro: [...combinedFieldsNro],
formula: '',
})
ld.combinedFields.splice(0)
}
const delCombinedField = function (ndx) {
ld.isDirty = true
tmpl.alanlar.splice(ndx, 1)
}
const addDagitimKural = function () {
ld.dagitim.kural.push({
baz: '', hedef: [],
})
}
const addDagitimKuralOran = function (ndx) {
ld.dagitim.kural[ndx].hedef.push({ deger: null, oran: 0 })
}
const addDagitim = function () {
ld.isDirty = true
const hedefAlan = toRaw(ld.dagitim.hedefAlan)
const bazAlan = toRaw(ld.dagitim.bazAlan)
tmpl.dagitim[bazAlan] = {
bazAlanColNro: getFieldColNumber(bazAlan),
hedefAlanColNro: getFieldColNumber(hedefAlan),
hedefAlan: hedefAlan,
kural: {},
}
ld.dagitim.kural.forEach(k => {
const bazDeger = toRaw(k.baz)
tmpl.dagitim[bazAlan].kural[bazDeger] = []
k.hedef.forEach(h => {
tmpl.dagitim[bazAlan].kural[bazDeger].push({ oran: h.oran, deger: h.deger })
})
})
cancelDagitim()
}
const cancelDagitim = function () {
ld.dagitim.bazAlan = ''
ld.dagitim.hedefAlan = ''
ld.dagitim.kural.splice(0)
}
const delDagitim = function (bazAlan, bazDeger) {
ld.isDirty = true
delete tmpl.dagitim[bazAlan].kural[bazDeger]
if (Object.keys(tmpl.dagitim[bazAlan].kural).length === 0) {
delete tmpl.dagitim[bazAlan]
}
}
</script> </script>

View File

@@ -3,6 +3,7 @@ import { LocalStorage } from 'quasar'
import { api } from 'boot/axios' import { api } from 'boot/axios'
import { jwtDecode } from "jwt-decode" import { jwtDecode } from "jwt-decode"
import Router from 'src/router/index' import Router from 'src/router/index'
import {bus} from 'boot/bus'
export const sessionName = 'bresSession' export const sessionName = 'bresSession'
@@ -10,17 +11,26 @@ const defaultState = {
LoggedIn: false, LoggedIn: false,
IsAdmin: false, IsAdmin: false,
Token: '', Token: '',
UsrKSUID: '', UsrKsuid: '',
UsrEmail: '', UsrEmail: '',
UsrFullname: '', UsrFullName: '',
Username: '', Username: '',
ClientKSUID: '', ClientKsuid: '',
ClientCode: '', ClientCode: '',
LicenseCode: '', LicenseCode: '',
PkgConf: {} PkgConf: {},
companyID: null
} }
bus.on('companySelect', (companyID) => {
const store = useLoginStore()
//store.companyID = companyID
store.setCompanyID(companyID)
})
export const useLoginStore = defineStore('login', { export const useLoginStore = defineStore('login', {
state: () => { state: () => {
return JSON.parse(JSON.stringify(defaultState)) return JSON.parse(JSON.stringify(defaultState))
@@ -28,6 +38,11 @@ export const useLoginStore = defineStore('login', {
getters: {}, getters: {},
actions: { actions: {
setCompanyID(companyID) {
this.companyID = companyID
this.save()
},
login (payload) { login (payload) {
// kaldıysa önceki session'ı uçuralım // kaldıysa önceki session'ı uçuralım
LocalStorage.remove(sessionName) LocalStorage.remove(sessionName)
@@ -58,6 +73,14 @@ export const useLoginStore = defineStore('login', {
} }
}, },
updateProfile (payload) {
this.UsrFullName = payload.fullname
this.UsrEmail = payload.email
this.Username = payload.username
this.save()
},
updateState (payload) { updateState (payload) {
Object.assign(this, payload) Object.assign(this, payload)
api.defaults.headers.common['Authorization'] = `Bearer ${payload.Token}` api.defaults.headers.common['Authorization'] = `Bearer ${payload.Token}`
@@ -76,9 +99,17 @@ export const useLoginStore = defineStore('login', {
} }
}, },
save () {
const pl = {}
Object.keys(defaultState).forEach((key) => {
pl[key] = this[key]
})
LocalStorage.set(sessionName, pl)
},
IsLoggedIn () { IsLoggedIn () {
return this.LoggedIn return this.LoggedIn
} },
} }
}) })

View File

@@ -2593,6 +2593,11 @@ readdirp@~3.6.0:
dependencies: dependencies:
picomatch "^2.2.1" picomatch "^2.2.1"
reconnecting-websocket@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783"
integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==
register-service-worker@^1.7.2: register-service-worker@^1.7.2:
version "1.7.2" version "1.7.2"
resolved "https://registry.yarnpkg.com/register-service-worker/-/register-service-worker-1.7.2.tgz#6516983e1ef790a98c4225af1216bc80941a4bd2" resolved "https://registry.yarnpkg.com/register-service-worker/-/register-service-worker-1.7.2.tgz#6516983e1ef790a98c4225af1216bc80941a4bd2"