@kernhq/module-hr 0.14.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contract/router.d.ts +14 -2
- package/dist/contract/router.d.ts.map +1 -1
- package/dist/contract/router.js +11 -2
- package/dist/contract/router.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +51 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/jobs.d.ts +5 -2
- package/dist/server/jobs.d.ts.map +1 -1
- package/dist/server/jobs.js +109 -2
- package/dist/server/jobs.js.map +1 -1
- package/dist/server/router.d.ts +122 -2
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/router.js +448 -274
- package/dist/server/router.js.map +1 -1
- package/dist/server/schema.d.ts +85 -0
- package/dist/server/schema.d.ts.map +1 -1
- package/dist/server/schema.js +32 -0
- package/dist/server/schema.js.map +1 -1
- package/dist/server/services/approvals.d.ts +150 -6
- package/dist/server/services/approvals.d.ts.map +1 -1
- package/dist/server/services/approvals.js +428 -26
- package/dist/server/services/approvals.js.map +1 -1
- package/migrations/0010_approval_timeouts.sql +28 -0
- package/migrations/meta/0010_snapshot.json +4263 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +1 -1
- package/src/client/components/DecisionDialog.svelte +99 -7
- package/src/client/messages.ts +85 -0
- package/src/client/mock.ts +256 -15
- package/src/client/pages/ApprovalsPage.svelte +256 -27
- package/src/client/pages/DirectoryPage.svelte +1 -1
- package/src/client/query.ts +2 -2
- package/src/client/widgets/ApprovalsWidget.svelte +120 -9
- package/src/contract/router.ts +11 -2
|
@@ -61,9 +61,16 @@
|
|
|
61
61
|
{
|
|
62
62
|
"idx": 9,
|
|
63
63
|
"version": "7",
|
|
64
|
-
"when":
|
|
64
|
+
"when": 1787848170497,
|
|
65
65
|
"tag": "0009_beyond_cap_minutes",
|
|
66
66
|
"breakpoints": true
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"idx": 10,
|
|
70
|
+
"version": "7",
|
|
71
|
+
"when": 1787851246006,
|
|
72
|
+
"tag": "0010_approval_timeouts",
|
|
73
|
+
"breakpoints": true
|
|
67
74
|
}
|
|
68
75
|
]
|
|
69
76
|
}
|
package/package.json
CHANGED
|
@@ -1,34 +1,90 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { Button, Dialog, Field, Textarea } from '@kernhq/ui'
|
|
2
|
+
import { Button, Dialog, Field, Select, Textarea } from '@kernhq/ui'
|
|
3
|
+
import { untrack } from 'svelte'
|
|
3
4
|
import { t } from '../i18n.js'
|
|
4
5
|
import type { ApprovalRequest } from '../index.js'
|
|
5
6
|
import { summarise } from '../summary.js'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* Confirming a decision, stating what it does and
|
|
9
|
+
* Confirming a decision, stating what it does, to whom — and in whose name.
|
|
9
10
|
*
|
|
10
11
|
* Approving leave moves somebody's balance and puts them on the team calendar; rejecting it sends
|
|
11
12
|
* them a notification and changes nothing else. "Are you sure?" says none of that, so the body text
|
|
12
13
|
* is chosen per subject type and per position in the chain — a middle step passes the request on
|
|
13
14
|
* rather than settling it, and an approver who thinks they just granted the leave is a support call.
|
|
15
|
+
*
|
|
16
|
+
* `identities` is who the reader may file this decision as: themselves (`onBehalfOfId: null`), or
|
|
17
|
+
* somebody who delegated their approvals to them. The rule this dialog exists to keep is that a
|
|
18
|
+
* decision is never filed against a person nobody named — so with one identity it is stated, with
|
|
19
|
+
* several it is chosen, and with none confirmed the confirm button does nothing.
|
|
14
20
|
*/
|
|
15
21
|
interface Props {
|
|
16
22
|
request: ApprovalRequest | null
|
|
17
23
|
decision: 'approve' | 'reject'
|
|
24
|
+
/**
|
|
25
|
+
* Recomputed by the caller as names and delegations arrive, so it may change while the dialog is
|
|
26
|
+
* open. Omitting it means the reader decides as themselves and nothing else is possible — which
|
|
27
|
+
* is what a surface with no delegation in it, like the directory panel or the dashboard widget,
|
|
28
|
+
* is saying.
|
|
29
|
+
*/
|
|
30
|
+
identities?: Array<{ onBehalfOfId: string | null; label: string }>
|
|
18
31
|
pending: boolean
|
|
19
32
|
error: string | null
|
|
20
|
-
onConfirm: (comment: string) => void
|
|
33
|
+
onConfirm: (comment: string, onBehalfOfId: string | null) => void
|
|
21
34
|
onCancel: () => void
|
|
22
35
|
}
|
|
23
|
-
const { request, decision, pending, error, onConfirm, onCancel }: Props = $props()
|
|
36
|
+
const { request, decision, identities, pending, error, onConfirm, onCancel }: Props = $props()
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* One identity by default, and it is the reader's own.
|
|
40
|
+
*
|
|
41
|
+
* A `$derived` rather than a destructuring fallback: a fallback is re-evaluated on every read, so a
|
|
42
|
+
* fresh array and a fresh `t()` call would land in the middle of the equality checks below.
|
|
43
|
+
*/
|
|
44
|
+
const options = $derived(identities ?? [{ onBehalfOfId: null, label: t('approvals_as_self') }])
|
|
24
45
|
|
|
25
46
|
let comment = $state('')
|
|
47
|
+
/** '' until chosen, 'self' for the reader's own decision, otherwise the person id being acted for. */
|
|
48
|
+
let actingAs = $state('')
|
|
49
|
+
|
|
50
|
+
/** A `Select` needs a string, and `null` is a real identity here rather than the absence of one. */
|
|
51
|
+
const keyOf = (identity: { onBehalfOfId: string | null }) => identity.onBehalfOfId ?? 'self'
|
|
26
52
|
|
|
27
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Reset between requests: yesterday's note must not ride along on today's decision, and neither
|
|
55
|
+
* must the name it was filed against.
|
|
56
|
+
*
|
|
57
|
+
* Only `request?.id` is tracked. `identities` changes whenever a name or a delegation arrives, and
|
|
58
|
+
* an effect that read it would wipe a half-typed comment under the reader's hands.
|
|
59
|
+
*/
|
|
28
60
|
$effect(() => {
|
|
29
61
|
void request?.id
|
|
30
|
-
|
|
62
|
+
untrack(() => {
|
|
63
|
+
comment = ''
|
|
64
|
+
// Preselected only where it cannot be a guess: the reader's own name. Which colleague they
|
|
65
|
+
// meant is the one thing this dialog must never assume.
|
|
66
|
+
actingAs = options.some((i) => i.onBehalfOfId === null) ? 'self' : ''
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The identity this click would file under, or null while it is still an open question.
|
|
72
|
+
*
|
|
73
|
+
* A single identity needs no selection — including one that arrives after the dialog opened, which
|
|
74
|
+
* is why this is derived from `identities` rather than from what was preselected.
|
|
75
|
+
*/
|
|
76
|
+
const chosen = $derived.by(() => {
|
|
77
|
+
if (options.length === 1) return options[0]!
|
|
78
|
+
return options.find((i) => keyOf(i) === actingAs) ?? null
|
|
31
79
|
})
|
|
80
|
+
const onBehalf = $derived(chosen?.onBehalfOfId ? chosen : null)
|
|
81
|
+
|
|
82
|
+
const confirm = () => {
|
|
83
|
+
// Guarded rather than trusted to the disabled attribute: an unnamed identity must not become a
|
|
84
|
+
// decision filed as the caller, which is the failure this whole dialog is arranged against.
|
|
85
|
+
if (!chosen || pending) return
|
|
86
|
+
onConfirm(comment, chosen.onBehalfOfId)
|
|
87
|
+
}
|
|
32
88
|
|
|
33
89
|
const isLastStep = $derived(request ? request.currentStep >= Math.max(request.steps.length - 1, 0) : true)
|
|
34
90
|
|
|
@@ -59,6 +115,27 @@ const title = $derived(decision === 'approve' ? t('approve_confirm_title') : t('
|
|
|
59
115
|
</p>
|
|
60
116
|
{/if}
|
|
61
117
|
|
|
118
|
+
<!--
|
|
119
|
+
The choice comes before the comment, because it changes what the comment is attached to. It is
|
|
120
|
+
only rendered where there is something to choose — one identity is stated below, not offered.
|
|
121
|
+
-->
|
|
122
|
+
{#if options.length > 1}
|
|
123
|
+
<Field label={t('approvals_decide_as')} hint={t('approvals_decide_as_hint')} required>
|
|
124
|
+
{#snippet children(id)}
|
|
125
|
+
<Select
|
|
126
|
+
{id}
|
|
127
|
+
bind:value={actingAs}
|
|
128
|
+
placeholder={t('approvals_decide_as_pick')}
|
|
129
|
+
options={options.map((i) => ({ value: keyOf(i), label: i.label }))}
|
|
130
|
+
/>
|
|
131
|
+
{/snippet}
|
|
132
|
+
</Field>
|
|
133
|
+
{/if}
|
|
134
|
+
|
|
135
|
+
{#if onBehalf}
|
|
136
|
+
<p class="behalf">{t('approvals_behalf_notice', { name: onBehalf.label })}</p>
|
|
137
|
+
{/if}
|
|
138
|
+
|
|
62
139
|
<Field label={t('approval_comment')} hint={t('approval_comment_hint')} error={error}>
|
|
63
140
|
{#snippet children(id)}
|
|
64
141
|
<Textarea {id} bind:value={comment} rows={3} />
|
|
@@ -70,7 +147,8 @@ const title = $derived(decision === 'approve' ? t('approve_confirm_title') : t('
|
|
|
70
147
|
<Button
|
|
71
148
|
variant={decision === 'reject' ? 'danger' : 'primary'}
|
|
72
149
|
loading={pending}
|
|
73
|
-
|
|
150
|
+
disabled={!chosen}
|
|
151
|
+
onclick={confirm}
|
|
74
152
|
>
|
|
75
153
|
{decision === 'approve' ? t('approve') : t('reject')}
|
|
76
154
|
</Button>
|
|
@@ -87,4 +165,18 @@ const title = $derived(decision === 'approve' ? t('approve_confirm_title') : t('
|
|
|
87
165
|
font-weight: 400;
|
|
88
166
|
color: var(--kern-ink-500);
|
|
89
167
|
}
|
|
168
|
+
/*
|
|
169
|
+
Tinted rather than muted. This is the sentence that says the decision will carry somebody else's
|
|
170
|
+
name, so it has to be the thing the eye lands on before the confirm button — and `--kern-ink-700`
|
|
171
|
+
on `--kern-info-tint` is a pair that holds its contrast in both themes.
|
|
172
|
+
*/
|
|
173
|
+
.behalf {
|
|
174
|
+
margin: 0 0 12px;
|
|
175
|
+
padding: 10px 12px;
|
|
176
|
+
border-radius: var(--kern-r-md2);
|
|
177
|
+
background: var(--kern-info-tint);
|
|
178
|
+
color: var(--kern-ink-700);
|
|
179
|
+
font-size: 12.5px;
|
|
180
|
+
line-height: 1.5;
|
|
181
|
+
}
|
|
90
182
|
</style>
|
package/src/client/messages.ts
CHANGED
|
@@ -232,14 +232,27 @@ export const en: Record<string, Message> = {
|
|
|
232
232
|
'hr.approval_summary_overtime': 'Overtime on {date}',
|
|
233
233
|
'hr.approval_summary_regularization': 'Attendance correction for {date}',
|
|
234
234
|
'hr.approvals_actions': 'Actions',
|
|
235
|
+
'hr.approvals_as_self': 'Yourself',
|
|
236
|
+
'hr.approvals_behalf_notice':
|
|
237
|
+
'You are deciding for {name}. It is recorded in their name, with yours beside it.',
|
|
238
|
+
'hr.approvals_behalf_pick': 'Whose decision?',
|
|
239
|
+
'hr.approvals_behalf_someone': 'another approver',
|
|
235
240
|
'hr.approvals_chains_hint': 'Who signs what is set in the module settings.',
|
|
241
|
+
'hr.approvals_decide_as': 'Deciding as',
|
|
242
|
+
'hr.approvals_decide_as_hint': 'The decision is recorded against the person you choose.',
|
|
243
|
+
'hr.approvals_decide_as_pick': 'Choose a person',
|
|
236
244
|
'hr.approvals_decided': 'Decided',
|
|
245
|
+
'hr.approvals_decided_behalf': 'Decided by {actor} for {person}',
|
|
237
246
|
'hr.approvals_decided_none': 'Nothing decided yet',
|
|
238
247
|
'hr.approvals_decided_none_desc': 'Requests you have approved or rejected appear here.',
|
|
239
248
|
'hr.approvals_error': 'Your approvals could not be loaded',
|
|
240
249
|
'hr.approvals_for': 'for {name}',
|
|
250
|
+
'hr.approvals_later_step': 'Not your step yet',
|
|
241
251
|
'hr.approvals_none': 'Nothing waiting on you',
|
|
242
252
|
'hr.approvals_none_desc': 'Requests needing your decision appear here.',
|
|
253
|
+
'hr.approvals_on_behalf': 'On behalf of {name}',
|
|
254
|
+
'hr.approvals_open': 'Open Approvals',
|
|
255
|
+
'hr.approvals_open_hint': 'Not one to decide from here — the approvals page shows where it stands.',
|
|
243
256
|
'hr.approvals_request': 'Request',
|
|
244
257
|
'hr.approvals_requested': 'Requested',
|
|
245
258
|
'hr.approvals_requested_by': 'Requested by',
|
|
@@ -247,6 +260,7 @@ export const en: Record<string, Message> = {
|
|
|
247
260
|
'hr.approvals_step_of': 'Step {n} of {total}',
|
|
248
261
|
'hr.approvals_title': 'Approvals',
|
|
249
262
|
'hr.approvals_waiting': 'Waiting on you',
|
|
263
|
+
'hr.approvals_you_decided': 'You have decided',
|
|
250
264
|
'hr.approve': 'Approve',
|
|
251
265
|
'hr.approve_confirm_attendance': 'The corrected punches are applied and that day is recomputed.',
|
|
252
266
|
'hr.approve_confirm_leave': 'The days come off their balance and the team calendar shows them as away.',
|
|
@@ -641,7 +655,10 @@ export const en: Record<string, Message> = {
|
|
|
641
655
|
'hr.cmd_directory': 'Open the people directory',
|
|
642
656
|
'hr.cmd_request_leave': 'Request time off',
|
|
643
657
|
'hr.days': { one: 'day', other: 'days' },
|
|
658
|
+
'hr.decide_behalf_error':
|
|
659
|
+
'The decision was not recorded. The delegation may have ended — reload and try again.',
|
|
644
660
|
'hr.decide_error': 'The decision could not be recorded',
|
|
661
|
+
'hr.decide_moved_error': 'This is no longer yours to decide. The list has been updated.',
|
|
645
662
|
'hr.delegate': 'Delegate',
|
|
646
663
|
'hr.delegate_add': 'Add delegation',
|
|
647
664
|
'hr.delegate_all_types': 'All requests',
|
|
@@ -1656,14 +1673,26 @@ export const ar: Record<string, Message> = {
|
|
|
1656
1673
|
'hr.approval_summary_overtime': 'عمل إضافي في {date}',
|
|
1657
1674
|
'hr.approval_summary_regularization': 'تصحيح حضور ليوم {date}',
|
|
1658
1675
|
'hr.approvals_actions': 'الإجراءات',
|
|
1676
|
+
'hr.approvals_as_self': 'أنت',
|
|
1677
|
+
'hr.approvals_behalf_notice': 'أنت تقرّر بدلاً من {name}. يُسجَّل القرار باسمه ويُذكر اسمك إلى جانبه.',
|
|
1678
|
+
'hr.approvals_behalf_pick': 'قرار مَن؟',
|
|
1679
|
+
'hr.approvals_behalf_someone': 'مُعتمِد آخر',
|
|
1659
1680
|
'hr.approvals_chains_hint': 'يُحدَّد من يوقّع على ماذا في إعدادات الوحدة.',
|
|
1681
|
+
'hr.approvals_decide_as': 'باسم مَن',
|
|
1682
|
+
'hr.approvals_decide_as_hint': 'يُسجَّل القرار باسم الشخص الذي تختاره.',
|
|
1683
|
+
'hr.approvals_decide_as_pick': 'اختر شخصًا',
|
|
1660
1684
|
'hr.approvals_decided': 'تم البتّ فيها',
|
|
1685
|
+
'hr.approvals_decided_behalf': 'قرّر {actor} نيابةً عن {person}',
|
|
1661
1686
|
'hr.approvals_decided_none': 'لم يتم البتّ في شيء بعد',
|
|
1662
1687
|
'hr.approvals_decided_none_desc': 'تظهر هنا الطلبات التي وافقت عليها أو رفضتها.',
|
|
1663
1688
|
'hr.approvals_error': 'تعذّر تحميل موافقاتك',
|
|
1664
1689
|
'hr.approvals_for': 'لـ {name}',
|
|
1690
|
+
'hr.approvals_later_step': 'ليست خطوتك بعد',
|
|
1665
1691
|
'hr.approvals_none': 'لا شيء بانتظارك',
|
|
1666
1692
|
'hr.approvals_none_desc': 'تظهر هنا الطلبات التي تنتظر قرارك.',
|
|
1693
|
+
'hr.approvals_on_behalf': 'نيابةً عن {name}',
|
|
1694
|
+
'hr.approvals_open': 'فتح الموافقات',
|
|
1695
|
+
'hr.approvals_open_hint': 'ليس مما يُبَتّ فيه من هنا — صفحة الموافقات تُظهر أين وصل هذا الطلب.',
|
|
1667
1696
|
'hr.approvals_request': 'الطلب',
|
|
1668
1697
|
'hr.approvals_requested': 'تاريخ الطلب',
|
|
1669
1698
|
'hr.approvals_requested_by': 'مقدّم الطلب',
|
|
@@ -1671,6 +1700,7 @@ export const ar: Record<string, Message> = {
|
|
|
1671
1700
|
'hr.approvals_step_of': 'الخطوة {n} من {total}',
|
|
1672
1701
|
'hr.approvals_title': 'الموافقات',
|
|
1673
1702
|
'hr.approvals_waiting': 'بانتظارك',
|
|
1703
|
+
'hr.approvals_you_decided': 'لقد قرّرت',
|
|
1674
1704
|
'hr.approve': 'موافقة',
|
|
1675
1705
|
'hr.approve_confirm_attendance': 'تُطبَّق التسجيلات المصحّحة ويُعاد احتساب ذلك اليوم.',
|
|
1676
1706
|
'hr.approve_confirm_leave': 'تُخصم الأيام من رصيده ويظهر في تقويم الفريق كغائب.',
|
|
@@ -2088,7 +2118,9 @@ export const ar: Record<string, Message> = {
|
|
|
2088
2118
|
'hr.cmd_directory': 'فتح دليل الأشخاص',
|
|
2089
2119
|
'hr.cmd_request_leave': 'طلب إجازة',
|
|
2090
2120
|
'hr.days': { zero: 'يوم', one: 'يوم', two: 'يومان', few: 'أيام', many: 'يومًا', other: 'يوم' },
|
|
2121
|
+
'hr.decide_behalf_error': 'لم يُسجَّل القرار. ربما انتهى التفويض — أعد تحميل الصفحة وحاول مرة أخرى.',
|
|
2091
2122
|
'hr.decide_error': 'تعذّر تسجيل القرار',
|
|
2123
|
+
'hr.decide_moved_error': 'لم يعد القرار في هذا الطلب لك. وقد حُدِّثت القائمة.',
|
|
2092
2124
|
'hr.delegate': 'تفويض',
|
|
2093
2125
|
'hr.delegate_add': 'إضافة تفويض',
|
|
2094
2126
|
'hr.delegate_all_types': 'كل الطلبات',
|
|
@@ -3127,14 +3159,28 @@ export const de: Record<string, Message> = {
|
|
|
3127
3159
|
'hr.approval_summary_overtime': 'Überstunden am {date}',
|
|
3128
3160
|
'hr.approval_summary_regularization': 'Zeitkorrektur für {date}',
|
|
3129
3161
|
'hr.approvals_actions': 'Aktionen',
|
|
3162
|
+
'hr.approvals_as_self': 'Sie selbst',
|
|
3163
|
+
'hr.approvals_behalf_notice':
|
|
3164
|
+
'Sie entscheiden für {name}. Die Entscheidung wird in deren Namen erfasst, Ihr Name steht daneben.',
|
|
3165
|
+
'hr.approvals_behalf_pick': 'Wessen Entscheidung?',
|
|
3166
|
+
'hr.approvals_behalf_someone': 'eine andere genehmigende Person',
|
|
3130
3167
|
'hr.approvals_chains_hint': 'Wer was freigibt, wird in den Moduleinstellungen festgelegt.',
|
|
3168
|
+
'hr.approvals_decide_as': 'Entscheiden als',
|
|
3169
|
+
'hr.approvals_decide_as_hint': 'Die Entscheidung wird der gewählten Person zugeschrieben.',
|
|
3170
|
+
'hr.approvals_decide_as_pick': 'Person wählen',
|
|
3131
3171
|
'hr.approvals_decided': 'Entschieden',
|
|
3172
|
+
'hr.approvals_decided_behalf': 'Von {actor} für {person} entschieden',
|
|
3132
3173
|
'hr.approvals_decided_none': 'Noch nichts entschieden',
|
|
3133
3174
|
'hr.approvals_decided_none_desc': 'Hier erscheinen Anträge, die Sie genehmigt oder abgelehnt haben.',
|
|
3134
3175
|
'hr.approvals_error': 'Ihre Freigaben konnten nicht geladen werden',
|
|
3135
3176
|
'hr.approvals_for': 'für {name}',
|
|
3177
|
+
'hr.approvals_later_step': 'Noch nicht Ihr Schritt',
|
|
3136
3178
|
'hr.approvals_none': 'Keine offenen Freigaben',
|
|
3137
3179
|
'hr.approvals_none_desc': 'Anträge, die auf Ihre Entscheidung warten, erscheinen hier.',
|
|
3180
|
+
'hr.approvals_on_behalf': 'Im Namen von {name}',
|
|
3181
|
+
'hr.approvals_open': 'Freigaben öffnen',
|
|
3182
|
+
'hr.approvals_open_hint':
|
|
3183
|
+
'Von hier aus nicht zu entscheiden — die Freigabenseite zeigt, wo der Antrag steht.',
|
|
3138
3184
|
'hr.approvals_request': 'Antrag',
|
|
3139
3185
|
'hr.approvals_requested': 'Eingereicht',
|
|
3140
3186
|
'hr.approvals_requested_by': 'Beantragt von',
|
|
@@ -3142,6 +3188,7 @@ export const de: Record<string, Message> = {
|
|
|
3142
3188
|
'hr.approvals_step_of': 'Schritt {n} von {total}',
|
|
3143
3189
|
'hr.approvals_title': 'Freigaben',
|
|
3144
3190
|
'hr.approvals_waiting': 'Wartet auf Sie',
|
|
3191
|
+
'hr.approvals_you_decided': 'Sie haben entschieden',
|
|
3145
3192
|
'hr.approve': 'Genehmigen',
|
|
3146
3193
|
'hr.approve_confirm_attendance':
|
|
3147
3194
|
'Die korrigierten Buchungen werden übernommen und der Tag wird neu berechnet.',
|
|
@@ -3554,7 +3601,10 @@ export const de: Record<string, Message> = {
|
|
|
3554
3601
|
'hr.cmd_directory': 'Personenverzeichnis öffnen',
|
|
3555
3602
|
'hr.cmd_request_leave': 'Abwesenheit beantragen',
|
|
3556
3603
|
'hr.days': { one: 'Tag', other: 'Tage' },
|
|
3604
|
+
'hr.decide_behalf_error':
|
|
3605
|
+
'Die Entscheidung wurde nicht erfasst. Die Vertretung ist möglicherweise abgelaufen — neu laden und erneut versuchen.',
|
|
3557
3606
|
'hr.decide_error': 'Die Entscheidung konnte nicht gespeichert werden',
|
|
3607
|
+
'hr.decide_moved_error': 'Diese Entscheidung liegt nicht mehr bei Ihnen. Die Liste wurde aktualisiert.',
|
|
3558
3608
|
'hr.delegate': 'Vertretung',
|
|
3559
3609
|
'hr.delegate_add': 'Vertretung hinzufügen',
|
|
3560
3610
|
'hr.delegate_all_types': 'Alle Anträge',
|
|
@@ -4527,14 +4577,28 @@ export const fa: Record<string, Message> = {
|
|
|
4527
4577
|
'hr.approval_summary_overtime': 'اضافهکاری در {date}',
|
|
4528
4578
|
'hr.approval_summary_regularization': 'اصلاح حضور برای {date}',
|
|
4529
4579
|
'hr.approvals_actions': 'کنشها',
|
|
4580
|
+
'hr.approvals_as_self': 'خودتان',
|
|
4581
|
+
'hr.approvals_behalf_notice':
|
|
4582
|
+
'شما بهجای {name} تصمیم میگیرید. تصمیم به نام او و نام شما در کنارش ثبت میشود.',
|
|
4583
|
+
'hr.approvals_behalf_pick': 'تصمیم از طرف چه کسی؟',
|
|
4584
|
+
'hr.approvals_behalf_someone': 'تأییدکنندهٔ دیگر',
|
|
4530
4585
|
'hr.approvals_chains_hint': 'اینکه چهکسی چهچیزی را امضا کند در تنظیمات ماژول تعیین میشود.',
|
|
4586
|
+
'hr.approvals_decide_as': 'تصمیم به نام',
|
|
4587
|
+
'hr.approvals_decide_as_hint': 'تصمیم به نام فردی که انتخاب میکنید ثبت میشود.',
|
|
4588
|
+
'hr.approvals_decide_as_pick': 'یک نفر را انتخاب کنید',
|
|
4531
4589
|
'hr.approvals_decided': 'تصمیمگرفتهشده',
|
|
4590
|
+
'hr.approvals_decided_behalf': '{actor} بهجای {person} تصمیم گرفت',
|
|
4532
4591
|
'hr.approvals_decided_none': 'هنوز چیزی تصمیمگیری نشده',
|
|
4533
4592
|
'hr.approvals_decided_none_desc': 'درخواستهایی که تأیید یا رد کردهاید اینجا نمایش داده میشوند.',
|
|
4534
4593
|
'hr.approvals_error': 'تأییدهای شما بارگیری نشد',
|
|
4535
4594
|
'hr.approvals_for': 'برای {name}',
|
|
4595
|
+
'hr.approvals_later_step': 'هنوز نوبت شما نیست',
|
|
4536
4596
|
'hr.approvals_none': 'چیزی منتظر تصمیم شما نیست',
|
|
4537
4597
|
'hr.approvals_none_desc': 'درخواستهایی که باید تصمیم بگیرید اینجا میآیند.',
|
|
4598
|
+
'hr.approvals_on_behalf': 'به نمایندگی از {name}',
|
|
4599
|
+
'hr.approvals_open': 'رفتن به تأییدها',
|
|
4600
|
+
'hr.approvals_open_hint':
|
|
4601
|
+
'از اینجا نمیشود دربارهٔ آن تصمیم گرفت — صفحهٔ تأییدها نشان میدهد در چه مرحلهای است.',
|
|
4538
4602
|
'hr.approvals_request': 'درخواست',
|
|
4539
4603
|
'hr.approvals_requested': 'زمان درخواست',
|
|
4540
4604
|
'hr.approvals_requested_by': 'درخواستدهنده',
|
|
@@ -4542,6 +4606,7 @@ export const fa: Record<string, Message> = {
|
|
|
4542
4606
|
'hr.approvals_step_of': 'مرحلهٔ {n} از {total}',
|
|
4543
4607
|
'hr.approvals_title': 'تأییدها',
|
|
4544
4608
|
'hr.approvals_waiting': 'در انتظار شما',
|
|
4609
|
+
'hr.approvals_you_decided': 'شما تصمیم گرفتهاید',
|
|
4545
4610
|
'hr.approve': 'تأیید',
|
|
4546
4611
|
'hr.approve_confirm_attendance': 'ثبتهای اصلاحشده اعمال میشود و آن روز دوباره محاسبه میشود.',
|
|
4547
4612
|
'hr.approve_confirm_leave': 'روزها از موجودی او کم میشود و در تقویم تیم غایب نمایش داده میشود.',
|
|
@@ -4934,7 +4999,10 @@ export const fa: Record<string, Message> = {
|
|
|
4934
4999
|
'hr.cmd_directory': 'باز کردن فهرست افراد',
|
|
4935
5000
|
'hr.cmd_request_leave': 'درخواست مرخصی',
|
|
4936
5001
|
'hr.days': { one: 'روز', other: 'روز' },
|
|
5002
|
+
'hr.decide_behalf_error':
|
|
5003
|
+
'تصمیم ثبت نشد. شاید واگذاری به پایان رسیده باشد — صفحه را دوباره بارگذاری کنید و دوباره تلاش کنید.',
|
|
4937
5004
|
'hr.decide_error': 'تصمیم ثبت نشد',
|
|
5005
|
+
'hr.decide_moved_error': 'تصمیم دربارهٔ این درخواست دیگر با شما نیست. فهرست بهروز شد.',
|
|
4938
5006
|
'hr.delegate': 'واگذاری',
|
|
4939
5007
|
'hr.delegate_add': 'افزودن واگذاری',
|
|
4940
5008
|
'hr.delegate_all_types': 'همهٔ درخواستها',
|
|
@@ -5883,14 +5951,27 @@ export const tr: Record<string, Message> = {
|
|
|
5883
5951
|
'hr.approval_summary_overtime': '{date} tarihinde fazla mesai',
|
|
5884
5952
|
'hr.approval_summary_regularization': '{date} için devam düzeltmesi',
|
|
5885
5953
|
'hr.approvals_actions': 'İşlemler',
|
|
5954
|
+
'hr.approvals_as_self': 'Kendiniz',
|
|
5955
|
+
'hr.approvals_behalf_notice':
|
|
5956
|
+
'{name} adına karar veriyorsunuz. Karar onun adına, sizin adınız da yanında kaydedilir.',
|
|
5957
|
+
'hr.approvals_behalf_pick': 'Kimin kararı?',
|
|
5958
|
+
'hr.approvals_behalf_someone': 'başka bir onaylayan',
|
|
5886
5959
|
'hr.approvals_chains_hint': 'Neyi kimin imzalayacağı modül ayarlarından belirlenir.',
|
|
5960
|
+
'hr.approvals_decide_as': 'Kimin adına',
|
|
5961
|
+
'hr.approvals_decide_as_hint': 'Karar, seçtiğiniz kişinin adına kaydedilir.',
|
|
5962
|
+
'hr.approvals_decide_as_pick': 'Bir kişi seçin',
|
|
5887
5963
|
'hr.approvals_decided': 'Karara bağlananlar',
|
|
5964
|
+
'hr.approvals_decided_behalf': '{person} adına {actor} karar verdi',
|
|
5888
5965
|
'hr.approvals_decided_none': 'Henüz karara bağlanan bir şey yok',
|
|
5889
5966
|
'hr.approvals_decided_none_desc': 'Onayladığınız veya reddettiğiniz talepler burada görünür.',
|
|
5890
5967
|
'hr.approvals_error': 'Onaylarınız yüklenemedi',
|
|
5891
5968
|
'hr.approvals_for': '{name} için',
|
|
5969
|
+
'hr.approvals_later_step': 'Henüz sizin adımınız değil',
|
|
5892
5970
|
'hr.approvals_none': 'Sizi bekleyen bir şey yok',
|
|
5893
5971
|
'hr.approvals_none_desc': 'Kararınızı bekleyen talepler burada görünür.',
|
|
5972
|
+
'hr.approvals_on_behalf': '{name} adına',
|
|
5973
|
+
'hr.approvals_open': 'Onayları aç',
|
|
5974
|
+
'hr.approvals_open_hint': 'Buradan karara bağlanmaz — talebin nerede olduğunu Onaylar sayfası gösterir.',
|
|
5894
5975
|
'hr.approvals_request': 'Talep',
|
|
5895
5976
|
'hr.approvals_requested': 'Talep edildi',
|
|
5896
5977
|
'hr.approvals_requested_by': 'Talep eden',
|
|
@@ -5898,6 +5979,7 @@ export const tr: Record<string, Message> = {
|
|
|
5898
5979
|
'hr.approvals_step_of': '{total} adımdan {n}. adım',
|
|
5899
5980
|
'hr.approvals_title': 'Onaylar',
|
|
5900
5981
|
'hr.approvals_waiting': 'Sizi bekleyenler',
|
|
5982
|
+
'hr.approvals_you_decided': 'Kararınızı verdiniz',
|
|
5901
5983
|
'hr.approve': 'Onayla',
|
|
5902
5984
|
'hr.approve_confirm_attendance': 'Düzeltilen giriş-çıkışlar uygulanır ve o gün yeniden hesaplanır.',
|
|
5903
5985
|
'hr.approve_confirm_leave': 'Günler bakiyesinden düşer ve takım takviminde izinli görünür.',
|
|
@@ -6288,7 +6370,10 @@ export const tr: Record<string, Message> = {
|
|
|
6288
6370
|
'hr.cmd_directory': 'Kişi rehberini aç',
|
|
6289
6371
|
'hr.cmd_request_leave': 'İzin talep et',
|
|
6290
6372
|
'hr.days': { one: 'gün', other: 'gün' },
|
|
6373
|
+
'hr.decide_behalf_error':
|
|
6374
|
+
'Karar kaydedilmedi. Yetki devri sona ermiş olabilir — sayfayı yenileyip yeniden deneyin.',
|
|
6291
6375
|
'hr.decide_error': 'Karar kaydedilemedi',
|
|
6376
|
+
'hr.decide_moved_error': 'Bu talebin kararı artık sizde değil. Liste güncellendi.',
|
|
6292
6377
|
'hr.delegate': 'Devret',
|
|
6293
6378
|
'hr.delegate_add': 'Devir ekle',
|
|
6294
6379
|
'hr.delegate_all_types': 'Tüm talepler',
|