Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7180bbd6d4 | ||
|
|
96ccc01d08 | ||
|
|
2108dd6c94 | ||
|
|
ca2003f2d6 | ||
|
|
acbbac588f | ||
|
|
f75ff97042 |
+20
-13
@@ -49,13 +49,19 @@ concurrency:
|
||||
group: frontend-tests-${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.head_ref || github.ref_name }}
|
||||
cancel-in-progress: true
|
||||
|
||||
# Repository variables used as CI runner and credit controls:
|
||||
# - FRONTEND_CI_STANDARD_RUNNER: JSON runs-on value for format/build/unit jobs.
|
||||
# - FRONTEND_CI_E2E_RUNNER: JSON runs-on value for Playwright jobs.
|
||||
# - FRONTEND_CI_PR_E2E_MAX_PARALLEL: numeric Playwright PR job parallelism.
|
||||
# - FRONTEND_CI_FULL_E2E_MAX_PARALLEL: numeric full-suite job parallelism.
|
||||
# GitHub-hosted example: ["ubuntu-22.04"], with PR parallelism 2 and full parallelism 1.
|
||||
jobs:
|
||||
format-tests:
|
||||
# CI normally runs on the repository's self-hosted pool; manual runs can opt into GitHub-hosted runners.
|
||||
runs-on: ${{ fromJSON(github.event_name == 'workflow_dispatch' && github.event.inputs.runner == 'github-hosted' && '["ubuntu-latest"]' || '["self-hosted","Linux","X64","pleno","frontend"]') }}
|
||||
runs-on: ${{ fromJSON(vars.FRONTEND_CI_STANDARD_RUNNER || '["self-hosted","Linux","X64","pleno","frontend"]') }}
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Normalize workspace permissions
|
||||
- name: Repair self-hosted workspace permissions
|
||||
if: ${{ contains(vars.FRONTEND_CI_STANDARD_RUNNER || 'self-hosted', 'self-hosted') }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -d "$GITHUB_WORKSPACE" ]]; then
|
||||
@@ -88,10 +94,11 @@ jobs:
|
||||
|
||||
build-and-unit:
|
||||
needs: format-tests
|
||||
runs-on: ${{ fromJSON(github.event_name == 'workflow_dispatch' && github.event.inputs.runner == 'github-hosted' && '["ubuntu-latest"]' || '["self-hosted","Linux","X64","pleno","frontend"]') }}
|
||||
runs-on: ${{ fromJSON(vars.FRONTEND_CI_STANDARD_RUNNER || '["self-hosted","Linux","X64","pleno","frontend"]') }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Normalize workspace permissions
|
||||
- name: Repair self-hosted workspace permissions
|
||||
if: ${{ contains(vars.FRONTEND_CI_STANDARD_RUNNER || 'self-hosted', 'self-hosted') }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -d "$GITHUB_WORKSPACE" ]]; then
|
||||
@@ -314,12 +321,11 @@ jobs:
|
||||
)
|
||||
needs: [build-and-unit, e2e-targeted]
|
||||
name: E2E-pr-${{ matrix.suite }}-${{ matrix.project }}
|
||||
# Use GitHub-hosted runners to avoid self-hosted desktop contention and sleep/power events.
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ${{ fromJSON(vars.FRONTEND_CI_E2E_RUNNER || '["self-hosted","Linux","X64","pleno","frontend","docker"]') }}
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 4
|
||||
max-parallel: ${{ fromJSON(vars.FRONTEND_CI_PR_E2E_MAX_PARALLEL || '2') }}
|
||||
matrix:
|
||||
suite: [core, changed]
|
||||
project: [chromium-desktop, chromium-mobile]
|
||||
@@ -329,7 +335,8 @@ jobs:
|
||||
PLAYWRIGHT_WORKERS: 1
|
||||
PLAYWRIGHT_VIDEO_MODE: on-first-retry
|
||||
steps:
|
||||
- name: Normalize workspace permissions
|
||||
- name: Repair self-hosted workspace permissions
|
||||
if: ${{ contains(vars.FRONTEND_CI_E2E_RUNNER || 'self-hosted', 'self-hosted') }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -d "$GITHUB_WORKSPACE" ]]; then
|
||||
@@ -515,12 +522,11 @@ jobs:
|
||||
)
|
||||
needs: [build-and-unit, e2e-pr, e2e-targeted]
|
||||
name: E2E-full-${{ matrix.browser_label }}-${{ matrix.device }}-${{ matrix.role }}
|
||||
runs-on: ${{ fromJSON(github.event_name == 'workflow_dispatch' && github.event.inputs.runner == 'github-hosted' && '["ubuntu-latest"]' || '["self-hosted","Linux","X64","pleno","frontend","docker"]') }}
|
||||
runs-on: ${{ fromJSON(vars.FRONTEND_CI_E2E_RUNNER || '["self-hosted","Linux","X64","pleno","frontend","docker"]') }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
# Manual GitHub-hosted runs can use paid runner capacity to finish the full matrix faster.
|
||||
max-parallel: ${{ fromJSON(github.event_name == 'workflow_dispatch' && github.event.inputs.runner == 'github-hosted' && '12' || '2') }}
|
||||
max-parallel: ${{ fromJSON(vars.FRONTEND_CI_FULL_E2E_MAX_PARALLEL || '1') }}
|
||||
matrix:
|
||||
browser: [chromium, webkit, firefox]
|
||||
device: [mobile, desktop, tablet]
|
||||
@@ -541,7 +547,8 @@ jobs:
|
||||
PLAYWRIGHT_WORKERS: 1
|
||||
PLAYWRIGHT_VIDEO_MODE: off
|
||||
steps:
|
||||
- name: Normalize workspace permissions
|
||||
- name: Repair self-hosted workspace permissions
|
||||
if: ${{ contains(vars.FRONTEND_CI_E2E_RUNNER || 'self-hosted', 'self-hosted') }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -d "$GITHUB_WORKSPACE" ]]; then
|
||||
|
||||
@@ -112,13 +112,24 @@ if (router.currentRoute.value.params.departmentId) {
|
||||
}
|
||||
const isImportLoading = ref(false);
|
||||
|
||||
const buildImportUsageParams = () => {
|
||||
if (!props.inheritPeriodFilters) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
...(props.initialDateFrom ? { dateFrom: props.initialDateFrom } : {}),
|
||||
...(props.initialDateTo ? { dateTo: props.initialDateTo } : {}),
|
||||
};
|
||||
};
|
||||
|
||||
const importUsageButton = async () => {
|
||||
isImportLoading.value = true;
|
||||
try {
|
||||
await SessionUser.request(
|
||||
'/modules/xlvask/tasks/import-usage',
|
||||
'GET',
|
||||
{},
|
||||
buildImportUsageParams(),
|
||||
function (error) {
|
||||
// This function is called when the request fails
|
||||
console.error("Failed to import orders.", error);
|
||||
|
||||
@@ -62,7 +62,7 @@ if (props.autoLoad) {
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<UsersTable :objects="list" />
|
||||
<UsersTable :objects="list" @migrated="loadList" />
|
||||
</TableLabeledPagination>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,21 +1,136 @@
|
||||
<script setup>
|
||||
import EditableTableColumn from "@/components/displays/buttons/EditableTableColumn.vue";
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Swal from "sweetalert2";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
defineProps(['objects']);
|
||||
import { ref } from 'vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { usePaginatedListInstance } from "@/components/pagination/paginatedList.vue";
|
||||
const { loadList } = usePaginatedListInstance();
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
||||
import ActionSettingsWheelItem from "@/components/displays/buttons/ActionSettingsWheelItem.vue";
|
||||
import ActionSettingsWheelItemLabel from "@/components/displays/buttons/ActionSettingsWheelItemLabel.vue";
|
||||
|
||||
const redirect = (path) => {
|
||||
window.location = path;
|
||||
}
|
||||
|
||||
const limitedBackofficeTemplates = ref([]);
|
||||
const templatesLoading = ref(false);
|
||||
const templatesLoadError = ref(false);
|
||||
const applyingTemplateKey = ref("");
|
||||
|
||||
const canApplyLimitedBackofficeTemplates = computed(() => SessionUser.hasPermission("add_role_permission"));
|
||||
|
||||
const loadLimitedBackofficeTemplates = async () => {
|
||||
if (!canApplyLimitedBackofficeTemplates.value || templatesLoading.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
templatesLoading.value = true;
|
||||
templatesLoadError.value = false;
|
||||
try {
|
||||
const templates = await SessionUser.objects.roles.functions.getLimitedBackofficePermissionTemplates();
|
||||
limitedBackofficeTemplates.value = Array.isArray(templates) ? templates : [];
|
||||
} catch (error) {
|
||||
console.error("Failed to load limited backoffice permission templates", error);
|
||||
templatesLoadError.value = true;
|
||||
} finally {
|
||||
templatesLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const templateTranslation = (template, field) => {
|
||||
const key = `templates.limited_backoffice.roles.${template?.key}.${field}`;
|
||||
const translated = t(key);
|
||||
return translated === key ? template?.[field] || template?.key || "" : translated;
|
||||
};
|
||||
|
||||
const templateLabel = (template) => templateTranslation(template, "label");
|
||||
|
||||
const rolePermissions = (role) => (Array.isArray(role?.permissions) ? role.permissions : []);
|
||||
const templatePermissions = (template) => (Array.isArray(template?.permissions) ? template.permissions : []);
|
||||
|
||||
const missingTemplatePermissions = (role, template) => {
|
||||
const currentPermissions = new Set(rolePermissions(role));
|
||||
return templatePermissions(template).filter((permission) => permission && !currentPermissions.has(permission));
|
||||
};
|
||||
|
||||
const roleTemplateActionKey = (role, template) => `${role?.id}:${template?.key}`;
|
||||
const isApplyingTemplate = (role, template) => applyingTemplateKey.value === roleTemplateActionKey(role, template);
|
||||
const isTemplateActionDisabled = (role, template) =>
|
||||
templatesLoading.value || Boolean(applyingTemplateKey.value) || missingTemplatePermissions(role, template).length === 0;
|
||||
|
||||
const applyLimitedBackofficeTemplate = async (role, template) => {
|
||||
const missingPermissions = missingTemplatePermissions(role, template);
|
||||
const label = templateLabel(template);
|
||||
|
||||
if (missingPermissions.length === 0) {
|
||||
await Swal.fire({
|
||||
icon: "success",
|
||||
title: t("roles.templates.up_to_date_title"),
|
||||
text: t("roles.templates.up_to_date_text", { role: role.name, template: label }),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmation = await Swal.fire({
|
||||
icon: "question",
|
||||
title: t("roles.templates.confirm_title"),
|
||||
text: t("roles.templates.confirm_text", {
|
||||
count: missingPermissions.length,
|
||||
role: role.name,
|
||||
template: label,
|
||||
}),
|
||||
showCancelButton: true,
|
||||
confirmButtonText: t("roles.templates.confirm_button"),
|
||||
cancelButtonText: t("common.cancel"),
|
||||
});
|
||||
|
||||
if (!confirmation.isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyingTemplateKey.value = roleTemplateActionKey(role, template);
|
||||
try {
|
||||
const results = await Promise.allSettled(
|
||||
missingPermissions.map((permission) =>
|
||||
SessionUser.objects.roles.functions.permissions.add(role.id, permission)
|
||||
)
|
||||
);
|
||||
const failed = results.filter((result) => result.status === "rejected");
|
||||
|
||||
if (failed.length > 0) {
|
||||
throw failed[0].reason;
|
||||
}
|
||||
|
||||
await Swal.fire({
|
||||
icon: "success",
|
||||
title: t("roles.templates.success_title"),
|
||||
text: t("roles.templates.success_text", {
|
||||
count: missingPermissions.length,
|
||||
role: role.name,
|
||||
template: label,
|
||||
}),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to apply limited backoffice permission template", error);
|
||||
await Swal.fire({
|
||||
icon: "error",
|
||||
title: t("roles.templates.error_title"),
|
||||
text: t("roles.templates.error_text", { role: role.name, template: label }),
|
||||
});
|
||||
} finally {
|
||||
applyingTemplateKey.value = "";
|
||||
await loadList();
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(loadLimitedBackofficeTemplates);
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -66,6 +181,46 @@ const redirect = (path) => {
|
||||
icon="fas fa-clone"
|
||||
:click-action="() => SessionUser.objects.roles.functions.cloneObject(object.id).then(() => loadList())"
|
||||
></ActionSettingsWheelItem>
|
||||
|
||||
<div
|
||||
v-if="canApplyLimitedBackofficeTemplates"
|
||||
class="role-limited-backoffice-template-actions"
|
||||
:data-testid="`role-limited-backoffice-template-actions-${object.id}`"
|
||||
>
|
||||
<ActionSettingsWheelItemLabel
|
||||
:label="$t('roles.templates.section')"
|
||||
icon="fas fa-id-badge"
|
||||
></ActionSettingsWheelItemLabel>
|
||||
<ActionSettingsWheelItem
|
||||
v-if="templatesLoading"
|
||||
:label="$t('roles.templates.loading')"
|
||||
icon="fas fa-spinner"
|
||||
disabled
|
||||
></ActionSettingsWheelItem>
|
||||
<ActionSettingsWheelItem
|
||||
v-else-if="templatesLoadError"
|
||||
:label="$t('roles.templates.load_error')"
|
||||
icon="fas fa-sync-alt"
|
||||
:click-action="loadLimitedBackofficeTemplates"
|
||||
></ActionSettingsWheelItem>
|
||||
<ActionSettingsWheelItem
|
||||
v-else-if="limitedBackofficeTemplates.length === 0"
|
||||
:label="$t('roles.templates.unavailable')"
|
||||
icon="fas fa-ban"
|
||||
disabled
|
||||
></ActionSettingsWheelItem>
|
||||
<template v-else>
|
||||
<ActionSettingsWheelItem
|
||||
v-for="template in limitedBackofficeTemplates"
|
||||
:key="template.key"
|
||||
:label="$t('roles.templates.apply', { template: templateLabel(template) })"
|
||||
:icon="isApplyingTemplate(object, template) ? 'fas fa-spinner' : 'fas fa-id-badge'"
|
||||
:disabled="isTemplateActionDisabled(object, template)"
|
||||
:test-id="`role-template-${object.id}-${template.key}`"
|
||||
:click-action="() => applyLimitedBackofficeTemplate(object, template)"
|
||||
></ActionSettingsWheelItem>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</ActionSettingsWheelButton>
|
||||
</div>
|
||||
@@ -85,4 +240,4 @@ const redirect = (path) => {
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
||||
import ActionSettingsWheelItem from "@/components/displays/buttons/ActionSettingsWheelItem.vue";
|
||||
import { showEditUserForm } from "@/components/forms/superUser/editUserForm.vue";
|
||||
import {
|
||||
getLimitedBackofficeDepartments,
|
||||
getLimitedBackofficeRoles,
|
||||
limitedBackofficeErrorMessage,
|
||||
migrateLimitedBackofficeEmployee,
|
||||
unwrapLimitedBackofficeResponse,
|
||||
} from "@/services/limitedBackoffice.js";
|
||||
import Swal from "sweetalert2";
|
||||
|
||||
defineProps({
|
||||
objects: {
|
||||
@@ -10,11 +18,110 @@ defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["migrated"]);
|
||||
|
||||
const editUser = (user) => {
|
||||
showEditUserForm(user.id, user.customer_number, user.display_name, user.group_id, {
|
||||
limitedBackofficeManaged: Boolean(user.limited_backoffice_managed),
|
||||
});
|
||||
};
|
||||
|
||||
const escapeHtml = (value) =>
|
||||
String(value ?? "")
|
||||
.replaceAll("&", "&")
|
||||
.replaceAll("<", "<")
|
||||
.replaceAll(">", ">")
|
||||
.replaceAll('"', """)
|
||||
.replaceAll("'", "'");
|
||||
|
||||
const canMigrateToLimitedBackoffice = (user) =>
|
||||
Number(user?.customer_number) === 0 && !Boolean(user?.limited_backoffice_managed);
|
||||
|
||||
const migrateUser = async (user) => {
|
||||
try {
|
||||
const [departmentsResponse, rolesResponse] = await Promise.all([
|
||||
getLimitedBackofficeDepartments(),
|
||||
getLimitedBackofficeRoles(),
|
||||
]);
|
||||
const departments = unwrapLimitedBackofficeResponse(departmentsResponse) || [];
|
||||
const roles = unwrapLimitedBackofficeResponse(rolesResponse) || [];
|
||||
|
||||
if (!Array.isArray(departments) || departments.length === 0 || !Array.isArray(roles) || roles.length === 0) {
|
||||
throw new Error("Limited backoffice roles or departments are unavailable.");
|
||||
}
|
||||
|
||||
const roleOptions = roles
|
||||
.filter((role) => role?.key && role?.key !== "superuser")
|
||||
.map((role) => {
|
||||
const selected = role.key === "cashier" ? " selected" : "";
|
||||
return `<option value="${escapeHtml(role.key)}"${selected}>${escapeHtml(role.label || role.key)}</option>`;
|
||||
})
|
||||
.join("");
|
||||
const departmentOptions = departments
|
||||
.map(
|
||||
(department) => `
|
||||
<label class="checkbox is-block has-text-left mb-2">
|
||||
<input type="checkbox" class="limited-migration-department" value="${escapeHtml(department.id)}" />
|
||||
${escapeHtml(department.name || `Department ${department.id}`)}
|
||||
</label>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
|
||||
const result = await Swal.fire({
|
||||
title: "Migrate employee",
|
||||
html: `
|
||||
<div class="field has-text-left">
|
||||
<label class="label">Employee</label>
|
||||
<p>${escapeHtml(user.display_name || `#${user.id}`)}</p>
|
||||
</div>
|
||||
<div class="field has-text-left">
|
||||
<label class="label" for="limited-migration-role">Role</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select id="limited-migration-role">${roleOptions}</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field has-text-left">
|
||||
<label class="label">Departments</label>
|
||||
<div class="control">${departmentOptions}</div>
|
||||
</div>
|
||||
`,
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Migrate",
|
||||
preConfirm: async () => {
|
||||
const role = document.getElementById("limited-migration-role")?.value;
|
||||
const departmentIds = Array.from(document.querySelectorAll(".limited-migration-department:checked")).map(
|
||||
(checkbox) => Number(checkbox.value)
|
||||
);
|
||||
|
||||
if (!role || departmentIds.length === 0) {
|
||||
Swal.showValidationMessage("Select a role and at least one department.");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
await migrateLimitedBackofficeEmployee(user.id, {
|
||||
role_key: role,
|
||||
department_ids: departmentIds,
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
Swal.showValidationMessage(limitedBackofficeErrorMessage(error, "Could not migrate employee."));
|
||||
return false;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (result.isConfirmed) {
|
||||
await Swal.fire("Employee migrated");
|
||||
emit("migrated");
|
||||
}
|
||||
} catch (error) {
|
||||
await Swal.fire("Error", limitedBackofficeErrorMessage(error, "Could not migrate employee."), "error");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -47,6 +154,13 @@ const editUser = (user) => {
|
||||
:label="$t('global.edit')"
|
||||
:test-id="`superuser-user-edit-${user.id}`"
|
||||
/>
|
||||
<ActionSettingsWheelItem
|
||||
v-if="canMigrateToLimitedBackoffice(user)"
|
||||
:click-action="() => migrateUser(user)"
|
||||
icon="fas fa-random"
|
||||
:label="$t('superuser.pages.employees.migrate_to_limited_backoffice')"
|
||||
:test-id="`superuser-user-migrate-limited-${user.id}`"
|
||||
/>
|
||||
</template>
|
||||
</ActionSettingsWheelButton>
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,25 @@
|
||||
<script setup>
|
||||
|
||||
const props = defineProps(['invoice_id'])
|
||||
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
|
||||
import LoadButtonWhileAwait from "@/components/request/LoadButtonWhileAwait.vue";
|
||||
import { handleEconomicError } from "@/components/request/HandleEconomicError.vue";
|
||||
import { ref } from "vue";
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps(["invoice_id"]);
|
||||
|
||||
const hasInvoice = computed(() => {
|
||||
return props.invoice_id !== null && props.invoice_id !== undefined && String(props.invoice_id).trim() !== "";
|
||||
});
|
||||
|
||||
const getOrderPDF = async () => {
|
||||
await authenticatedRequest('/invoices/pdf?id=' + props.invoice_id,
|
||||
'GET',{
|
||||
}) .then((response) => {
|
||||
if (!hasInvoice.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
await authenticatedRequest("/invoices/pdf", "GET", {
|
||||
id: props.invoice_id,
|
||||
}).then((response) => {
|
||||
// Open the PDF in a new tab
|
||||
window.open(response.data.data.url, '_blank');
|
||||
window.open(response.data.data.url, "_blank");
|
||||
}).catch((error) => {
|
||||
handleEconomicError(error);
|
||||
});
|
||||
@@ -19,9 +27,17 @@ const getOrderPDF = async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LoadButtonWhileAwait class="is-dark" :loadFunction="getOrderPDF" icon="fas fa-file-pdf"> Hent faktura PDF </LoadButtonWhileAwait>
|
||||
<LoadButtonWhileAwait
|
||||
class="is-dark"
|
||||
:loadFunction="getOrderPDF"
|
||||
:disabled="!hasInvoice"
|
||||
actionKey="economic-invoice-pdf-download"
|
||||
icon="fas fa-file-pdf"
|
||||
>
|
||||
Hent faktura PDF
|
||||
</LoadButtonWhileAwait>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script>
|
||||
import Swal from "sweetalert2";
|
||||
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
|
||||
import { ObjectsGlobal } from "@/components/session/token/SessionUser/Objects/ObjectsGlobal.vue";
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
@@ -123,6 +122,10 @@ export const Roles = {
|
||||
id: id
|
||||
});
|
||||
},
|
||||
getLimitedBackofficePermissionTemplates: async () => {
|
||||
const response = await authenticatedRequest("/roles/limited-backoffice-permission-templates", "GET");
|
||||
return response?.data?.data ?? response?.data ?? [];
|
||||
},
|
||||
permissions: {
|
||||
add: async (roleId, permissionId) => {
|
||||
return authenticatedRequest("/roles/permissions", "POST", {
|
||||
@@ -161,4 +164,4 @@ export const Roles = {
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -1270,6 +1270,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -1321,6 +1326,66 @@
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -4983,6 +5048,22 @@
|
||||
"title": "Tilladelser for rolle {id}",
|
||||
"title_with_name": "Tilladelser for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Anvend {template}-skabelon",
|
||||
"confirm_button": "Anvend skabelon",
|
||||
"confirm_text": "Tilfoej {count} manglende tilladelser fra {template} til {role}?",
|
||||
"confirm_title": "Anvend tilladelsesskabelon?",
|
||||
"error_text": "En eller flere tilladelser fra {template} kunne ikke tilfoejes til {role}. Rollelisten blev genindlaest.",
|
||||
"error_title": "Kunne ikke anvende skabelon",
|
||||
"load_error": "Kunne ikke indlaese skabeloner. Proev igen",
|
||||
"loading": "Indlaeser skabeloner...",
|
||||
"section": "Begraenset backoffice-skabeloner",
|
||||
"success_text": "Tilfoejede {count} tilladelser fra {template} til {role}.",
|
||||
"success_title": "Skabelon anvendt",
|
||||
"unavailable": "Ingen skabeloner er tilgaengelige.",
|
||||
"up_to_date_text": "{role} har allerede alle tilladelser i {template}.",
|
||||
"up_to_date_title": "Rollen er opdateret"
|
||||
},
|
||||
"subtitle": "@.capitalize:{'words.generated.brugerroller'}"
|
||||
},
|
||||
"self_wash": {
|
||||
@@ -5392,6 +5473,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@:{'words.generated.opret'} @:{'words.generated.ny'} @:{'words.generated.medarbejder'}",
|
||||
"migrate_to_limited_backoffice": "Migrer til begrænset backoffice",
|
||||
"subtitle": "@.capitalize:{'words.generated.her'} @:{'words.generated.kan'} @:{'words.generated.du'} @:{'words.generated.se'} @:{'words.replication.host_definite_suffix'} @:{'words.generated.liste'} @:{'words.generated.over'} @:{'words.generated.alle'} @:{'words.generated.medarbejdere'} @:{'words.generated.i'} @:{'words.generated.systemet'}"
|
||||
},
|
||||
"orders": {
|
||||
@@ -6135,12 +6217,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Viser",
|
||||
"description": "@.capitalize:{'words.generated.kan'} logge ind @:{'words.generated.og'} se data @:{'words.generated.for'} @:{'words.generated.tildelte'} @:{'words.generated.afdelinger'}."
|
||||
"label": "Deaktiveret",
|
||||
"description": "Holder medarbejderen registreret uden adgang til ordre-, booking- eller administrationsfunktioner."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Kassemedarbejder",
|
||||
"description": "@.capitalize:{'words.generated.kan'} arbejde med @:{'words.generated.ordrer'} @:{'words.generated.og'} ordrelinjer @:{'words.generated.for'} @:{'words.generated.tildelte'} @:{'words.generated.afdelinger'}."
|
||||
"description": "@.capitalize:{'words.generated.kan'} arbejde med @:{'words.generated.ordrer'}, ordrelinjer @:{'words.generated.og'} @:{'words.generated.bookinger'} @:{'words.generated.for'} @:{'words.generated.tildelte'} @:{'words.generated.afdelinger'}."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Bookingkoordinator",
|
||||
@@ -6175,6 +6257,11 @@
|
||||
"groups": {
|
||||
"account": "Konto",
|
||||
"orders": "Ordrer",
|
||||
"products": "Produkter",
|
||||
"customers": "Kunder",
|
||||
"vehicles": "Køretøjer",
|
||||
"attachments": "Vedhæftninger",
|
||||
"scanner": "Scannere",
|
||||
"bookings": "Bookinger",
|
||||
"time_bookings": "Tidsbookinger",
|
||||
"reports": "Rapporter",
|
||||
@@ -6226,6 +6313,66 @@
|
||||
"label": "Opkræv ordrer",
|
||||
"description": "Kan tage betaling eller opkræve en betalingsreservation for en ordre."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Afslut ordrer",
|
||||
"description": "Kan markere ordrer som afsluttede."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "Se produktkatalog",
|
||||
"description": "Kan indlæse POS-kategorier, produkter, priser og tilvalg."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "Se produktforslag",
|
||||
"description": "Kan se produktforslag baseret på ordrer og køretøjsdata."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Søg kunder",
|
||||
"description": "Kan søge og vælge kunder til POS-ordrer."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "Se kundeoplysninger",
|
||||
"description": "Kan indlæse kundeoplysninger fra et kundenummer."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "Se kundebemærkninger",
|
||||
"description": "Kan læse kundebemærkninger i POS."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Tilføj kundebemærkninger",
|
||||
"description": "Kan tilføje kundebemærkninger fra POS."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "Se kundemarkeringer",
|
||||
"description": "Kan se kundemarkeringer, der påvirker ordrekrav og produktregler."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Søg køretøjer",
|
||||
"description": "Kan søge nummerplader og se køretøjsstatus."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "Se køretøjsmatch",
|
||||
"description": "Kan se kundematch for køretøjer og forslag til ukendte køretøjer."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "Se køretøjshistorik",
|
||||
"description": "Kan se seneste ordrehistorik for en nummerplade."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "Se ordrevedhæftninger",
|
||||
"description": "Kan liste vedhæftninger på ordrer."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Tilføj ordrevedhæftninger",
|
||||
"description": "Kan uploade filer og vedhæfte vaskecertifikater til ordrer."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Download ordrevedhæftninger",
|
||||
"description": "Kan åbne og downloade ordrevedhæftninger."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "Se nummerpladescanninger",
|
||||
"description": "Kan se seneste nummerpladescanninger og scannere for tildelte afdelinger."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "Se afdelingsbookinger",
|
||||
"description": "Kan se bookinger for tildelte afdelinger."
|
||||
|
||||
@@ -1381,6 +1381,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -1432,6 +1437,66 @@
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -5094,6 +5159,22 @@
|
||||
"title": "Berechtigungen fuer Rolle {id}",
|
||||
"title_with_name": "Berechtigungen fuer {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "{template}-Vorlage anwenden",
|
||||
"confirm_button": "Vorlage anwenden",
|
||||
"confirm_text": "{count} fehlende Berechtigungen aus {template} zu {role} hinzufuegen?",
|
||||
"confirm_title": "Berechtigungsvorlage anwenden?",
|
||||
"error_text": "Eine oder mehrere Berechtigungen aus {template} konnten {role} nicht hinzugefuegt werden. Die Rollenliste wurde neu geladen.",
|
||||
"error_title": "Vorlage konnte nicht angewendet werden",
|
||||
"load_error": "Vorlagen konnten nicht geladen werden. Erneut versuchen",
|
||||
"loading": "Vorlagen werden geladen...",
|
||||
"section": "Limited-Backoffice-Vorlagen",
|
||||
"success_text": "{count} Berechtigungen aus {template} zu {role} hinzugefuegt.",
|
||||
"success_title": "Vorlage angewendet",
|
||||
"unavailable": "Keine Vorlagen verfuegbar.",
|
||||
"up_to_date_text": "{role} hat bereits alle Berechtigungen in {template}.",
|
||||
"up_to_date_title": "Rolle ist aktuell"
|
||||
},
|
||||
"subtitle": "Benutzerrollen"
|
||||
},
|
||||
"self_wash": {
|
||||
@@ -5503,6 +5584,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@.capitalize:{'words.generated.neuen'} @:{'words.generated.mitarbeiter'} @:{'words.generated.erstellen'}",
|
||||
"migrate_to_limited_backoffice": "Zu eingeschränktem Backoffice migrieren",
|
||||
"subtitle": "@.capitalize:{'words.generated.hier'} @:{'words.generated.sehen'} @.capitalize:{'words.generated.sie'} @:{'words.generated.eine'} @:{'words.generated.liste'} @:{'words.generated.aller'} @:{'words.generated.mitarbeiter'} @:{'words.generated.im'} @.capitalize:{'words.generated.system'}"
|
||||
},
|
||||
"orders": {
|
||||
@@ -6246,12 +6328,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Betrachter",
|
||||
"description": "@.capitalize:{'words.generated.kann'} sich anmelden @:{'words.generated.und'} Daten zugewiesener @:{'words.generated.abteilungen'} @:{'words.generated.anzeigen'}."
|
||||
"label": "Deaktiviert",
|
||||
"description": "Hält den Mitarbeiter registriert, ohne Zugriff auf Auftrags-, Buchungs- oder Verwaltungsfunktionen."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Kassierer",
|
||||
"description": "@.capitalize:{'words.generated.kann'} mit Aufträgen @:{'words.generated.und'} Auftragszeilen @:{'words.generated.fur'} @:{'words.generated.zugewiesene'} @:{'words.generated.abteilungen'} arbeiten."
|
||||
"description": "@.capitalize:{'words.generated.kann'} mit Aufträgen, Auftragszeilen @:{'words.generated.und'} @:{'words.generated.buchungen'} @:{'words.generated.fur'} @:{'words.generated.zugewiesene'} @:{'words.generated.abteilungen'} arbeiten."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Buchungskoordinator",
|
||||
@@ -6286,6 +6368,11 @@
|
||||
"groups": {
|
||||
"account": "Konto",
|
||||
"orders": "Aufträge",
|
||||
"products": "Produkte",
|
||||
"customers": "Kunden",
|
||||
"vehicles": "Fahrzeuge",
|
||||
"attachments": "Anhänge",
|
||||
"scanner": "Scanner",
|
||||
"bookings": "Buchungen",
|
||||
"time_bookings": "Zeitbuchungen",
|
||||
"reports": "Berichte",
|
||||
@@ -6337,6 +6424,66 @@
|
||||
"label": "Aufträge abrechnen",
|
||||
"description": "Kann Zahlungen annehmen oder eine Zahlungsreservierung für einen Auftrag belasten."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Aufträge abschließen",
|
||||
"description": "Kann Aufträge als abgeschlossen markieren."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "Produktkatalog anzeigen",
|
||||
"description": "Kann POS-Kategorien, Produkte, Preise und Zusatzoptionen laden."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "Produktempfehlungen anzeigen",
|
||||
"description": "Kann Produktempfehlungen auf Basis von Aufträgen und Fahrzeugdaten sehen."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Kunden suchen",
|
||||
"description": "Kann Kunden für POS-Aufträge suchen und auswählen."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "Kundendetails anzeigen",
|
||||
"description": "Kann Kundendetails anhand einer Kundennummer laden."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "Kundennotizen anzeigen",
|
||||
"description": "Kann Kundennotizen im POS lesen."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Kundennotizen hinzufügen",
|
||||
"description": "Kann Kundennotizen im POS hinzufügen."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "Kundenmarkierungen anzeigen",
|
||||
"description": "Kann Kundenmarkierungen sehen, die Auftragsanforderungen und Produktregeln beeinflussen."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Fahrzeuge suchen",
|
||||
"description": "Kann Kennzeichen suchen und den Fahrzeugstatus sehen."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "Fahrzeugtreffer anzeigen",
|
||||
"description": "Kann Kundentreffer für Fahrzeuge und Vorschläge zu unbekannten Fahrzeugen sehen."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "Fahrzeughistorie anzeigen",
|
||||
"description": "Kann die letzte Auftragshistorie für ein Kennzeichen sehen."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "Auftragsanhänge anzeigen",
|
||||
"description": "Kann Anhänge auf Aufträgen auflisten."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Auftragsanhänge hinzufügen",
|
||||
"description": "Kann Dateien hochladen und Waschzertifikate an Aufträge anhängen."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Auftragsanhänge herunterladen",
|
||||
"description": "Kann Auftragsanhänge öffnen und herunterladen."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "Kennzeichenscans anzeigen",
|
||||
"description": "Kann aktuelle Kennzeichenscans und Scanner für zugewiesene Abteilungen sehen."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "Abteilungsbuchungen anzeigen",
|
||||
"description": "Kann Buchungen für zugewiesene Abteilungen sehen."
|
||||
|
||||
@@ -1102,6 +1102,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -1153,6 +1158,66 @@
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -4815,6 +4880,22 @@
|
||||
"title": "Role {id} permissions",
|
||||
"title_with_name": "{name} permissions"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Apply {template} template",
|
||||
"confirm_button": "Apply template",
|
||||
"confirm_text": "Add {count} missing permissions from {template} to {role}?",
|
||||
"confirm_title": "Apply permission template?",
|
||||
"error_text": "One or more permissions from {template} could not be added to {role}. The role list was reloaded.",
|
||||
"error_title": "Could not apply template",
|
||||
"load_error": "Could not load templates. Try again",
|
||||
"loading": "Loading templates...",
|
||||
"section": "Limited backoffice templates",
|
||||
"success_text": "Added {count} permissions from {template} to {role}.",
|
||||
"success_title": "Template applied",
|
||||
"unavailable": "No templates are available.",
|
||||
"up_to_date_text": "{role} already has every permission in {template}.",
|
||||
"up_to_date_title": "Role is up to date"
|
||||
},
|
||||
"subtitle": "@.capitalize:{'words.generated.user'} @:{'words.generated.roles'}"
|
||||
},
|
||||
"self_wash": {
|
||||
@@ -5224,6 +5305,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@.capitalize:{'words.generated.create'} @:{'words.generated.new'} @:{'words.generated.employee'}",
|
||||
"migrate_to_limited_backoffice": "Migrate to limited backoffice",
|
||||
"subtitle": "@.capitalize:{'words.generated.here'} @:{'words.generated.you'} @:{'words.generated.can'} @:{'words.generated.see'} @:{'words.generated.a'} @:{'words.generated.list'} @:{'words.generated.of'} @:{'words.generated.all'} @:{'words.generated.employees'} @:{'words.generated.in'} @:{'words.replication.article.host_mention'} @:{'words.generated.system'}"
|
||||
},
|
||||
"orders": {
|
||||
@@ -5967,12 +6049,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Viewer",
|
||||
"description": "@.capitalize:{'words.generated.can'} sign @:{'words.generated.in'} @:{'words.generated.and'} view @:{'words.generated.assigned'} @:{'words.generated.department'} data."
|
||||
"label": "Deactivated",
|
||||
"description": "Keeps the employee registered without order, booking, or management permissions."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Cashier",
|
||||
"description": "@.capitalize:{'words.generated.can'} work with @:{'words.generated.orders'} @:{'words.generated.and'} order lines @:{'words.generated.for'} @:{'words.generated.assigned'} @:{'words.generated.departments'}."
|
||||
"description": "@.capitalize:{'words.generated.can'} work with @:{'words.generated.orders'}, order lines @:{'words.generated.and'} @:{'words.generated.bookings'} @:{'words.generated.for'} @:{'words.generated.assigned'} @:{'words.generated.departments'}."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Booking coordinator",
|
||||
@@ -6007,6 +6089,11 @@
|
||||
"groups": {
|
||||
"account": "Account",
|
||||
"orders": "Orders",
|
||||
"products": "Products",
|
||||
"customers": "Customers",
|
||||
"vehicles": "Vehicles",
|
||||
"attachments": "Attachments",
|
||||
"scanner": "Scanners",
|
||||
"bookings": "Bookings",
|
||||
"time_bookings": "Time bookings",
|
||||
"reports": "Reports",
|
||||
@@ -6058,6 +6145,66 @@
|
||||
"label": "Charge orders",
|
||||
"description": "Can take payment or charge a payment intent for an order."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Complete orders",
|
||||
"description": "Can mark orders as completed."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "View product catalog",
|
||||
"description": "Can load POS categories, products, prices, and addons."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "View product recommendations",
|
||||
"description": "Can see product suggestions based on orders and vehicle data."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Search customers",
|
||||
"description": "Can search and select customers for POS orders."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "View customer details",
|
||||
"description": "Can load customer details from a customer number."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "View customer notes",
|
||||
"description": "Can read customer notes in POS."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Add customer notes",
|
||||
"description": "Can add customer notes from POS."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "View customer flags",
|
||||
"description": "Can see customer flags that affect order requirements and product rules."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Search vehicles",
|
||||
"description": "Can search license plates and see vehicle status."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "View vehicle matches",
|
||||
"description": "Can see vehicle customer matches and unknown vehicle suggestions."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "View vehicle history",
|
||||
"description": "Can see recent order history for a license plate."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "View order attachments",
|
||||
"description": "Can list attachments on orders."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Add order attachments",
|
||||
"description": "Can upload files and attach wash certificates to orders."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Download order attachments",
|
||||
"description": "Can open and download order attachments."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "View plate scans",
|
||||
"description": "Can view recent license plate scans and scanners for assigned departments."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "View department bookings",
|
||||
"description": "Can see bookings for assigned departments."
|
||||
|
||||
@@ -4373,6 +4373,22 @@
|
||||
"title": "@:{'templates.generated.compat.roles.permissions.title'}",
|
||||
"title_with_name": "@:{'templates.generated.compat.roles.permissions.title_with_name'}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "@:{'templates.generated.compat.roles.templates.apply'}",
|
||||
"confirm_button": "@:{'templates.generated.compat.roles.templates.confirm_button'}",
|
||||
"confirm_text": "@:{'templates.generated.compat.roles.templates.confirm_text'}",
|
||||
"confirm_title": "@:{'templates.generated.compat.roles.templates.confirm_title'}",
|
||||
"error_text": "@:{'templates.generated.compat.roles.templates.error_text'}",
|
||||
"error_title": "@:{'templates.generated.compat.roles.templates.error_title'}",
|
||||
"load_error": "@:{'templates.generated.compat.roles.templates.load_error'}",
|
||||
"loading": "@:{'templates.generated.compat.roles.templates.loading'}",
|
||||
"section": "@:{'templates.generated.compat.roles.templates.section'}",
|
||||
"success_text": "@:{'templates.generated.compat.roles.templates.success_text'}",
|
||||
"success_title": "@:{'templates.generated.compat.roles.templates.success_title'}",
|
||||
"unavailable": "@:{'templates.generated.compat.roles.templates.unavailable'}",
|
||||
"up_to_date_text": "@:{'templates.generated.compat.roles.templates.up_to_date_text'}",
|
||||
"up_to_date_title": "@:{'templates.generated.compat.roles.templates.up_to_date_title'}"
|
||||
},
|
||||
"subtitle": "@:{'templates.generated.compat.roles.subtitle'}",
|
||||
"title": "@:{'templates.generated.compat.common.roles'}"
|
||||
},
|
||||
|
||||
@@ -1384,6 +1384,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -1435,6 +1440,66 @@
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -5097,6 +5162,22 @@
|
||||
"title": "Tillatelser for rolle {id}",
|
||||
"title_with_name": "Tillatelser for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Bruk {template}-mal",
|
||||
"confirm_button": "Bruk mal",
|
||||
"confirm_text": "Legg til {count} manglende tillatelser fra {template} til {role}?",
|
||||
"confirm_title": "Bruke tillatelsesmal?",
|
||||
"error_text": "En eller flere tillatelser fra {template} kunne ikke legges til i {role}. Rollelisten ble lastet inn pa nytt.",
|
||||
"error_title": "Kunne ikke bruke mal",
|
||||
"load_error": "Kunne ikke laste maler. Prov igjen",
|
||||
"loading": "Laster maler...",
|
||||
"section": "Begrenset backoffice-maler",
|
||||
"success_text": "La til {count} tillatelser fra {template} i {role}.",
|
||||
"success_title": "Mal brukt",
|
||||
"unavailable": "Ingen maler er tilgjengelige.",
|
||||
"up_to_date_text": "{role} har allerede alle tillatelser i {template}.",
|
||||
"up_to_date_title": "Rollen er oppdatert"
|
||||
},
|
||||
"subtitle": "@.capitalize:{'words.generated.user'} roles"
|
||||
},
|
||||
"self_wash": {
|
||||
@@ -5506,6 +5587,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@:{'words.generated.opprett'} @:{'words.generated.ny'} medarbeider",
|
||||
"migrate_to_limited_backoffice": "Migrer til begrenset backoffice",
|
||||
"subtitle": "@.capitalize:{'words.generated.her'} @:{'words.generated.kan'} @:{'words.generated.du'} @:{'words.generated.se'} @:{'words.replication.host_definite_suffix'} @:{'words.generated.liste'} @:{'words.generated.over'} @:{'words.generated.alle'} @:{'words.generated.ansatte'} @:{'words.generated.i'} @:{'words.generated.systemet'}"
|
||||
},
|
||||
"orders": {
|
||||
@@ -6249,12 +6331,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Viser",
|
||||
"description": "@.capitalize:{'words.generated.kan'} logge inn @:{'words.generated.og'} se data @:{'words.generated.for'} @:{'words.generated.tildelte'} @:{'words.generated.avdelinger'}."
|
||||
"label": "Deaktivert",
|
||||
"description": "Holder den ansatte registrert uten tilgang til ordre-, booking- eller administrasjonsfunksjoner."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Kasserer",
|
||||
"description": "@.capitalize:{'words.generated.kan'} arbeide med @:{'words.generated.ordre'} @:{'words.generated.og'} ordrelinjer @:{'words.generated.for'} @:{'words.generated.tildelte'} @:{'words.generated.avdelinger'}."
|
||||
"description": "@.capitalize:{'words.generated.kan'} arbeide med @:{'words.generated.ordre'}, ordrelinjer @:{'words.generated.og'} @:{'words.generated.bookinger'} @:{'words.generated.for'} @:{'words.generated.tildelte'} @:{'words.generated.avdelinger'}."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Bookingkoordinator",
|
||||
@@ -6289,6 +6371,11 @@
|
||||
"groups": {
|
||||
"account": "Konto",
|
||||
"orders": "Ordrer",
|
||||
"products": "Produkter",
|
||||
"customers": "Kunder",
|
||||
"vehicles": "Kjøretøy",
|
||||
"attachments": "Vedlegg",
|
||||
"scanner": "Skannere",
|
||||
"bookings": "Bookinger",
|
||||
"time_bookings": "Tidsbookinger",
|
||||
"reports": "Rapporter",
|
||||
@@ -6340,6 +6427,66 @@
|
||||
"label": "Belast ordrer",
|
||||
"description": "Kan ta betaling eller belaste en betalingsreservasjon for en ordre."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Fullfør ordrer",
|
||||
"description": "Kan markere ordrer som fullført."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "Se produktkatalog",
|
||||
"description": "Kan laste POS-kategorier, produkter, priser og tillegg."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "Se produktforslag",
|
||||
"description": "Kan se produktforslag basert på ordrer og kjøretøydata."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Søk kunder",
|
||||
"description": "Kan søke og velge kunder for POS-ordrer."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "Se kundeopplysninger",
|
||||
"description": "Kan laste kundeopplysninger fra et kundenummer."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "Se kundemerknader",
|
||||
"description": "Kan lese kundemerknader i POS."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Legg til kundemerknader",
|
||||
"description": "Kan legge til kundemerknader fra POS."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "Se kundemarkeringer",
|
||||
"description": "Kan se kundemarkeringer som påvirker ordrekrav og produktregler."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Søk kjøretøy",
|
||||
"description": "Kan søke etter registreringsnummer og se kjøretøystatus."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "Se kjøretøytreff",
|
||||
"description": "Kan se kundetreff for kjøretøy og forslag til ukjente kjøretøy."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "Se kjøretøyhistorikk",
|
||||
"description": "Kan se nylig ordrehistorikk for et registreringsnummer."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "Se ordrevedlegg",
|
||||
"description": "Kan liste vedlegg på ordrer."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Legg til ordrevedlegg",
|
||||
"description": "Kan laste opp filer og legge ved vaskesertifikater på ordrer."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Last ned ordrevedlegg",
|
||||
"description": "Kan åpne og laste ned ordrevedlegg."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "Se nummerskiltskanninger",
|
||||
"description": "Kan se nylige nummerskiltskanninger og skannere for tildelte avdelinger."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "Se avdelingsbookinger",
|
||||
"description": "Kan se bookinger for tildelte avdelinger."
|
||||
|
||||
@@ -1434,6 +1434,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'templates.generated.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -1485,6 +1490,66 @@
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'templates.generated.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -5147,6 +5212,22 @@
|
||||
"title": "Behorigheter for roll {id}",
|
||||
"title_with_name": "Behorigheter for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Anvand mallen {template}",
|
||||
"confirm_button": "Anvand mall",
|
||||
"confirm_text": "Lagg till {count} saknade behorigheter fran {template} till {role}?",
|
||||
"confirm_title": "Anvanda behorighetsmall?",
|
||||
"error_text": "En eller flera behorigheter fran {template} kunde inte laggas till i {role}. Rolllistan laddades om.",
|
||||
"error_title": "Kunde inte anvanda mall",
|
||||
"load_error": "Kunde inte ladda mallar. Forsok igen",
|
||||
"loading": "Laddar mallar...",
|
||||
"section": "Begransade backoffice-mallar",
|
||||
"success_text": "Lade till {count} behorigheter fran {template} i {role}.",
|
||||
"success_title": "Mall anvand",
|
||||
"unavailable": "Inga mallar ar tillgangliga.",
|
||||
"up_to_date_text": "{role} har redan alla behorigheter i {template}.",
|
||||
"up_to_date_title": "Rollen ar uppdaterad"
|
||||
},
|
||||
"subtitle": "@.capitalize:{'words.generated.user'} @:{'words.generated.roles'}"
|
||||
},
|
||||
"self_wash": {
|
||||
@@ -5556,6 +5637,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@.capitalize:{'words.generated.skapa'} @:{'words.generated.ny'} @:{'words.generated.anstalld'}",
|
||||
"migrate_to_limited_backoffice": "Migrera till begränsad backoffice",
|
||||
"subtitle": "@.capitalize:{'words.generated.har_2'} @:{'words.generated.kan'} @:{'words.generated.du'} @:{'words.generated.se'} @:{'words.replication.host_definite_suffix'} @:{'words.generated.lista'} @:{'words.generated.over'} @:{'words.generated.alla'} @:{'words.generated.anstallda'} @:{'words.generated.i'} @:{'words.generated.systemet'}"
|
||||
},
|
||||
"orders": {
|
||||
@@ -6299,12 +6381,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Visare",
|
||||
"description": "@.capitalize:{'words.generated.kan'} logga in @:{'words.generated.och'} se data @:{'words.generated.for'} @:{'words.generated.tilldelade'} @:{'words.generated.avdelningar'}."
|
||||
"label": "Inaktiverad",
|
||||
"description": "Behåller medarbetaren registrerad utan åtkomst till order-, boknings- eller administrationsfunktioner."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Kassör",
|
||||
"description": "@.capitalize:{'words.generated.kan'} arbeta med @:{'words.generated.order'} @:{'words.generated.och'} orderrader @:{'words.generated.for'} @:{'words.generated.tilldelade'} @:{'words.generated.avdelningar'}."
|
||||
"description": "@.capitalize:{'words.generated.kan'} arbeta med @:{'words.generated.order'}, orderrader @:{'words.generated.och'} @:{'words.generated.bokningar'} @:{'words.generated.for'} @:{'words.generated.tilldelade'} @:{'words.generated.avdelningar'}."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Bokningskoordinator",
|
||||
@@ -6339,6 +6421,11 @@
|
||||
"groups": {
|
||||
"account": "Konto",
|
||||
"orders": "Order",
|
||||
"products": "Produkter",
|
||||
"customers": "Kunder",
|
||||
"vehicles": "Fordon",
|
||||
"attachments": "Bilagor",
|
||||
"scanner": "Skannrar",
|
||||
"bookings": "Bokningar",
|
||||
"time_bookings": "Tidsbokningar",
|
||||
"reports": "Rapporter",
|
||||
@@ -6390,6 +6477,66 @@
|
||||
"label": "Debitera order",
|
||||
"description": "Kan ta betalt eller debitera en betalningsreservation för en order."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Slutför ordrar",
|
||||
"description": "Kan markera ordrar som slutförda."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "Visa produktkatalog",
|
||||
"description": "Kan läsa in POS-kategorier, produkter, priser och tillval."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "Visa produktförslag",
|
||||
"description": "Kan se produktförslag baserade på ordrar och fordonsdata."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Sök kunder",
|
||||
"description": "Kan söka och välja kunder för POS-ordrar."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "Visa kunduppgifter",
|
||||
"description": "Kan läsa in kunduppgifter från ett kundnummer."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "Visa kundanteckningar",
|
||||
"description": "Kan läsa kundanteckningar i POS."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Lägg till kundanteckningar",
|
||||
"description": "Kan lägga till kundanteckningar från POS."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "Visa kundmarkeringar",
|
||||
"description": "Kan se kundmarkeringar som påverkar orderkrav och produktregler."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Sök fordon",
|
||||
"description": "Kan söka registreringsnummer och se fordonsstatus."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "Visa fordonsträffar",
|
||||
"description": "Kan se kundträffar för fordon och förslag på okända fordon."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "Visa fordonshistorik",
|
||||
"description": "Kan se senaste orderhistorik för ett registreringsnummer."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "Visa orderbilagor",
|
||||
"description": "Kan lista bilagor på ordrar."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Lägg till orderbilagor",
|
||||
"description": "Kan ladda upp filer och bifoga tvättcertifikat till ordrar."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Ladda ner orderbilagor",
|
||||
"description": "Kan öppna och ladda ner orderbilagor."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "Visa nummerskyltsavläsningar",
|
||||
"description": "Kan se senaste nummerskyltsavläsningar och skannrar för tilldelade avdelningar."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "Se avdelningsbokningar",
|
||||
"description": "Kan se bokningar för tilldelade avdelningar."
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Rolletilladelser",
|
||||
"title": "Tilladelser for rolle {id}",
|
||||
"title_with_name": "Tilladelser for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Anvend {template}-skabelon",
|
||||
"confirm_button": "Anvend skabelon",
|
||||
"confirm_text": "Tilfoej {count} manglende tilladelser fra {template} til {role}?",
|
||||
"confirm_title": "Anvend tilladelsesskabelon?",
|
||||
"error_text": "En eller flere tilladelser fra {template} kunne ikke tilfoejes til {role}. Rollelisten blev genindlaest.",
|
||||
"error_title": "Kunne ikke anvende skabelon",
|
||||
"load_error": "Kunne ikke indlaese skabeloner. Proev igen",
|
||||
"loading": "Indlaeser skabeloner...",
|
||||
"section": "Begraenset backoffice-skabeloner",
|
||||
"success_text": "Tilfoejede {count} tilladelser fra {template} til {role}.",
|
||||
"success_title": "Skabelon anvendt",
|
||||
"unavailable": "Ingen skabeloner er tilgaengelige.",
|
||||
"up_to_date_text": "{role} har allerede alle tilladelser i {template}.",
|
||||
"up_to_date_title": "Rollen er opdateret"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@:{'terms.glossary.opret'} @:{'terms.glossary.ny'} @:{'terms.glossary.medarbejder'}",
|
||||
"migrate_to_limited_backoffice": "Migrer til begrænset backoffice",
|
||||
"subtitle": "@.capitalize:{'terms.glossary.her'} @:{'terms.glossary.kan'} @:{'terms.glossary.du'} @:{'terms.glossary.se'} @:{'terms.replication.host_definite_suffix'} @:{'terms.glossary.liste'} @:{'terms.glossary.over'} @:{'terms.glossary.alle'} @:{'terms.glossary.medarbejdere'} @:{'terms.glossary.i'} @:{'terms.glossary.systemet'}"
|
||||
},
|
||||
"orders": {
|
||||
|
||||
@@ -28,16 +28,16 @@
|
||||
"title": "@:{'phrases.compat.limited_backoffice.forbidden.title'}",
|
||||
"department": "@:{'phrases.compat.limited_backoffice.forbidden.department'}"
|
||||
},
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"setup_required_title": "@:{'phrases.compat.limited_backoffice.prices.setup_required_title'}",
|
||||
"setup_required_message": "@:{'phrases.compat.limited_backoffice.prices.setup_required_message'}",
|
||||
"no_products": "@:{'phrases.compat.limited_backoffice.prices.no_products'}"
|
||||
@@ -126,6 +126,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -177,6 +182,66 @@
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -338,12 +403,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Viser",
|
||||
"description": "@.capitalize:{'terms.glossary.kan'} logge ind @:{'terms.glossary.og'} se data @:{'terms.glossary.for'} @:{'terms.glossary.tildelte'} @:{'terms.glossary.afdelinger'}."
|
||||
"label": "Deaktiveret",
|
||||
"description": "Holder medarbejderen registreret uden adgang til ordre-, booking- eller administrationsfunktioner."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Kassemedarbejder",
|
||||
"description": "@.capitalize:{'terms.glossary.kan'} arbejde med @:{'terms.glossary.ordrer'} @:{'terms.glossary.og'} ordrelinjer @:{'terms.glossary.for'} @:{'terms.glossary.tildelte'} @:{'terms.glossary.afdelinger'}."
|
||||
"description": "@.capitalize:{'terms.glossary.kan'} arbejde med @:{'terms.glossary.ordrer'}, ordrelinjer @:{'terms.glossary.og'} @:{'terms.glossary.bookinger'} @:{'terms.glossary.for'} @:{'terms.glossary.tildelte'} @:{'terms.glossary.afdelinger'}."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Bookingkoordinator",
|
||||
@@ -378,6 +443,11 @@
|
||||
"groups": {
|
||||
"account": "Konto",
|
||||
"orders": "Ordrer",
|
||||
"products": "Produkter",
|
||||
"customers": "Kunder",
|
||||
"vehicles": "Køretøjer",
|
||||
"attachments": "Vedhæftninger",
|
||||
"scanner": "Scannere",
|
||||
"bookings": "Bookinger",
|
||||
"time_bookings": "Tidsbookinger",
|
||||
"reports": "Rapporter",
|
||||
@@ -429,6 +499,66 @@
|
||||
"label": "Opkræv ordrer",
|
||||
"description": "Kan tage betaling eller opkræve en betalingsreservation for en ordre."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Afslut ordrer",
|
||||
"description": "Kan markere ordrer som afsluttede."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "Se produktkatalog",
|
||||
"description": "Kan indlæse POS-kategorier, produkter, priser og tilvalg."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "Se produktforslag",
|
||||
"description": "Kan se produktforslag baseret på ordrer og køretøjsdata."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Søg kunder",
|
||||
"description": "Kan søge og vælge kunder til POS-ordrer."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "Se kundeoplysninger",
|
||||
"description": "Kan indlæse kundeoplysninger fra et kundenummer."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "Se kundebemærkninger",
|
||||
"description": "Kan læse kundebemærkninger i POS."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Tilføj kundebemærkninger",
|
||||
"description": "Kan tilføje kundebemærkninger fra POS."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "Se kundemarkeringer",
|
||||
"description": "Kan se kundemarkeringer, der påvirker ordrekrav og produktregler."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Søg køretøjer",
|
||||
"description": "Kan søge nummerplader og se køretøjsstatus."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "Se køretøjsmatch",
|
||||
"description": "Kan se kundematch for køretøjer og forslag til ukendte køretøjer."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "Se køretøjshistorik",
|
||||
"description": "Kan se seneste ordrehistorik for en nummerplade."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "Se ordrevedhæftninger",
|
||||
"description": "Kan liste vedhæftninger på ordrer."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Tilføj ordrevedhæftninger",
|
||||
"description": "Kan uploade filer og vedhæfte vaskecertifikater til ordrer."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Download ordrevedhæftninger",
|
||||
"description": "Kan åbne og downloade ordrevedhæftninger."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "Se nummerpladescanninger",
|
||||
"description": "Kan se seneste nummerpladescanninger og scannere for tildelte afdelinger."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "Se afdelingsbookinger",
|
||||
"description": "Kan se bookinger for tildelte afdelinger."
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Rollenberechtigungen",
|
||||
"title": "Berechtigungen fuer Rolle {id}",
|
||||
"title_with_name": "Berechtigungen fuer {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "{template}-Vorlage anwenden",
|
||||
"confirm_button": "Vorlage anwenden",
|
||||
"confirm_text": "{count} fehlende Berechtigungen aus {template} zu {role} hinzufuegen?",
|
||||
"confirm_title": "Berechtigungsvorlage anwenden?",
|
||||
"error_text": "Eine oder mehrere Berechtigungen aus {template} konnten {role} nicht hinzugefuegt werden. Die Rollenliste wurde neu geladen.",
|
||||
"error_title": "Vorlage konnte nicht angewendet werden",
|
||||
"load_error": "Vorlagen konnten nicht geladen werden. Erneut versuchen",
|
||||
"loading": "Vorlagen werden geladen...",
|
||||
"section": "Limited-Backoffice-Vorlagen",
|
||||
"success_text": "{count} Berechtigungen aus {template} zu {role} hinzugefuegt.",
|
||||
"success_title": "Vorlage angewendet",
|
||||
"unavailable": "Keine Vorlagen verfuegbar.",
|
||||
"up_to_date_text": "{role} hat bereits alle Berechtigungen in {template}.",
|
||||
"up_to_date_title": "Rolle ist aktuell"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@.capitalize:{'terms.glossary.neuen'} @:{'terms.glossary.mitarbeiter'} @:{'terms.glossary.erstellen'}",
|
||||
"migrate_to_limited_backoffice": "Zu eingeschränktem Backoffice migrieren",
|
||||
"subtitle": "@.capitalize:{'terms.glossary.hier'} @:{'terms.glossary.sehen'} @.capitalize:{'terms.glossary.sie'} @:{'terms.glossary.eine'} @:{'terms.glossary.liste'} @:{'terms.glossary.aller'} @:{'terms.glossary.mitarbeiter'} @:{'terms.glossary.im'} @.capitalize:{'terms.glossary.system'}"
|
||||
},
|
||||
"orders": {
|
||||
|
||||
@@ -28,16 +28,16 @@
|
||||
"title": "@:{'phrases.compat.limited_backoffice.forbidden.title'}",
|
||||
"department": "@:{'phrases.compat.limited_backoffice.forbidden.department'}"
|
||||
},
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"setup_required_title": "@:{'phrases.compat.limited_backoffice.prices.setup_required_title'}",
|
||||
"setup_required_message": "@:{'phrases.compat.limited_backoffice.prices.setup_required_message'}",
|
||||
"no_products": "@:{'phrases.compat.limited_backoffice.prices.no_products'}"
|
||||
@@ -126,6 +126,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -177,6 +182,66 @@
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -338,12 +403,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Betrachter",
|
||||
"description": "@.capitalize:{'terms.glossary.kann'} sich anmelden @:{'terms.glossary.und'} Daten zugewiesener @:{'terms.glossary.abteilungen'} @:{'terms.glossary.anzeigen'}."
|
||||
"label": "Deaktiviert",
|
||||
"description": "Hält den Mitarbeiter registriert, ohne Zugriff auf Auftrags-, Buchungs- oder Verwaltungsfunktionen."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Kassierer",
|
||||
"description": "@.capitalize:{'terms.glossary.kann'} mit Aufträgen @:{'terms.glossary.und'} Auftragszeilen @:{'terms.glossary.fur'} @:{'terms.glossary.zugewiesene'} @:{'terms.glossary.abteilungen'} arbeiten."
|
||||
"description": "@.capitalize:{'terms.glossary.kann'} mit Aufträgen, Auftragszeilen @:{'terms.glossary.und'} @:{'terms.glossary.buchungen'} @:{'terms.glossary.fur'} @:{'terms.glossary.zugewiesene'} @:{'terms.glossary.abteilungen'} arbeiten."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Buchungskoordinator",
|
||||
@@ -378,6 +443,11 @@
|
||||
"groups": {
|
||||
"account": "Konto",
|
||||
"orders": "Aufträge",
|
||||
"products": "Produkte",
|
||||
"customers": "Kunden",
|
||||
"vehicles": "Fahrzeuge",
|
||||
"attachments": "Anhänge",
|
||||
"scanner": "Scanner",
|
||||
"bookings": "Buchungen",
|
||||
"time_bookings": "Zeitbuchungen",
|
||||
"reports": "Berichte",
|
||||
@@ -429,6 +499,66 @@
|
||||
"label": "Aufträge abrechnen",
|
||||
"description": "Kann Zahlungen annehmen oder eine Zahlungsreservierung für einen Auftrag belasten."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Aufträge abschließen",
|
||||
"description": "Kann Aufträge als abgeschlossen markieren."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "Produktkatalog anzeigen",
|
||||
"description": "Kann POS-Kategorien, Produkte, Preise und Zusatzoptionen laden."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "Produktempfehlungen anzeigen",
|
||||
"description": "Kann Produktempfehlungen auf Basis von Aufträgen und Fahrzeugdaten sehen."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Kunden suchen",
|
||||
"description": "Kann Kunden für POS-Aufträge suchen und auswählen."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "Kundendetails anzeigen",
|
||||
"description": "Kann Kundendetails anhand einer Kundennummer laden."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "Kundennotizen anzeigen",
|
||||
"description": "Kann Kundennotizen im POS lesen."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Kundennotizen hinzufügen",
|
||||
"description": "Kann Kundennotizen im POS hinzufügen."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "Kundenmarkierungen anzeigen",
|
||||
"description": "Kann Kundenmarkierungen sehen, die Auftragsanforderungen und Produktregeln beeinflussen."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Fahrzeuge suchen",
|
||||
"description": "Kann Kennzeichen suchen und den Fahrzeugstatus sehen."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "Fahrzeugtreffer anzeigen",
|
||||
"description": "Kann Kundentreffer für Fahrzeuge und Vorschläge zu unbekannten Fahrzeugen sehen."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "Fahrzeughistorie anzeigen",
|
||||
"description": "Kann die letzte Auftragshistorie für ein Kennzeichen sehen."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "Auftragsanhänge anzeigen",
|
||||
"description": "Kann Anhänge auf Aufträgen auflisten."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Auftragsanhänge hinzufügen",
|
||||
"description": "Kann Dateien hochladen und Waschzertifikate an Aufträge anhängen."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Auftragsanhänge herunterladen",
|
||||
"description": "Kann Auftragsanhänge öffnen und herunterladen."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "Kennzeichenscans anzeigen",
|
||||
"description": "Kann aktuelle Kennzeichenscans und Scanner für zugewiesene Abteilungen sehen."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "Abteilungsbuchungen anzeigen",
|
||||
"description": "Kann Buchungen für zugewiesene Abteilungen sehen."
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Role permissions",
|
||||
"title": "Role {id} permissions",
|
||||
"title_with_name": "{name} permissions"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Apply {template} template",
|
||||
"confirm_button": "Apply template",
|
||||
"confirm_text": "Add {count} missing permissions from {template} to {role}?",
|
||||
"confirm_title": "Apply permission template?",
|
||||
"error_text": "One or more permissions from {template} could not be added to {role}. The role list was reloaded.",
|
||||
"error_title": "Could not apply template",
|
||||
"load_error": "Could not load templates. Try again",
|
||||
"loading": "Loading templates...",
|
||||
"section": "Limited backoffice templates",
|
||||
"success_text": "Added {count} permissions from {template} to {role}.",
|
||||
"success_title": "Template applied",
|
||||
"unavailable": "No templates are available.",
|
||||
"up_to_date_text": "{role} already has every permission in {template}.",
|
||||
"up_to_date_title": "Role is up to date"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@.capitalize:{'terms.glossary.create'} @:{'terms.glossary.new'} @:{'terms.glossary.employee'}",
|
||||
"migrate_to_limited_backoffice": "Migrate to limited backoffice",
|
||||
"subtitle": "@.capitalize:{'terms.glossary.here'} @:{'terms.glossary.you'} @:{'terms.glossary.can'} @:{'terms.glossary.see'} @:{'terms.glossary.a'} @:{'terms.glossary.list'} @:{'terms.glossary.of'} @:{'terms.glossary.all'} @:{'terms.glossary.employees'} @:{'terms.glossary.in'} @:{'terms.replication.article.host_mention'} @:{'terms.glossary.system'}"
|
||||
},
|
||||
"orders": {
|
||||
|
||||
@@ -28,16 +28,16 @@
|
||||
"title": "@:{'phrases.compat.limited_backoffice.forbidden.title'}",
|
||||
"department": "@:{'phrases.compat.limited_backoffice.forbidden.department'}"
|
||||
},
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"setup_required_title": "@:{'phrases.compat.limited_backoffice.prices.setup_required_title'}",
|
||||
"setup_required_message": "@:{'phrases.compat.limited_backoffice.prices.setup_required_message'}",
|
||||
"no_products": "@:{'phrases.compat.limited_backoffice.prices.no_products'}"
|
||||
@@ -126,6 +126,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -177,6 +182,66 @@
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -338,12 +403,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Viewer",
|
||||
"description": "@.capitalize:{'terms.glossary.can'} sign @:{'terms.glossary.in'} @:{'terms.glossary.and'} view @:{'terms.glossary.assigned'} @:{'terms.glossary.department'} data."
|
||||
"label": "Deactivated",
|
||||
"description": "Keeps the employee registered without order, booking, or management permissions."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Cashier",
|
||||
"description": "@.capitalize:{'terms.glossary.can'} work with @:{'terms.glossary.orders'} @:{'terms.glossary.and'} order lines @:{'terms.glossary.for'} @:{'terms.glossary.assigned'} @:{'terms.glossary.departments'}."
|
||||
"description": "@.capitalize:{'terms.glossary.can'} work with @:{'terms.glossary.orders'}, order lines @:{'terms.glossary.and'} @:{'terms.glossary.bookings'} @:{'terms.glossary.for'} @:{'terms.glossary.assigned'} @:{'terms.glossary.departments'}."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Booking coordinator",
|
||||
@@ -378,6 +443,11 @@
|
||||
"groups": {
|
||||
"account": "Account",
|
||||
"orders": "Orders",
|
||||
"products": "Products",
|
||||
"customers": "Customers",
|
||||
"vehicles": "Vehicles",
|
||||
"attachments": "Attachments",
|
||||
"scanner": "Scanners",
|
||||
"bookings": "Bookings",
|
||||
"time_bookings": "Time bookings",
|
||||
"reports": "Reports",
|
||||
@@ -429,6 +499,66 @@
|
||||
"label": "Charge orders",
|
||||
"description": "Can take payment or charge a payment intent for an order."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Complete orders",
|
||||
"description": "Can mark orders as completed."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "View product catalog",
|
||||
"description": "Can load POS categories, products, prices, and addons."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "View product recommendations",
|
||||
"description": "Can see product suggestions based on orders and vehicle data."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Search customers",
|
||||
"description": "Can search and select customers for POS orders."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "View customer details",
|
||||
"description": "Can load customer details from a customer number."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "View customer notes",
|
||||
"description": "Can read customer notes in POS."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Add customer notes",
|
||||
"description": "Can add customer notes from POS."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "View customer flags",
|
||||
"description": "Can see customer flags that affect order requirements and product rules."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Search vehicles",
|
||||
"description": "Can search license plates and see vehicle status."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "View vehicle matches",
|
||||
"description": "Can see vehicle customer matches and unknown vehicle suggestions."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "View vehicle history",
|
||||
"description": "Can see recent order history for a license plate."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "View order attachments",
|
||||
"description": "Can list attachments on orders."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Add order attachments",
|
||||
"description": "Can upload files and attach wash certificates to orders."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Download order attachments",
|
||||
"description": "Can open and download order attachments."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "View plate scans",
|
||||
"description": "Can view recent license plate scans and scanners for assigned departments."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "View department bookings",
|
||||
"description": "Can see bookings for assigned departments."
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"title": "@:{'phrases.compat.roles.permissions.title'}",
|
||||
"title_with_name": "@:{'phrases.compat.roles.permissions.title_with_name'}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "@:{'phrases.compat.roles.templates.apply'}",
|
||||
"confirm_button": "@:{'phrases.compat.roles.templates.confirm_button'}",
|
||||
"confirm_text": "@:{'phrases.compat.roles.templates.confirm_text'}",
|
||||
"confirm_title": "@:{'phrases.compat.roles.templates.confirm_title'}",
|
||||
"error_text": "@:{'phrases.compat.roles.templates.error_text'}",
|
||||
"error_title": "@:{'phrases.compat.roles.templates.error_title'}",
|
||||
"load_error": "@:{'phrases.compat.roles.templates.load_error'}",
|
||||
"loading": "@:{'phrases.compat.roles.templates.loading'}",
|
||||
"section": "@:{'phrases.compat.roles.templates.section'}",
|
||||
"success_text": "@:{'phrases.compat.roles.templates.success_text'}",
|
||||
"success_title": "@:{'phrases.compat.roles.templates.success_title'}",
|
||||
"unavailable": "@:{'phrases.compat.roles.templates.unavailable'}",
|
||||
"up_to_date_text": "@:{'phrases.compat.roles.templates.up_to_date_text'}",
|
||||
"up_to_date_title": "@:{'phrases.compat.roles.templates.up_to_date_title'}"
|
||||
},
|
||||
"subtitle": "@:{'phrases.compat.roles.subtitle'}",
|
||||
"title": "@:{'phrases.compat.common.roles'}"
|
||||
}
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Rolletillatelser",
|
||||
"title": "Tillatelser for rolle {id}",
|
||||
"title_with_name": "Tillatelser for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Bruk {template}-mal",
|
||||
"confirm_button": "Bruk mal",
|
||||
"confirm_text": "Legg til {count} manglende tillatelser fra {template} til {role}?",
|
||||
"confirm_title": "Bruke tillatelsesmal?",
|
||||
"error_text": "En eller flere tillatelser fra {template} kunne ikke legges til i {role}. Rollelisten ble lastet inn pa nytt.",
|
||||
"error_title": "Kunne ikke bruke mal",
|
||||
"load_error": "Kunne ikke laste maler. Prov igjen",
|
||||
"loading": "Laster maler...",
|
||||
"section": "Begrenset backoffice-maler",
|
||||
"success_text": "La til {count} tillatelser fra {template} i {role}.",
|
||||
"success_title": "Mal brukt",
|
||||
"unavailable": "Ingen maler er tilgjengelige.",
|
||||
"up_to_date_text": "{role} har allerede alle tillatelser i {template}.",
|
||||
"up_to_date_title": "Rollen er oppdatert"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@:{'terms.glossary.opprett'} @:{'terms.glossary.ny'} medarbeider",
|
||||
"migrate_to_limited_backoffice": "Migrer til begrenset backoffice",
|
||||
"subtitle": "@.capitalize:{'terms.glossary.her'} @:{'terms.glossary.kan'} @:{'terms.glossary.du'} @:{'terms.glossary.se'} @:{'terms.replication.host_definite_suffix'} @:{'terms.glossary.liste'} @:{'terms.glossary.over'} @:{'terms.glossary.alle'} @:{'terms.glossary.ansatte'} @:{'terms.glossary.i'} @:{'terms.glossary.systemet'}"
|
||||
},
|
||||
"orders": {
|
||||
|
||||
@@ -28,16 +28,16 @@
|
||||
"title": "@:{'phrases.compat.limited_backoffice.forbidden.title'}",
|
||||
"department": "@:{'phrases.compat.limited_backoffice.forbidden.department'}"
|
||||
},
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"setup_required_title": "@:{'phrases.compat.limited_backoffice.prices.setup_required_title'}",
|
||||
"setup_required_message": "@:{'phrases.compat.limited_backoffice.prices.setup_required_message'}",
|
||||
"no_products": "@:{'phrases.compat.limited_backoffice.prices.no_products'}"
|
||||
@@ -126,6 +126,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -177,6 +182,66 @@
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -338,12 +403,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Viser",
|
||||
"description": "@.capitalize:{'terms.glossary.kan'} logge inn @:{'terms.glossary.og'} se data @:{'terms.glossary.for'} @:{'terms.glossary.tildelte'} @:{'terms.glossary.avdelinger'}."
|
||||
"label": "Deaktivert",
|
||||
"description": "Holder den ansatte registrert uten tilgang til ordre-, booking- eller administrasjonsfunksjoner."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Kasserer",
|
||||
"description": "@.capitalize:{'terms.glossary.kan'} arbeide med @:{'terms.glossary.ordre'} @:{'terms.glossary.og'} ordrelinjer @:{'terms.glossary.for'} @:{'terms.glossary.tildelte'} @:{'terms.glossary.avdelinger'}."
|
||||
"description": "@.capitalize:{'terms.glossary.kan'} arbeide med @:{'terms.glossary.ordre'}, ordrelinjer @:{'terms.glossary.og'} @:{'terms.glossary.bookinger'} @:{'terms.glossary.for'} @:{'terms.glossary.tildelte'} @:{'terms.glossary.avdelinger'}."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Bookingkoordinator",
|
||||
@@ -378,6 +443,11 @@
|
||||
"groups": {
|
||||
"account": "Konto",
|
||||
"orders": "Ordrer",
|
||||
"products": "Produkter",
|
||||
"customers": "Kunder",
|
||||
"vehicles": "Kjøretøy",
|
||||
"attachments": "Vedlegg",
|
||||
"scanner": "Skannere",
|
||||
"bookings": "Bookinger",
|
||||
"time_bookings": "Tidsbookinger",
|
||||
"reports": "Rapporter",
|
||||
@@ -429,6 +499,66 @@
|
||||
"label": "Belast ordrer",
|
||||
"description": "Kan ta betaling eller belaste en betalingsreservasjon for en ordre."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Fullfør ordrer",
|
||||
"description": "Kan markere ordrer som fullført."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "Se produktkatalog",
|
||||
"description": "Kan laste POS-kategorier, produkter, priser og tillegg."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "Se produktforslag",
|
||||
"description": "Kan se produktforslag basert på ordrer og kjøretøydata."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Søk kunder",
|
||||
"description": "Kan søke og velge kunder for POS-ordrer."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "Se kundeopplysninger",
|
||||
"description": "Kan laste kundeopplysninger fra et kundenummer."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "Se kundemerknader",
|
||||
"description": "Kan lese kundemerknader i POS."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Legg til kundemerknader",
|
||||
"description": "Kan legge til kundemerknader fra POS."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "Se kundemarkeringer",
|
||||
"description": "Kan se kundemarkeringer som påvirker ordrekrav og produktregler."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Søk kjøretøy",
|
||||
"description": "Kan søke etter registreringsnummer og se kjøretøystatus."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "Se kjøretøytreff",
|
||||
"description": "Kan se kundetreff for kjøretøy og forslag til ukjente kjøretøy."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "Se kjøretøyhistorikk",
|
||||
"description": "Kan se nylig ordrehistorikk for et registreringsnummer."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "Se ordrevedlegg",
|
||||
"description": "Kan liste vedlegg på ordrer."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Legg til ordrevedlegg",
|
||||
"description": "Kan laste opp filer og legge ved vaskesertifikater på ordrer."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Last ned ordrevedlegg",
|
||||
"description": "Kan åpne og laste ned ordrevedlegg."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "Se nummerskiltskanninger",
|
||||
"description": "Kan se nylige nummerskiltskanninger og skannere for tildelte avdelinger."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "Se avdelingsbookinger",
|
||||
"description": "Kan se bookinger for tildelte avdelinger."
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Rollbehorigheter",
|
||||
"title": "Behorigheter for roll {id}",
|
||||
"title_with_name": "Behorigheter for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Anvand mallen {template}",
|
||||
"confirm_button": "Anvand mall",
|
||||
"confirm_text": "Lagg till {count} saknade behorigheter fran {template} till {role}?",
|
||||
"confirm_title": "Anvanda behorighetsmall?",
|
||||
"error_text": "En eller flera behorigheter fran {template} kunde inte laggas till i {role}. Rolllistan laddades om.",
|
||||
"error_title": "Kunde inte anvanda mall",
|
||||
"load_error": "Kunde inte ladda mallar. Forsok igen",
|
||||
"loading": "Laddar mallar...",
|
||||
"section": "Begransade backoffice-mallar",
|
||||
"success_text": "Lade till {count} behorigheter fran {template} i {role}.",
|
||||
"success_title": "Mall anvand",
|
||||
"unavailable": "Inga mallar ar tillgangliga.",
|
||||
"up_to_date_text": "{role} har redan alla behorigheter i {template}.",
|
||||
"up_to_date_title": "Rollen ar uppdaterad"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
},
|
||||
"employees": {
|
||||
"create": "@.capitalize:{'terms.glossary.skapa'} @:{'terms.glossary.ny'} @:{'terms.glossary.anstalld'}",
|
||||
"migrate_to_limited_backoffice": "Migrera till begränsad backoffice",
|
||||
"subtitle": "@.capitalize:{'terms.glossary.har_2'} @:{'terms.glossary.kan'} @:{'terms.glossary.du'} @:{'terms.glossary.se'} @:{'terms.replication.host_definite_suffix'} @:{'terms.glossary.lista'} @:{'terms.glossary.over'} @:{'terms.glossary.alla'} @:{'terms.glossary.anstallda'} @:{'terms.glossary.i'} @:{'terms.glossary.systemet'}"
|
||||
},
|
||||
"orders": {
|
||||
|
||||
@@ -28,16 +28,16 @@
|
||||
"title": "@:{'phrases.compat.limited_backoffice.forbidden.title'}",
|
||||
"department": "@:{'phrases.compat.limited_backoffice.forbidden.department'}"
|
||||
},
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"prices": {
|
||||
"title": "@:{'phrases.compat.limited_backoffice.prices.title'}",
|
||||
"save": "@:{'phrases.compat.limited_backoffice.prices.save'}",
|
||||
"saved": "@:{'phrases.compat.limited_backoffice.prices.saved'}",
|
||||
"autosave_saving": "@:{'phrases.compat.limited_backoffice.prices.autosave_saving'}",
|
||||
"autosave_pending": "@:{'phrases.compat.limited_backoffice.prices.autosave_pending'}",
|
||||
"autosave_saved": "@:{'phrases.compat.limited_backoffice.prices.autosave_saved'}",
|
||||
"product": "@:{'phrases.compat.limited_backoffice.prices.product'}",
|
||||
"price": "@:{'phrases.compat.limited_backoffice.prices.price'}",
|
||||
"price_required": "@:{'phrases.compat.limited_backoffice.prices.price_required'}",
|
||||
"setup_required_title": "@:{'phrases.compat.limited_backoffice.prices.setup_required_title'}",
|
||||
"setup_required_message": "@:{'phrases.compat.limited_backoffice.prices.setup_required_message'}",
|
||||
"no_products": "@:{'phrases.compat.limited_backoffice.prices.no_products'}"
|
||||
@@ -126,6 +126,11 @@
|
||||
"groups": {
|
||||
"account": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.account'}",
|
||||
"orders": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.orders'}",
|
||||
"products": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.products'}",
|
||||
"customers": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.customers'}",
|
||||
"vehicles": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.vehicles'}",
|
||||
"attachments": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.attachments'}",
|
||||
"scanner": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.scanner'}",
|
||||
"bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.bookings'}",
|
||||
"time_bookings": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.time_bookings'}",
|
||||
"reports": "@:{'phrases.compat.limited_backoffice.role_permissions.groups.reports'}",
|
||||
@@ -177,6 +182,66 @@
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.charge_orders.description'}"
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.complete_orders.description'}"
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_catalog.description'}"
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description'}"
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_customers.description'}"
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_details.description'}"
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_notes.description'}"
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_customer_notes.description'}"
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_customer_flags.description'}"
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.search_vehicles.description'}"
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description'}"
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description'}"
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_order_attachments.description'}"
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.add_order_attachments.description'}"
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.download_order_attachments.description'}"
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_plate_scans.description'}"
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.label'}",
|
||||
"description": "@:{'phrases.compat.limited_backoffice.role_permissions.capabilities.view_department_bookings.description'}"
|
||||
@@ -338,12 +403,12 @@
|
||||
},
|
||||
"roles": {
|
||||
"viewer": {
|
||||
"label": "Visare",
|
||||
"description": "@.capitalize:{'terms.glossary.kan'} logga in @:{'terms.glossary.och'} se data @:{'terms.glossary.for'} @:{'terms.glossary.tilldelade'} @:{'terms.glossary.avdelningar'}."
|
||||
"label": "Inaktiverad",
|
||||
"description": "Behåller medarbetaren registrerad utan åtkomst till order-, boknings- eller administrationsfunktioner."
|
||||
},
|
||||
"cashier": {
|
||||
"label": "Kassör",
|
||||
"description": "@.capitalize:{'terms.glossary.kan'} arbeta med @:{'terms.glossary.order'} @:{'terms.glossary.och'} orderrader @:{'terms.glossary.for'} @:{'terms.glossary.tilldelade'} @:{'terms.glossary.avdelningar'}."
|
||||
"description": "@.capitalize:{'terms.glossary.kan'} arbeta med @:{'terms.glossary.order'}, orderrader @:{'terms.glossary.och'} @:{'terms.glossary.bokningar'} @:{'terms.glossary.for'} @:{'terms.glossary.tilldelade'} @:{'terms.glossary.avdelningar'}."
|
||||
},
|
||||
"booking_coordinator": {
|
||||
"label": "Bokningskoordinator",
|
||||
@@ -378,6 +443,11 @@
|
||||
"groups": {
|
||||
"account": "Konto",
|
||||
"orders": "Order",
|
||||
"products": "Produkter",
|
||||
"customers": "Kunder",
|
||||
"vehicles": "Fordon",
|
||||
"attachments": "Bilagor",
|
||||
"scanner": "Skannrar",
|
||||
"bookings": "Bokningar",
|
||||
"time_bookings": "Tidsbokningar",
|
||||
"reports": "Rapporter",
|
||||
@@ -429,6 +499,66 @@
|
||||
"label": "Debitera order",
|
||||
"description": "Kan ta betalt eller debitera en betalningsreservation för en order."
|
||||
},
|
||||
"complete_orders": {
|
||||
"label": "Slutför ordrar",
|
||||
"description": "Kan markera ordrar som slutförda."
|
||||
},
|
||||
"view_product_catalog": {
|
||||
"label": "Visa produktkatalog",
|
||||
"description": "Kan läsa in POS-kategorier, produkter, priser och tillval."
|
||||
},
|
||||
"view_product_recommendations": {
|
||||
"label": "Visa produktförslag",
|
||||
"description": "Kan se produktförslag baserade på ordrar och fordonsdata."
|
||||
},
|
||||
"search_customers": {
|
||||
"label": "Sök kunder",
|
||||
"description": "Kan söka och välja kunder för POS-ordrar."
|
||||
},
|
||||
"view_customer_details": {
|
||||
"label": "Visa kunduppgifter",
|
||||
"description": "Kan läsa in kunduppgifter från ett kundnummer."
|
||||
},
|
||||
"view_customer_notes": {
|
||||
"label": "Visa kundanteckningar",
|
||||
"description": "Kan läsa kundanteckningar i POS."
|
||||
},
|
||||
"add_customer_notes": {
|
||||
"label": "Lägg till kundanteckningar",
|
||||
"description": "Kan lägga till kundanteckningar från POS."
|
||||
},
|
||||
"view_customer_flags": {
|
||||
"label": "Visa kundmarkeringar",
|
||||
"description": "Kan se kundmarkeringar som påverkar orderkrav och produktregler."
|
||||
},
|
||||
"search_vehicles": {
|
||||
"label": "Sök fordon",
|
||||
"description": "Kan söka registreringsnummer och se fordonsstatus."
|
||||
},
|
||||
"view_vehicle_matches": {
|
||||
"label": "Visa fordonsträffar",
|
||||
"description": "Kan se kundträffar för fordon och förslag på okända fordon."
|
||||
},
|
||||
"view_vehicle_history": {
|
||||
"label": "Visa fordonshistorik",
|
||||
"description": "Kan se senaste orderhistorik för ett registreringsnummer."
|
||||
},
|
||||
"view_order_attachments": {
|
||||
"label": "Visa orderbilagor",
|
||||
"description": "Kan lista bilagor på ordrar."
|
||||
},
|
||||
"add_order_attachments": {
|
||||
"label": "Lägg till orderbilagor",
|
||||
"description": "Kan ladda upp filer och bifoga tvättcertifikat till ordrar."
|
||||
},
|
||||
"download_order_attachments": {
|
||||
"label": "Ladda ner orderbilagor",
|
||||
"description": "Kan öppna och ladda ner orderbilagor."
|
||||
},
|
||||
"view_plate_scans": {
|
||||
"label": "Visa nummerskyltsavläsningar",
|
||||
"description": "Kan se senaste nummerskyltsavläsningar och skannrar för tilldelade avdelningar."
|
||||
},
|
||||
"view_department_bookings": {
|
||||
"label": "Se avdelningsbokningar",
|
||||
"description": "Kan se bokningar för tilldelade avdelningar."
|
||||
|
||||
@@ -18,8 +18,10 @@ export const getLimitedBackofficeRoles = () => limitedBackofficeRequest("/roles"
|
||||
export const getLimitedBackofficeEmployees = ({ includeInactive = false } = {}) =>
|
||||
limitedBackofficeRequest("/employees", "GET", { include_inactive: includeInactive ? "true" : "false" });
|
||||
|
||||
export const createLimitedBackofficeEmployee = (payload) =>
|
||||
limitedBackofficeRequest("/employees", "POST", payload);
|
||||
export const createLimitedBackofficeEmployee = (payload) => limitedBackofficeRequest("/employees", "POST", payload);
|
||||
|
||||
export const migrateLimitedBackofficeEmployee = (employeeId, payload) =>
|
||||
limitedBackofficeRequest(`/employees/${encodeURIComponent(String(employeeId))}/migrate`, "POST", payload);
|
||||
|
||||
export const updateLimitedBackofficeEmployee = (employeeId, payload) =>
|
||||
limitedBackofficeRequest(`/employees/${encodeURIComponent(String(employeeId))}`, "PUT", payload);
|
||||
@@ -33,7 +35,4 @@ export const deactivateLimitedBackofficeEmployee = (employeeId) =>
|
||||
export const unwrapLimitedBackofficeResponse = (response) => response?.data?.data ?? response?.data ?? null;
|
||||
|
||||
export const limitedBackofficeErrorMessage = (error, fallback) =>
|
||||
error?.response?.data?.data?.message ||
|
||||
error?.response?.data?.message ||
|
||||
error?.message ||
|
||||
fallback;
|
||||
error?.response?.data?.data?.message || error?.response?.data?.message || error?.message || fallback;
|
||||
|
||||
@@ -74,8 +74,8 @@ const selectedDepartmentId = computed(() => {
|
||||
return Number.isInteger(departmentId) && departmentId > 0 ? departmentId : null;
|
||||
});
|
||||
|
||||
const selectedDepartment = computed(() =>
|
||||
departments.value.find((department) => Number(department.id) === selectedDepartmentId.value) || null
|
||||
const selectedDepartment = computed(
|
||||
() => departments.value.find((department) => Number(department.id) === selectedDepartmentId.value) || null
|
||||
);
|
||||
|
||||
const hasForbiddenDepartment = computed(
|
||||
@@ -112,6 +112,21 @@ const rolePermissionGroupMessages = computed(() => ({
|
||||
orders: {
|
||||
label: t("templates.limited_backoffice.role_permissions.groups.orders"),
|
||||
},
|
||||
products: {
|
||||
label: t("templates.limited_backoffice.role_permissions.groups.products"),
|
||||
},
|
||||
customers: {
|
||||
label: t("templates.limited_backoffice.role_permissions.groups.customers"),
|
||||
},
|
||||
vehicles: {
|
||||
label: t("templates.limited_backoffice.role_permissions.groups.vehicles"),
|
||||
},
|
||||
attachments: {
|
||||
label: t("templates.limited_backoffice.role_permissions.groups.attachments"),
|
||||
},
|
||||
scanner: {
|
||||
label: t("templates.limited_backoffice.role_permissions.groups.scanner"),
|
||||
},
|
||||
bookings: {
|
||||
label: t("templates.limited_backoffice.role_permissions.groups.bookings"),
|
||||
},
|
||||
@@ -154,6 +169,10 @@ const roleCapabilityMessages = computed(() => ({
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.delete_orders.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.delete_orders.description"),
|
||||
},
|
||||
complete_orders: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.complete_orders.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.complete_orders.description"),
|
||||
},
|
||||
view_order_items: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_order_items.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_order_items.description"),
|
||||
@@ -174,6 +193,64 @@ const roleCapabilityMessages = computed(() => ({
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.charge_orders.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.charge_orders.description"),
|
||||
},
|
||||
view_product_catalog: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_product_catalog.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_product_catalog.description"),
|
||||
},
|
||||
view_product_recommendations: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_product_recommendations.label"),
|
||||
description: t(
|
||||
"templates.limited_backoffice.role_permissions.capabilities.view_product_recommendations.description"
|
||||
),
|
||||
},
|
||||
search_customers: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.search_customers.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.search_customers.description"),
|
||||
},
|
||||
view_customer_details: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_customer_details.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_customer_details.description"),
|
||||
},
|
||||
view_customer_notes: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_customer_notes.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_customer_notes.description"),
|
||||
},
|
||||
add_customer_notes: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.add_customer_notes.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.add_customer_notes.description"),
|
||||
},
|
||||
view_customer_flags: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_customer_flags.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_customer_flags.description"),
|
||||
},
|
||||
search_vehicles: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.search_vehicles.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.search_vehicles.description"),
|
||||
},
|
||||
view_vehicle_matches: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_vehicle_matches.description"),
|
||||
},
|
||||
view_vehicle_history: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_vehicle_history.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_vehicle_history.description"),
|
||||
},
|
||||
view_order_attachments: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_order_attachments.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_order_attachments.description"),
|
||||
},
|
||||
add_order_attachments: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.add_order_attachments.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.add_order_attachments.description"),
|
||||
},
|
||||
download_order_attachments: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.download_order_attachments.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.download_order_attachments.description"),
|
||||
},
|
||||
view_plate_scans: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_plate_scans.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_plate_scans.description"),
|
||||
},
|
||||
view_department_bookings: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.view_department_bookings.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.view_department_bookings.description"),
|
||||
@@ -204,7 +281,9 @@ const roleCapabilityMessages = computed(() => ({
|
||||
},
|
||||
create_time_booking_entries: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.create_time_booking_entries.label"),
|
||||
description: t("templates.limited_backoffice.role_permissions.capabilities.create_time_booking_entries.description"),
|
||||
description: t(
|
||||
"templates.limited_backoffice.role_permissions.capabilities.create_time_booking_entries.description"
|
||||
),
|
||||
},
|
||||
edit_time_booking_entries: {
|
||||
label: t("templates.limited_backoffice.role_permissions.capabilities.edit_time_booking_entries.label"),
|
||||
@@ -339,10 +418,7 @@ const loadData = async () => {
|
||||
|
||||
await loadEmployees();
|
||||
} catch (error) {
|
||||
errorMessage.value = limitedBackofficeErrorMessage(
|
||||
error,
|
||||
t("templates.limited_backoffice.errors.load_employees")
|
||||
);
|
||||
errorMessage.value = limitedBackofficeErrorMessage(error, t("templates.limited_backoffice.errors.load_employees"));
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
@@ -428,10 +504,7 @@ const saveEmployee = async () => {
|
||||
resetForm();
|
||||
await loadEmployees();
|
||||
} catch (error) {
|
||||
errorMessage.value = limitedBackofficeErrorMessage(
|
||||
error,
|
||||
t("templates.limited_backoffice.errors.save_employee")
|
||||
);
|
||||
errorMessage.value = limitedBackofficeErrorMessage(error, t("templates.limited_backoffice.errors.save_employee"));
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
@@ -540,10 +613,7 @@ const reloadEmployees = async () => {
|
||||
try {
|
||||
await loadEmployees();
|
||||
} catch (error) {
|
||||
errorMessage.value = limitedBackofficeErrorMessage(
|
||||
error,
|
||||
t("templates.limited_backoffice.errors.load_employees")
|
||||
);
|
||||
errorMessage.value = limitedBackofficeErrorMessage(error, t("templates.limited_backoffice.errors.load_employees"));
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
@@ -576,7 +646,11 @@ watch(
|
||||
show-department-switcher
|
||||
@change-department="changeDepartment"
|
||||
>
|
||||
<div v-if="hasForbiddenDepartment" class="notification is-danger is-light" data-testid="limited-employees-forbidden">
|
||||
<div
|
||||
v-if="hasForbiddenDepartment"
|
||||
class="notification is-danger is-light"
|
||||
data-testid="limited-employees-forbidden"
|
||||
>
|
||||
<strong>{{ t("templates.limited_backoffice.forbidden.title") }}</strong>
|
||||
<p>{{ t("templates.limited_backoffice.forbidden.department") }}</p>
|
||||
</div>
|
||||
@@ -746,7 +820,11 @@ watch(
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-if="formAttempted && !isFormValid" class="notification is-danger is-light" data-testid="limited-employee-validation">
|
||||
<div
|
||||
v-if="formAttempted && !isFormValid"
|
||||
class="notification is-danger is-light"
|
||||
data-testid="limited-employee-validation"
|
||||
>
|
||||
{{ t("templates.limited_backoffice.employees.validation") }}
|
||||
</div>
|
||||
|
||||
@@ -814,7 +892,10 @@ watch(
|
||||
</div>
|
||||
|
||||
<div v-if="!loading && visibleEmployees.length > 0" class="table-container">
|
||||
<table class="table is-fullwidth is-hoverable limited-employees-table" data-testid="limited-employees-table">
|
||||
<table
|
||||
class="table is-fullwidth is-hoverable limited-employees-table"
|
||||
data-testid="limited-employees-table"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ t("templates.limited_backoffice.employees.user_id") }}</th>
|
||||
@@ -822,11 +903,17 @@ watch(
|
||||
<th>{{ t("templates.limited_backoffice.employees.role") }}</th>
|
||||
<th>{{ t("templates.limited_backoffice.employees.departments") }}</th>
|
||||
<th>{{ t("templates.limited_backoffice.employees.status") }}</th>
|
||||
<th class="limited-employees-table__actions">{{ t("templates.limited_backoffice.employees.actions") }}</th>
|
||||
<th class="limited-employees-table__actions">
|
||||
{{ t("templates.limited_backoffice.employees.actions") }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="employee in visibleEmployees" :key="employee.id" :data-testid="`limited-employee-row-${employee.id}`">
|
||||
<tr
|
||||
v-for="employee in visibleEmployees"
|
||||
:key="employee.id"
|
||||
:data-testid="`limited-employee-row-${employee.id}`"
|
||||
>
|
||||
<td>
|
||||
<span class="tag is-light" :data-testid="`limited-employee-user-id-${employee.id}`">
|
||||
{{ employee.user_id || employee.id }}
|
||||
@@ -848,7 +935,11 @@ watch(
|
||||
<p class="has-text-grey is-size-7">{{ roleDescription(employee.role) }}</p>
|
||||
</td>
|
||||
<td>
|
||||
<span v-for="department in employee.departments" :key="department.id" class="tag is-light mr-1 mb-1">
|
||||
<span
|
||||
v-for="department in employee.departments"
|
||||
:key="department.id"
|
||||
class="tag is-light mr-1 mb-1"
|
||||
>
|
||||
{{ department.name }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
import SessionUser from "@/components/session/token/SessionUser.vue";
|
||||
import WhiteBoxCard from "@/components/displays/boxes/WhiteBoxCard.vue";
|
||||
import SubuserGrantSelector from "@/components/session/subuser/SubuserGrantSelector.vue";
|
||||
import {ref, onMounted, nextTick, computed, onUnmounted} from "vue";
|
||||
import {ref, onMounted, nextTick, computed, onUnmounted, watch} from "vue";
|
||||
import { IS_DEV } from '@/config.js';
|
||||
import {BLoading} from "buefy";
|
||||
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
|
||||
|
||||
/**
|
||||
* Subuser grant selection gate
|
||||
@@ -76,6 +77,59 @@ const canShowVehicleShortcut = computed(() => SessionUser.canAccessCustomerFeatu
|
||||
const canShowOrderShortcut = computed(() => SessionUser.canAccessCustomerFeature("orders", "list"));
|
||||
const canShowSelfServeShortcut = computed(() => SessionUser.canAccessCustomerFeature("selfserve", "list"));
|
||||
const canShowInvoiceShortcut = computed(() => canShowClassicCustomerShortcut());
|
||||
const hasInvoicesAvailable = ref(false);
|
||||
const isCheckingInvoiceAvailability = ref(true);
|
||||
const canDownloadInvoices = computed(() => canShowInvoiceShortcut.value && hasInvoicesAvailable.value && !isCheckingInvoiceAvailability.value);
|
||||
|
||||
const responseHasInvoices = (response: any) => {
|
||||
const total = Number(response?.data?.meta?.pagination?.total);
|
||||
if (Number.isFinite(total) && total > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Array.isArray(response?.data?.data) && response.data.data.length > 0;
|
||||
};
|
||||
|
||||
const resetInvoiceAvailability = () => {
|
||||
hasInvoicesAvailable.value = false;
|
||||
isCheckingInvoiceAvailability.value = false;
|
||||
};
|
||||
|
||||
const loadInvoiceAvailability = async () => {
|
||||
if (!canShowInvoiceShortcut.value) {
|
||||
resetInvoiceAvailability();
|
||||
return;
|
||||
}
|
||||
|
||||
isCheckingInvoiceAvailability.value = true;
|
||||
|
||||
try {
|
||||
const response = await authenticatedRequest("/user/invoices", "GET", {
|
||||
page: 1,
|
||||
limit: 1,
|
||||
order: "created_at:desc",
|
||||
});
|
||||
hasInvoicesAvailable.value = responseHasInvoices(response);
|
||||
} catch (_error) {
|
||||
hasInvoicesAvailable.value = false;
|
||||
} finally {
|
||||
isCheckingInvoiceAvailability.value = false;
|
||||
setEqualHeights();
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
canShowInvoiceShortcut,
|
||||
(canShow) => {
|
||||
if (canShow) {
|
||||
void loadInvoiceAvailability();
|
||||
return;
|
||||
}
|
||||
|
||||
resetInvoiceAvailability();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const windowInnerWidth = ref(window.innerWidth);
|
||||
const updateWindowInnerWidth = () => {
|
||||
@@ -291,9 +345,26 @@ const isPermissionsLoading = computed(() => {
|
||||
</template>
|
||||
<template #footer>
|
||||
<div class="card-footer-item">
|
||||
<router-link to="/user/invoices" class="button is-link is-fullwidth" :class="classes.button" id="download-invoices-button">
|
||||
<router-link
|
||||
v-if="canDownloadInvoices"
|
||||
to="/user/invoices"
|
||||
class="button is-link is-fullwidth"
|
||||
:class="classes.button"
|
||||
id="download-invoices-button"
|
||||
>
|
||||
{{ $t('user_home.download_invoices') }}
|
||||
</router-link>
|
||||
<button
|
||||
v-else
|
||||
class="button is-link is-fullwidth"
|
||||
:class="[classes.button, { 'is-loading': isCheckingInvoiceAvailability }]"
|
||||
id="download-invoices-button"
|
||||
type="button"
|
||||
disabled
|
||||
aria-disabled="true"
|
||||
>
|
||||
{{ $t('user_home.download_invoices') }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</WhiteBoxCard>
|
||||
|
||||
@@ -370,8 +370,12 @@ const isInvoiced = () => {
|
||||
return isInvoicedWithEconomic() || isInvoicedWithStripe();
|
||||
};
|
||||
|
||||
const isBookedWithEconomic = () => {
|
||||
return economicModule.value.invoice_id !== null;
|
||||
const hasEconomicInvoiceDownloadContext = () => {
|
||||
const module = economicModule.value || {};
|
||||
return (
|
||||
Object.prototype.hasOwnProperty.call(module, 'invoice_id') ||
|
||||
Object.prototype.hasOwnProperty.call(module, 'invoice_draft_id')
|
||||
);
|
||||
};
|
||||
|
||||
const isCompleted = () => {
|
||||
@@ -1376,7 +1380,11 @@ const isDisplayingReceipt = () => {
|
||||
|
||||
<template #rail-actions>
|
||||
<ButtonsBox class="pos-actions pos-actions--rail">
|
||||
<GetOrderInvoicePDFButton :invoice_id="economicModule.invoice_id" class="is-fullwidth" v-if="isBookedWithEconomic()" />
|
||||
<GetOrderInvoicePDFButton
|
||||
:invoice_id="economicModule.invoice_id"
|
||||
class="is-fullwidth"
|
||||
v-if="hasEconomicInvoiceDownloadContext()"
|
||||
/>
|
||||
<div
|
||||
v-if="isEconomicExportBlocked"
|
||||
class="message is-warning is-light"
|
||||
|
||||
@@ -1844,7 +1844,7 @@ test("shows live Stripe payment status and cancellation for open card payment or
|
||||
await expect(page.getByTestId("pos-order-stripe-email-cancel")).toBeVisible();
|
||||
await expect(page.getByTestId("pos-order-print-receipt")).toHaveCount(0);
|
||||
await expect(page.getByRole("button", { name: /Fuldfør ordre|Complete order/ })).toHaveCount(0);
|
||||
await expect(page.getByRole("button", { name: /Hent faktura|Get invoice/ })).toHaveCount(0);
|
||||
await expect(page.locator('[data-action-key="economic-invoice-pdf-download"]')).toBeDisabled();
|
||||
|
||||
await page.getByTestId("pos-order-stripe-email-cancel").click();
|
||||
await deleteStripeInvoiceRequest;
|
||||
@@ -2950,6 +2950,28 @@ test.describe("Admin POS Orders - desktop locked states", () => {
|
||||
await expectOrderTotal(page, 1372);
|
||||
});
|
||||
|
||||
test("disables invoice PDF download while the Economic invoice id is missing", async ({ page }) => {
|
||||
await mockApi(page, {
|
||||
authenticated: true,
|
||||
permissions: POS_PERMISSIONS,
|
||||
edgeGateways: false,
|
||||
pos: createPosFixture({
|
||||
economicModuleOrdersByOrderId: {
|
||||
54518: {
|
||||
invoice_id: null,
|
||||
invoice_draft_id: 88012,
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
await primeOperatorSession(page, "pos-orders-draft-invoice-token");
|
||||
await openOrderDetail(page);
|
||||
|
||||
const downloadButton = page.locator('[data-action-key="economic-invoice-pdf-download"]');
|
||||
await expect(downloadButton).toBeVisible();
|
||||
await expect(downloadButton).toBeDisabled();
|
||||
});
|
||||
|
||||
test("hides item mutation controls when the order is already invoiced", async ({ page }) => {
|
||||
await mockApi(page, {
|
||||
authenticated: true,
|
||||
@@ -2970,6 +2992,7 @@ test.describe("Admin POS Orders - desktop locked states", () => {
|
||||
await expect(page.getByTestId("pos-order-item-edit-9101")).toHaveCount(0);
|
||||
await expect(page.getByTestId("pos-order-item-delete-9101")).toHaveCount(0);
|
||||
await expect(page.getByTestId("pos-order-add-item")).toHaveCount(0);
|
||||
await expect(page.locator('[data-action-key="economic-invoice-pdf-download"]')).toBeEnabled();
|
||||
await expectOrderTotal(page, 1372);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -350,6 +350,10 @@ async function readStoredToken(page: Page) {
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForAppRootMounted(page: Page) {
|
||||
await expect.poll(async () => page.locator("#app > *").count(), { timeout: AUTH_TIMEOUT }).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
async function settleAuthenticatedNavigation(page: Page, targetPath: string, targetUrl: RegExp) {
|
||||
await expect.poll(() => readStoredToken(page), { timeout: AUTH_TIMEOUT }).not.toBeNull();
|
||||
const navigateToTarget = async () => {
|
||||
@@ -376,6 +380,8 @@ async function settleAuthenticatedNavigation(page: Page, targetPath: string, tar
|
||||
await navigateToTarget();
|
||||
await expect.poll(() => page.url(), { timeout: AUTH_TIMEOUT }).toMatch(targetUrl);
|
||||
}
|
||||
|
||||
await waitForAppRootMounted(page);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,10 @@ const GENERATED_LOCALES_DIRECTORY = path.join(process.cwd(), "src", "i18n", "gen
|
||||
const REVIEWED_NON_LITERAL_CALLS = new Set([
|
||||
"src/views/backoffice/LimitedBackofficeEmployees.vue|t|return `${option.flag} +${option.value} ${t(`templates.limited_backoffice.employees.country_codes.${option.labelKey}`)}`;",
|
||||
"src/views/dashboards/superUserDashboard/InvoicingBillingPeriod/components/InvoicingPeriodFlagList.vue|t|const translated = t(key, params);",
|
||||
"src/views/dashboards/superUserDashboard/roles/SuperUserRolesPermissions.vue|t|label: t(`roles.permissions.page_access.${permission}.label`),",
|
||||
"src/views/dashboards/superUserDashboard/roles/SuperUserRolesPermissions.vue|t|description: t(`roles.permissions.page_access.${permission}.description`),",
|
||||
"src/views/dashboards/superUserDashboard/roles/SuperUserRolesPermissions.vue|t|label: t(`roles.permissions.groups.${group.key}.label`),",
|
||||
"src/views/dashboards/superUserDashboard/roles/SuperUserRolesPermissions.vue|t|description: t(`roles.permissions.groups.${group.key}.description`),",
|
||||
'src/views/dashboards/superUserDashboard/system/ReplicationManagement.vue|t|return t(`replication.status.${status || "unknown"}`);',
|
||||
"src/views/dashboards/superUserDashboard/system/ReplicationManagement.vue|te|if (key && te(key)) {",
|
||||
"src/views/dashboards/superUserDashboard/system/ReplicationManagement.vue|t|return t(key, params);",
|
||||
|
||||
@@ -1112,6 +1112,7 @@ test.describe("Invoicing period tab", () => {
|
||||
const usageOrderRequests = [];
|
||||
const fastLinkRequests = [];
|
||||
const automationAcceptRequests = [];
|
||||
const importUsageRequests = [];
|
||||
let automation = {
|
||||
id: 7101,
|
||||
status: "suggested",
|
||||
@@ -1133,6 +1134,15 @@ test.describe("Invoicing period tab", () => {
|
||||
|
||||
await openPeriodView(page);
|
||||
|
||||
await page.route("**/modules/xlvask/tasks/import-usage**", async (route) => {
|
||||
const url = new URL(route.request().url());
|
||||
importUsageRequests.push({
|
||||
dateFrom: url.searchParams.get("dateFrom"),
|
||||
dateTo: url.searchParams.get("dateTo"),
|
||||
});
|
||||
await route.fulfill(json({ data: "Usage logs imported" }));
|
||||
});
|
||||
|
||||
await page.route("**/modules/xlvask/services/usage/orders**", async (route) => {
|
||||
const path = new URL(route.request().url()).pathname;
|
||||
if (
|
||||
@@ -1285,6 +1295,12 @@ test.describe("Invoicing period tab", () => {
|
||||
request.filters.includes("StartTime-date_to:2026-03-31")
|
||||
)
|
||||
).toBe(true);
|
||||
await selfWashView.getByRole("button", { name: /import/i }).click();
|
||||
await expect.poll(() => importUsageRequests.length).toBe(1);
|
||||
expect(importUsageRequests[0]).toEqual({
|
||||
dateFrom: "2026-03-01",
|
||||
dateTo: "2026-03-31",
|
||||
});
|
||||
});
|
||||
|
||||
test("@smoke period view shows flags and saves automatic flag decisions", async ({ page }) => {
|
||||
|
||||
@@ -148,6 +148,7 @@ const rolePermissionGroups = {
|
||||
"view_orders",
|
||||
"create_orders",
|
||||
"edit_orders",
|
||||
"complete_orders",
|
||||
"view_order_items",
|
||||
"create_order_items",
|
||||
"update_order_lines",
|
||||
@@ -155,6 +156,43 @@ const rolePermissionGroups = {
|
||||
"charge_orders",
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "products",
|
||||
capabilities: ["view_product_catalog", "view_product_recommendations"],
|
||||
},
|
||||
{
|
||||
key: "customers",
|
||||
capabilities: [
|
||||
"search_customers",
|
||||
"view_customer_details",
|
||||
"view_customer_notes",
|
||||
"add_customer_notes",
|
||||
"view_customer_flags",
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "vehicles",
|
||||
capabilities: ["search_vehicles", "view_vehicle_matches", "view_vehicle_history"],
|
||||
},
|
||||
{
|
||||
key: "attachments",
|
||||
capabilities: ["view_order_attachments", "add_order_attachments", "download_order_attachments"],
|
||||
},
|
||||
{
|
||||
key: "scanner",
|
||||
capabilities: ["view_plate_scans"],
|
||||
},
|
||||
{
|
||||
key: "bookings",
|
||||
capabilities: [
|
||||
"view_department_bookings",
|
||||
"view_own_bookings",
|
||||
"update_bookings",
|
||||
"create_bookings",
|
||||
"mark_bookings_complete",
|
||||
"send_booking_confirmations",
|
||||
],
|
||||
},
|
||||
],
|
||||
booking_coordinator: [
|
||||
{ key: "account", capabilities: ["sign_in", "view_own_permissions"] },
|
||||
@@ -184,6 +222,7 @@ const rolePermissionGroups = {
|
||||
"create_orders",
|
||||
"edit_orders",
|
||||
"delete_orders",
|
||||
"complete_orders",
|
||||
"view_order_items",
|
||||
"create_order_items",
|
||||
"update_order_lines",
|
||||
@@ -191,6 +230,32 @@ const rolePermissionGroups = {
|
||||
"charge_orders",
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "products",
|
||||
capabilities: ["view_product_catalog", "view_product_recommendations"],
|
||||
},
|
||||
{
|
||||
key: "customers",
|
||||
capabilities: [
|
||||
"search_customers",
|
||||
"view_customer_details",
|
||||
"view_customer_notes",
|
||||
"add_customer_notes",
|
||||
"view_customer_flags",
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "vehicles",
|
||||
capabilities: ["search_vehicles", "view_vehicle_matches", "view_vehicle_history"],
|
||||
},
|
||||
{
|
||||
key: "attachments",
|
||||
capabilities: ["view_order_attachments", "add_order_attachments", "download_order_attachments"],
|
||||
},
|
||||
{
|
||||
key: "scanner",
|
||||
capabilities: ["view_plate_scans"],
|
||||
},
|
||||
{
|
||||
key: "bookings",
|
||||
capabilities: [
|
||||
@@ -213,6 +278,7 @@ const rolePermissionGroups = {
|
||||
"create_orders",
|
||||
"edit_orders",
|
||||
"delete_orders",
|
||||
"complete_orders",
|
||||
"view_order_items",
|
||||
"create_order_items",
|
||||
"update_order_lines",
|
||||
@@ -220,6 +286,32 @@ const rolePermissionGroups = {
|
||||
"charge_orders",
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "products",
|
||||
capabilities: ["view_product_catalog", "view_product_recommendations"],
|
||||
},
|
||||
{
|
||||
key: "customers",
|
||||
capabilities: [
|
||||
"search_customers",
|
||||
"view_customer_details",
|
||||
"view_customer_notes",
|
||||
"add_customer_notes",
|
||||
"view_customer_flags",
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "vehicles",
|
||||
capabilities: ["search_vehicles", "view_vehicle_matches", "view_vehicle_history"],
|
||||
},
|
||||
{
|
||||
key: "attachments",
|
||||
capabilities: ["view_order_attachments", "add_order_attachments", "download_order_attachments"],
|
||||
},
|
||||
{
|
||||
key: "scanner",
|
||||
capabilities: ["view_plate_scans"],
|
||||
},
|
||||
{
|
||||
key: "bookings",
|
||||
capabilities: [
|
||||
@@ -245,7 +337,12 @@ const remotePricePayload = {
|
||||
};
|
||||
|
||||
const rolesPayload = [
|
||||
{ key: "viewer", label: "Viewer", description: "Can view.", permission_groups: rolePermissionGroups.viewer },
|
||||
{
|
||||
key: "viewer",
|
||||
label: "Deactivated",
|
||||
description: "No order, booking, or management access.",
|
||||
permission_groups: rolePermissionGroups.viewer,
|
||||
},
|
||||
{ key: "cashier", label: "Cashier", description: "Can sell.", permission_groups: rolePermissionGroups.cashier },
|
||||
{
|
||||
key: "booking_coordinator",
|
||||
@@ -272,7 +369,7 @@ const employeesPayload = [
|
||||
{
|
||||
id: 501,
|
||||
user_id: 501,
|
||||
customer_number: 900000501,
|
||||
customer_number: 0,
|
||||
display_name: "Casey Clerk",
|
||||
email: "casey@example.com",
|
||||
phone_country_code: 45,
|
||||
@@ -285,11 +382,11 @@ const employeesPayload = [
|
||||
},
|
||||
{
|
||||
id: 502,
|
||||
customer_number: 900000502,
|
||||
customer_number: 0,
|
||||
display_name: "Riley Remote",
|
||||
email: "riley@example.com",
|
||||
active: true,
|
||||
role: { key: "viewer", label: "Viewer", description: "Can view." },
|
||||
role: { key: "viewer", label: "Deactivated", description: "No order, booking, or management access." },
|
||||
departments: [{ id: 2, name: "Remote Depot" }],
|
||||
created_at: "2026-01-01 00:00:00",
|
||||
updated_at: "2026-01-01 00:00:00",
|
||||
@@ -842,17 +939,36 @@ test.describe("Limited backoffice", () => {
|
||||
await expect(modal).toBeVisible();
|
||||
await expect(modal).toContainText("Role permissions");
|
||||
await expect(modal).toContainText("Every capability is limited to the departments selected for the employee.");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-viewer")).toContainText("Deactivated");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Cashier");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Orders");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Products");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Customers");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Vehicles");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Attachments");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Scanners");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Bookings");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("View orders");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Complete orders");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("View product catalog");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Search customers");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Search vehicles");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Add order attachments");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("View plate scans");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Create bookings");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-cashier")).toContainText("Create order lines");
|
||||
await expect(page.getByTestId("limited-role-permissions-role-viewer")).toContainText("Selected");
|
||||
|
||||
for (const rawPermission of [
|
||||
"list_orders",
|
||||
"add_order",
|
||||
"fetch_order",
|
||||
"edit_order_items",
|
||||
"delete_order_items",
|
||||
"search_customers",
|
||||
"list_order_attachments",
|
||||
"list_products",
|
||||
"add_bookings",
|
||||
"department_timebookings_entries_get",
|
||||
"limited_backoffice_employees_manage",
|
||||
"department_access_1",
|
||||
|
||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 98 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 107 KiB |
@@ -2328,7 +2328,11 @@ test("superusers manage release settings, assignments, integrations, and sync op
|
||||
await expect(page.getByTestId("release-assignment-subject-manual-user-909")).toContainText("User #909");
|
||||
await expect(page.getByTestId("release-assignment-subject-manual-subuser-909")).toContainText("Subuser #909");
|
||||
await expect(page.getByTestId("release-assignment-subject-manual-customer-909")).toContainText("Customer #909");
|
||||
await page.getByTestId("release-assignment-subject-manual-subuser-909").click({ force: true });
|
||||
await page
|
||||
.getByTestId("release-assignment-subject-autocomplete")
|
||||
.getByRole("button", { name: /Subuser #909/ })
|
||||
.click();
|
||||
await expect(assignmentSubjectInput).toHaveValue("Subuser #909 - Use typed value subuser:909");
|
||||
await page.getByTestId("release-assignment-form").getByRole("button", { name: "Assign" }).click();
|
||||
expect(state.assignmentPayloads[state.assignmentPayloads.length - 1]).toMatchObject({
|
||||
subject_type: "subuser",
|
||||
|
||||
@@ -27,10 +27,7 @@ async function primeSession(page, { token, permissions, sessionData = {} }) {
|
||||
await seedAuthenticatedState(page, token);
|
||||
}
|
||||
|
||||
async function mockSelectedSubuserGrant(
|
||||
page,
|
||||
{ customerNumber = 12345679, permissions = ["user", "SELFSERVE_LIST", "SELFSERVE_ADD"] } = {}
|
||||
) {
|
||||
async function mockSelectedSubuserGrant(page, { customerNumber = 12345679, permissions = ["SELFSERVE_LIST"] } = {}) {
|
||||
await page.route("**/subusers/me", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
|
||||
@@ -43,11 +43,46 @@ const departments = [
|
||||
},
|
||||
];
|
||||
|
||||
const roleTemplatePermissions = [
|
||||
"user",
|
||||
"permissions_list_own",
|
||||
"list_departments",
|
||||
"list_orders",
|
||||
"fetch_order",
|
||||
"statistics_orders_new",
|
||||
];
|
||||
|
||||
const limitedBackofficePermissionTemplates = [
|
||||
{
|
||||
key: "viewer",
|
||||
label: "Deactivated",
|
||||
description: "Keeps the employee registered without order, booking, or management permissions.",
|
||||
permissions: ["user", "permissions_list_own"],
|
||||
},
|
||||
{
|
||||
key: "cashier",
|
||||
label: "Cashier",
|
||||
description: "Can work with POS orders for assigned departments.",
|
||||
permissions: roleTemplatePermissions,
|
||||
},
|
||||
];
|
||||
|
||||
type PermissionCall = {
|
||||
action: "add" | "remove";
|
||||
permission: string;
|
||||
};
|
||||
|
||||
const roleListEnvelope = (rows: Array<Record<string, unknown>>) => ({
|
||||
data: rows,
|
||||
meta: {
|
||||
pagination: {
|
||||
page: 1,
|
||||
per_page: 100,
|
||||
total: rows.length,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const openGroupTab = async (page: Page, label: RegExp) => {
|
||||
await page.locator(".tabs").getByText(label).click();
|
||||
};
|
||||
@@ -147,6 +182,107 @@ const bootRolePermissionsPage = async (page: Page, routeOptions = {}) => {
|
||||
};
|
||||
|
||||
test.describe("Superuser role permissions", () => {
|
||||
test("applies limited backoffice templates from the role action wheel in add-only mode", async ({ page }) => {
|
||||
const role = {
|
||||
id: 2,
|
||||
name: "Operations manager",
|
||||
description: "Can manage operations.",
|
||||
created_at: "2026-07-06T08:00:00.000Z",
|
||||
permissions: ["user", "list_orders"],
|
||||
};
|
||||
const calls: PermissionCall[] = [];
|
||||
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.setItem("locale", "en");
|
||||
});
|
||||
await seedAuthenticatedState(page, "superuser-roles-template-token");
|
||||
await mockApi(page, {
|
||||
authenticated: true,
|
||||
permissions: ["superuser", "user", "list_roles", "add_role_permission"],
|
||||
sessionData: {
|
||||
group_id: 1,
|
||||
},
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles/limited-backoffice-permission-templates"), async (route: Route) => {
|
||||
await route.fulfill(json({ data: limitedBackofficePermissionTemplates }));
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles"), async (route: Route) => {
|
||||
await route.fulfill(json(roleListEnvelope([role])));
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles/permissions"), async (route: Route) => {
|
||||
const body = route.request().postDataJSON();
|
||||
const permission = String(body.permission_id || "");
|
||||
calls.push({ action: "add", permission });
|
||||
if (!role.permissions.includes(permission)) {
|
||||
role.permissions = [...role.permissions, permission];
|
||||
}
|
||||
await route.fulfill(json({ data: role }));
|
||||
});
|
||||
|
||||
await page.goto("/superuser/roles", { waitUntil: "domcontentloaded" });
|
||||
await expect(page.getByRole("row", { name: /Operations manager/ })).toBeVisible();
|
||||
|
||||
const row = page.getByRole("row", { name: /Operations manager/ });
|
||||
await row.locator(".action-settings-wheel-trigger").click();
|
||||
await expect(page.getByTestId("role-limited-backoffice-template-actions-2")).toBeVisible();
|
||||
await page.getByTestId("role-template-2-cashier").click();
|
||||
|
||||
await expect(page.getByText("Apply permission template?")).toBeVisible();
|
||||
await page.getByRole("button", { name: "Apply template" }).click();
|
||||
|
||||
await expect
|
||||
.poll(() => calls.map((call) => call.permission))
|
||||
.toEqual(["permissions_list_own", "list_departments", "fetch_order", "statistics_orders_new"]);
|
||||
await expect(page.getByText("Template applied")).toBeVisible();
|
||||
});
|
||||
|
||||
test("disables limited backoffice template actions when a role is already up to date", async ({ page }) => {
|
||||
const role = {
|
||||
id: 3,
|
||||
name: "Cashier role",
|
||||
description: "Current cashier permissions.",
|
||||
created_at: "2026-07-06T08:00:00.000Z",
|
||||
permissions: [...roleTemplatePermissions],
|
||||
};
|
||||
const calls: PermissionCall[] = [];
|
||||
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.setItem("locale", "en");
|
||||
});
|
||||
await seedAuthenticatedState(page, "superuser-roles-template-up-to-date-token");
|
||||
await mockApi(page, {
|
||||
authenticated: true,
|
||||
permissions: ["superuser", "user", "list_roles", "add_role_permission"],
|
||||
sessionData: {
|
||||
group_id: 1,
|
||||
},
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles/limited-backoffice-permission-templates"), async (route: Route) => {
|
||||
await route.fulfill(json({ data: limitedBackofficePermissionTemplates }));
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles"), async (route: Route) => {
|
||||
await route.fulfill(json(roleListEnvelope([role])));
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles/permissions"), async (route: Route) => {
|
||||
calls.push({ action: "add", permission: String(route.request().postDataJSON().permission_id || "") });
|
||||
await route.fulfill(json({ data: role }));
|
||||
});
|
||||
|
||||
await page.goto("/superuser/roles", { waitUntil: "domcontentloaded" });
|
||||
const row = page.getByRole("row", { name: /Cashier role/ });
|
||||
await expect(row).toBeVisible();
|
||||
await row.locator(".action-settings-wheel-trigger").click();
|
||||
|
||||
await expect(page.getByTestId("role-template-3-cashier")).toBeDisabled();
|
||||
expect(calls).toEqual([]);
|
||||
});
|
||||
|
||||
test("@smoke @pr loads grouped permissions, searches, and toggles without a blank page", async ({ page }) => {
|
||||
const { calls } = await bootRolePermissionsPage(page);
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@ const userEnvelope = (rows: Array<Record<string, unknown>>) => ({
|
||||
},
|
||||
});
|
||||
|
||||
const usersApiPattern =
|
||||
/https?:\/\/(?:api\.truckwash\.io(?::\d+)?\/users|localhost(?::\d+)?\/api\/users|127\.0\.0\.1(?::\d+)?\/api\/users)(?:\?.*)?$/i;
|
||||
|
||||
const overviewUser = {
|
||||
id: 11,
|
||||
customer_number: 12345,
|
||||
@@ -217,25 +220,22 @@ test.describe("Superuser employees list", () => {
|
||||
},
|
||||
});
|
||||
|
||||
await page.route(
|
||||
/https?:\/\/(?:api\.truckwash\.io(?::\d+)?\/users|localhost(?::\d+)?\/api\/users|127\.0\.0\.1(?::\d+)?\/api\/users)(?:\?.*)?$/i,
|
||||
async (route) => {
|
||||
const request = route.request();
|
||||
const url = new URL(request.url());
|
||||
await page.route(usersApiPattern, async (route) => {
|
||||
const request = route.request();
|
||||
const url = new URL(request.url());
|
||||
|
||||
if (request.method() !== "GET") {
|
||||
await route.fulfill(json({ data: { message: "OK" } }));
|
||||
return;
|
||||
}
|
||||
|
||||
const search = url.searchParams.get("search");
|
||||
searchesSeen.push(search);
|
||||
const normalizedSearch = String(search || "").toLowerCase();
|
||||
const rows = normalizedSearch.includes("anna") ? [users[0]] : users;
|
||||
|
||||
await route.fulfill(json(userEnvelope(rows)));
|
||||
if (request.method() !== "GET") {
|
||||
await route.fulfill(json({ data: { message: "OK" } }));
|
||||
return;
|
||||
}
|
||||
);
|
||||
|
||||
const search = url.searchParams.get("search");
|
||||
searchesSeen.push(search);
|
||||
const normalizedSearch = String(search || "").toLowerCase();
|
||||
const rows = normalizedSearch.includes("anna") ? [users[0]] : users;
|
||||
|
||||
await route.fulfill(json(userEnvelope(rows)));
|
||||
});
|
||||
|
||||
await page.goto("/superuser/users", { waitUntil: "domcontentloaded" });
|
||||
|
||||
@@ -258,6 +258,114 @@ test.describe("Superuser employees list", () => {
|
||||
await expect(page.getByTestId("action-settings-wheel-section-customer")).toBeVisible();
|
||||
expect(searchesSeen).toContain("Anna");
|
||||
});
|
||||
|
||||
test("migrates an existing employee account into limited backoffice", async ({ page }, testInfo) => {
|
||||
test.skip(!isDesktopProject(testInfo), "Desktop only");
|
||||
|
||||
await page.setViewportSize({ width: 1280, height: 720 });
|
||||
await seedAuthenticatedState(page, "superuser-users-migration-token");
|
||||
await mockApi(page, {
|
||||
authenticated: true,
|
||||
permissions: ["superuser", "user"],
|
||||
sessionData: {
|
||||
group_id: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const legacyEmployee = {
|
||||
id: 13,
|
||||
customer_number: 0,
|
||||
display_name: "Legacy Clerk",
|
||||
group_id: 2,
|
||||
limited_backoffice_managed: false,
|
||||
};
|
||||
const managedEmployee = {
|
||||
id: 14,
|
||||
customer_number: 0,
|
||||
display_name: "Managed Clerk",
|
||||
group_id: 77,
|
||||
limited_backoffice_managed: true,
|
||||
};
|
||||
const customerUser = {
|
||||
id: 15,
|
||||
customer_number: 12345,
|
||||
display_name: "Customer Account",
|
||||
group_id: 2,
|
||||
limited_backoffice_managed: false,
|
||||
};
|
||||
const rows = [legacyEmployee, managedEmployee, customerUser];
|
||||
let usersRequests = 0;
|
||||
let migrationPayload: unknown = null;
|
||||
|
||||
await page.route(usersApiPattern, async (route) => {
|
||||
usersRequests += 1;
|
||||
await route.fulfill(json(userEnvelope(rows)));
|
||||
});
|
||||
await page.route(apiPathPattern("/limited-backoffice/departments"), async (route) => {
|
||||
await route.fulfill(
|
||||
json({
|
||||
data: [
|
||||
{ id: 1, name: "Assigned Depot" },
|
||||
{ id: 2, name: "Remote Depot" },
|
||||
],
|
||||
})
|
||||
);
|
||||
});
|
||||
await page.route(apiPathPattern("/limited-backoffice/roles"), async (route) => {
|
||||
await route.fulfill(
|
||||
json({
|
||||
data: [
|
||||
{ key: "viewer", label: "Deactivated" },
|
||||
{ key: "cashier", label: "Cashier" },
|
||||
{ key: "department_admin", label: "Department admin" },
|
||||
],
|
||||
})
|
||||
);
|
||||
});
|
||||
await page.route(apiPathPattern("/limited-backoffice/employees/13/migrate"), async (route) => {
|
||||
if (route.request().method() !== "POST") {
|
||||
await route.fulfill(json({ data: { message: "OK" } }));
|
||||
return;
|
||||
}
|
||||
|
||||
migrationPayload = await route.request().postDataJSON();
|
||||
await route.fulfill(
|
||||
json({
|
||||
data: {
|
||||
id: 13,
|
||||
user_id: 13,
|
||||
customer_number: 0,
|
||||
display_name: "Legacy Clerk",
|
||||
role: { key: "cashier", label: "Cashier" },
|
||||
departments: [{ id: 1, name: "Assigned Depot" }],
|
||||
active: true,
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
await page.goto("/superuser/users", { waitUntil: "domcontentloaded" });
|
||||
|
||||
await expect(page.getByTestId("superuser-users-row-13")).toContainText("Legacy Clerk");
|
||||
await page.locator('[data-testid="superuser-user-actions-13"] .action-settings-wheel-trigger').click();
|
||||
await expect(page.getByTestId("superuser-user-migrate-limited-13")).toBeVisible();
|
||||
await page.getByTestId("superuser-user-migrate-limited-13").click();
|
||||
|
||||
await expect(page.locator(".swal2-popup")).toContainText("Migrate employee");
|
||||
await page.locator(".limited-migration-department").first().check();
|
||||
await page.locator(".swal2-confirm").click();
|
||||
|
||||
await expect.poll(() => migrationPayload).toEqual({ role_key: "cashier", department_ids: [1] });
|
||||
await expect(page.locator(".swal2-popup")).toContainText("Employee migrated");
|
||||
await page.locator(".swal2-confirm").click();
|
||||
await expect.poll(() => usersRequests).toBeGreaterThan(1);
|
||||
|
||||
await page.locator('[data-testid="superuser-user-actions-14"] .action-settings-wheel-trigger').click();
|
||||
await expect(page.getByTestId("superuser-user-migrate-limited-14")).toHaveCount(0);
|
||||
|
||||
await page.locator('[data-testid="superuser-user-actions-15"] .action-settings-wheel-trigger').click();
|
||||
await expect(page.getByTestId("superuser-user-migrate-limited-15")).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Superuser user overview", () => {
|
||||
|
||||
@@ -6740,6 +6740,51 @@ export async function mockApi(page, options = {}) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pathname.endsWith("/user/invoices") && method === "GET") {
|
||||
const invoiceFixture = posFixture || { collectedInvoices: [] };
|
||||
const customerNumber = Number(options.sessionData?.customer_number || 0);
|
||||
const collectedInvoices = (invoiceFixture.collectedInvoices || []).filter((invoice) => {
|
||||
if (!customerNumber) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Number(invoice.customer_number) === customerNumber;
|
||||
});
|
||||
const page = Number(parsedUrl.searchParams.get("page") || 1);
|
||||
const limit = Number(parsedUrl.searchParams.get("limit") || collectedInvoices.length || 100);
|
||||
|
||||
await route.fulfill(
|
||||
json({
|
||||
data: collectedInvoices.slice((page - 1) * limit, page * limit),
|
||||
meta: {
|
||||
pagination: {
|
||||
page,
|
||||
per_page: limit,
|
||||
total: collectedInvoices.length,
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pathname.endsWith("/invoices/pdf") && method === "GET") {
|
||||
const invoiceId = String(parsedUrl.searchParams.get("id") || "").trim();
|
||||
if (!invoiceId) {
|
||||
await route.fulfill(json({ message: "Invoice not found" }, 404));
|
||||
return;
|
||||
}
|
||||
|
||||
await route.fulfill(
|
||||
json({
|
||||
data: {
|
||||
url: `https://pdf.example.test/invoices/${invoiceId}.pdf`,
|
||||
},
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pathname.endsWith("/collected-invoices") && method === "GET") {
|
||||
const invoiceFixture = posFixture || { collectedInvoices: [] };
|
||||
const filters = parseFilterExpressions(parsedUrl.searchParams.get("filters") || "");
|
||||
|
||||
+48
-22
@@ -1,20 +1,25 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
import {
|
||||
userCredentials,
|
||||
subuserPhoneCredentials,
|
||||
subuserUsernameCredentials,
|
||||
operatorCredentials,
|
||||
customerRegistrationData,
|
||||
driverRegistrationData,
|
||||
invalidCredentials,
|
||||
loginAsUser,
|
||||
loginAsSubuserByPhone,
|
||||
loginAsSubuserByUsername,
|
||||
loginAsOperator,
|
||||
goToUserLogin,
|
||||
goToSubuserLogin,
|
||||
goToOperatorLogin,
|
||||
} from "./fixtures";
|
||||
import { test, expect, type Page } from "@playwright/test";
|
||||
import { createPosFixture, mockApi, seedAuthenticatedState } from "./support/network.js";
|
||||
import { loginAsUser } from "./fixtures";
|
||||
|
||||
const USER_HOME_CUSTOMER_NUMBER = 12345679;
|
||||
|
||||
async function gotoUserHomeWithInvoices(page: Page, collectedInvoices: Array<Record<string, unknown>>) {
|
||||
await mockApi(page, {
|
||||
authenticated: true,
|
||||
sessionData: {
|
||||
customer_number: USER_HOME_CUSTOMER_NUMBER,
|
||||
display_name: "E2E User",
|
||||
permissions: ["user"],
|
||||
},
|
||||
pos: createPosFixture({
|
||||
collectedInvoices,
|
||||
}),
|
||||
});
|
||||
await seedAuthenticatedState(page, "user-home-invoice-shortcut-token");
|
||||
await page.goto("/user", { waitUntil: "domcontentloaded" });
|
||||
await expect(page).toHaveURL(/\/user(?:\/)?(?:[?#].*)?$/);
|
||||
}
|
||||
|
||||
/** User home Tests */
|
||||
// User home page content tests
|
||||
@@ -41,9 +46,30 @@ test("[PAGES][User][/user] should display the download certificate button", asyn
|
||||
// Check if the "download certificate" element is visible
|
||||
await expect(page.locator("a#download-certificates-button")).toBeVisible();
|
||||
});
|
||||
// Download invoices button visibility test
|
||||
test("[PAGES][User][/user] should display the download invoices button", async ({ page }) => {
|
||||
await loginAsUser(page);
|
||||
// Check if the "download invoices" element is visible
|
||||
await expect(page.locator("a#download-invoices-button")).toBeVisible();
|
||||
test("[PAGES][User][/user] should disable the download invoices button when no invoice exists", async ({ page }) => {
|
||||
await gotoUserHomeWithInvoices(page, []);
|
||||
|
||||
const button = page.locator("button#download-invoices-button");
|
||||
await expect(button).toBeVisible();
|
||||
await expect(button).toBeDisabled();
|
||||
await expect(button).not.toHaveClass(/is-loading/);
|
||||
await expect(page.locator("a#download-invoices-button")).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("[PAGES][User][/user] should enable the download invoices button when an invoice exists", async ({ page }) => {
|
||||
await gotoUserHomeWithInvoices(page, [
|
||||
{
|
||||
id: 7001,
|
||||
customer_number: USER_HOME_CUSTOMER_NUMBER,
|
||||
customer_name: "E2E User",
|
||||
total_net_amount: 1250,
|
||||
created_at: "2026-07-01",
|
||||
closed_at: "2026-07-01",
|
||||
},
|
||||
]);
|
||||
|
||||
const link = page.locator("a#download-invoices-button");
|
||||
await expect(link).toBeVisible();
|
||||
await expect(link).toHaveAttribute("href", "/user/invoices");
|
||||
await expect(page.locator("button#download-invoices-button")).toHaveCount(0);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// @vitest-environment jsdom
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
authenticatedRequest: vi.fn(),
|
||||
handleEconomicError: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/components/session/authenticatedRequest.vue", () => ({
|
||||
authenticatedRequest: mocks.authenticatedRequest,
|
||||
}));
|
||||
|
||||
vi.mock("@/components/request/HandleEconomicError.vue", () => ({
|
||||
handleEconomicError: mocks.handleEconomicError,
|
||||
}));
|
||||
|
||||
import GetOrderInvoicePDFButton from "@/components/search/economic/getOrderInvoicePDFButton.vue";
|
||||
|
||||
const LoadButtonWhileAwaitStub = {
|
||||
props: ["disabled", "loadFunction", "actionKey"],
|
||||
template: `
|
||||
<button
|
||||
type="button"
|
||||
:disabled="disabled"
|
||||
:data-action-key="actionKey"
|
||||
@click="loadFunction"
|
||||
>
|
||||
<slot />
|
||||
</button>
|
||||
`,
|
||||
};
|
||||
|
||||
describe("GetOrderInvoicePDFButton", () => {
|
||||
beforeEach(() => {
|
||||
mocks.authenticatedRequest.mockReset();
|
||||
mocks.handleEconomicError.mockReset();
|
||||
vi.stubGlobal("open", vi.fn());
|
||||
});
|
||||
|
||||
it.each([null, undefined, ""])("disables the PDF download when invoice id is %s", async (invoiceId) => {
|
||||
const wrapper = mount(GetOrderInvoicePDFButton, {
|
||||
props: {
|
||||
invoice_id: invoiceId,
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
LoadButtonWhileAwait: LoadButtonWhileAwaitStub,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const button = wrapper.get('[data-action-key="economic-invoice-pdf-download"]');
|
||||
expect(button.attributes("disabled")).toBeDefined();
|
||||
|
||||
await button.trigger("click");
|
||||
await flushPromises();
|
||||
|
||||
expect(mocks.authenticatedRequest).not.toHaveBeenCalled();
|
||||
expect(window.open).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("requests and opens the invoice PDF when invoice id exists", async () => {
|
||||
mocks.authenticatedRequest.mockResolvedValue({
|
||||
data: {
|
||||
data: {
|
||||
url: "https://pdf.example.test/invoices/99101.pdf",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const wrapper = mount(GetOrderInvoicePDFButton, {
|
||||
props: {
|
||||
invoice_id: 99101,
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
LoadButtonWhileAwait: LoadButtonWhileAwaitStub,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const button = wrapper.get('[data-action-key="economic-invoice-pdf-download"]');
|
||||
expect(button.attributes("disabled")).toBeUndefined();
|
||||
|
||||
await button.trigger("click");
|
||||
await flushPromises();
|
||||
|
||||
expect(mocks.authenticatedRequest).toHaveBeenCalledWith("/invoices/pdf", "GET", {
|
||||
id: 99101,
|
||||
});
|
||||
expect(window.open).toHaveBeenCalledWith("https://pdf.example.test/invoices/99101.pdf", "_blank");
|
||||
});
|
||||
});
|
||||
@@ -33,9 +33,12 @@ describe("Playwright full E2E workflow grouping", () => {
|
||||
it("keeps self-hosted full-suite runner pressure bounded while hosted dispatch can fan out", () => {
|
||||
const source = workflowSource();
|
||||
|
||||
expect(source).toMatch(
|
||||
/e2e-full:[\s\S]*?max-parallel: \$\{\{ fromJSON\(github\.event_name == 'workflow_dispatch' && github\.event\.inputs\.runner == 'github-hosted' && '12' \|\| '2'\) \}\}/u
|
||||
);
|
||||
expect(source).toContain("FRONTEND_CI_STANDARD_RUNNER");
|
||||
expect(source).toContain("FRONTEND_CI_E2E_RUNNER");
|
||||
expect(source).toContain("FRONTEND_CI_PR_E2E_MAX_PARALLEL");
|
||||
expect(source).toContain("FRONTEND_CI_FULL_E2E_MAX_PARALLEL");
|
||||
expect(source).toMatch(/e2e-pr:[\s\S]*?max-parallel: \$\{\{ fromJSON\(vars\.FRONTEND_CI_PR_E2E_MAX_PARALLEL/u);
|
||||
expect(source).toMatch(/e2e-full:[\s\S]*?max-parallel: \$\{\{ fromJSON\(vars\.FRONTEND_CI_FULL_E2E_MAX_PARALLEL/u);
|
||||
expect(source).toMatch(/e2e-full:[\s\S]*?PLAYWRIGHT_WORKERS: 1/u);
|
||||
expect(source).toMatch(/e2e-full:[\s\S]*?PLAYWRIGHT_VIDEO_MODE: off/u);
|
||||
expect(source).toContain("scripts/ci/with-systemd-inhibit.sh");
|
||||
@@ -55,22 +58,24 @@ describe("Playwright full E2E workflow grouping", () => {
|
||||
it("keeps PR E2E runner pressure bounded and diagnosable", () => {
|
||||
const source = workflowSource();
|
||||
|
||||
expect(source).toMatch(/e2e-pr:[\s\S]*?runs-on: ubuntu-24\.04/u);
|
||||
expect(source).toMatch(/e2e-pr:[\s\S]*?max-parallel: 4/u);
|
||||
expect(source).toContain("FRONTEND_CI_E2E_RUNNER");
|
||||
expect(source).toMatch(
|
||||
/e2e-pr:[\s\S]*?max-parallel: \$\{\{ fromJSON\(vars\.FRONTEND_CI_PR_E2E_MAX_PARALLEL \|\| '2'\) \}\}/u
|
||||
);
|
||||
expect(source).toMatch(/e2e-pr:[\s\S]*?PLAYWRIGHT_WORKERS: 1/u);
|
||||
expect(source).toMatch(/e2e-pr:[\s\S]*?PLAYWRIGHT_VIDEO_MODE: on-first-retry/u);
|
||||
expect(source).toMatch(/e2e-pr:[\s\S]*?--env PLAYWRIGHT_WORKERS="\$PLAYWRIGHT_WORKERS"/u);
|
||||
expect(source).toMatch(/e2e-pr:[\s\S]*?--env PLAYWRIGHT_VIDEO_MODE="\$PLAYWRIGHT_VIDEO_MODE"/u);
|
||||
});
|
||||
|
||||
it("supports GitHub-hosted manual runners while keeping PR E2E on Ubuntu", () => {
|
||||
it("supports repo-variable runner controls while keeping targeted reruns on Ubuntu", () => {
|
||||
const source = workflowSource();
|
||||
|
||||
expect(source).toContain("github.event.inputs.runner == 'github-hosted'");
|
||||
expect(source).toContain('["ubuntu-latest"]');
|
||||
expect(source).toContain("FRONTEND_CI_STANDARD_RUNNER");
|
||||
expect(source).toContain("FRONTEND_CI_E2E_RUNNER");
|
||||
expect(source).toContain('["self-hosted","Linux","X64","pleno","frontend"]');
|
||||
expect(source).toMatch(/e2e-targeted:[\s\S]*?runs-on: ubuntu-24\.04/u);
|
||||
expect(source).toMatch(/e2e-pr:[\s\S]*?runs-on: ubuntu-24\.04/u);
|
||||
expect(source).toMatch(/e2e-pr:[\s\S]*?runs-on: \$\{\{ fromJSON\(vars\.FRONTEND_CI_E2E_RUNNER/u);
|
||||
expect(source).toMatch(/e2e-full:[\s\S]*?frontend","docker"\]/u);
|
||||
});
|
||||
|
||||
|
||||
@@ -491,6 +491,10 @@ describe("Periode tab contract", () => {
|
||||
expect(xlvaskUsagePaginationSource).toContain('v-if="shouldShowLocalFilters"');
|
||||
expect(xlvaskUsagePaginationSource).toContain('v-if="!hideSearchField && shouldShowLocalFilters"');
|
||||
expect(xlvaskUsagePaginationSource).toContain('v-if="!props.loadAllAtOnce"');
|
||||
expect(xlvaskUsagePaginationSource).toContain("const buildImportUsageParams = () => {");
|
||||
expect(xlvaskUsagePaginationSource).toContain("dateFrom: props.initialDateFrom");
|
||||
expect(xlvaskUsagePaginationSource).toContain("dateTo: props.initialDateTo");
|
||||
expect(xlvaskUsagePaginationSource).toContain("buildImportUsageParams()");
|
||||
});
|
||||
|
||||
it("loads Selvvask selector counts and progress from the selected period", () => {
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
// @vitest-environment jsdom
|
||||
import { flushPromises } from "@vue/test-utils";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { mountWithApp } from "./helpers/mountWithApp.js";
|
||||
|
||||
const mocks = vi.hoisted(() => {
|
||||
const device = {
|
||||
isMobile: vi.fn(() => false),
|
||||
isTablet: vi.fn(() => false),
|
||||
isDesktop: vi.fn(() => true),
|
||||
isWidescreen: vi.fn(() => false),
|
||||
isUltraWideScreen: vi.fn(() => false),
|
||||
};
|
||||
|
||||
return {
|
||||
authenticatedRequest: vi.fn(),
|
||||
sessionUser: {
|
||||
isSubuser: {
|
||||
value: false,
|
||||
},
|
||||
subuser: {
|
||||
selectedGrantCustomerNumber: {
|
||||
value: null,
|
||||
},
|
||||
},
|
||||
permissions: {
|
||||
value: ["user"],
|
||||
},
|
||||
hasPermission: vi.fn((permission) => permission === "user"),
|
||||
canAccessCustomerFeature: vi.fn(() => true),
|
||||
canManageSubusers: vi.fn(() => false),
|
||||
getName: vi.fn(() => "E2E User"),
|
||||
functions: {
|
||||
device,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("@/components/session/authenticatedRequest.vue", () => ({
|
||||
authenticatedRequest: mocks.authenticatedRequest,
|
||||
}));
|
||||
|
||||
vi.mock("@/components/session/token/SessionUser.vue", () => ({
|
||||
default: mocks.sessionUser,
|
||||
}));
|
||||
|
||||
import UserDashboard from "@/views/dashboards/UserDashboard.vue";
|
||||
|
||||
const flushDashboard = async () => {
|
||||
await flushPromises();
|
||||
await flushPromises();
|
||||
};
|
||||
|
||||
const RouterLinkStub = {
|
||||
props: ["to"],
|
||||
template: "<a v-bind=\"$attrs\" :href=\"typeof to === 'string' ? to : '#'\"><slot /></a>",
|
||||
};
|
||||
|
||||
const mountDashboard = () =>
|
||||
mountWithApp(UserDashboard, {
|
||||
global: {
|
||||
stubs: {
|
||||
RouterLink: RouterLinkStub,
|
||||
"router-link": RouterLinkStub,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe("UserDashboard invoice shortcut", () => {
|
||||
beforeEach(() => {
|
||||
mocks.authenticatedRequest.mockReset();
|
||||
mocks.sessionUser.isSubuser.value = false;
|
||||
mocks.sessionUser.permissions.value = ["user"];
|
||||
mocks.sessionUser.hasPermission.mockReset();
|
||||
mocks.sessionUser.hasPermission.mockImplementation((permission) => permission === "user");
|
||||
mocks.sessionUser.canAccessCustomerFeature.mockReset();
|
||||
mocks.sessionUser.canAccessCustomerFeature.mockReturnValue(true);
|
||||
mocks.sessionUser.canManageSubusers.mockReset();
|
||||
mocks.sessionUser.canManageSubusers.mockReturnValue(false);
|
||||
});
|
||||
|
||||
it("keeps the invoice shortcut disabled while invoice availability is loading", () => {
|
||||
mocks.authenticatedRequest.mockReturnValue(new Promise(() => {}));
|
||||
|
||||
const wrapper = mountDashboard();
|
||||
|
||||
const button = wrapper.get("button#download-invoices-button");
|
||||
expect(button.attributes("disabled")).toBeDefined();
|
||||
expect(button.classes()).toContain("is-loading");
|
||||
expect(wrapper.find("a#download-invoices-button").exists()).toBe(false);
|
||||
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it("keeps the invoice shortcut disabled when no invoice exists", async () => {
|
||||
mocks.authenticatedRequest.mockResolvedValue({
|
||||
data: {
|
||||
data: [],
|
||||
meta: {
|
||||
pagination: {
|
||||
total: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const wrapper = mountDashboard();
|
||||
await flushDashboard();
|
||||
|
||||
const button = wrapper.get("button#download-invoices-button");
|
||||
expect(button.attributes("disabled")).toBeDefined();
|
||||
expect(button.classes()).not.toContain("is-loading");
|
||||
expect(wrapper.find("a#download-invoices-button").exists()).toBe(false);
|
||||
expect(mocks.authenticatedRequest).toHaveBeenCalledWith("/user/invoices", "GET", {
|
||||
page: 1,
|
||||
limit: 1,
|
||||
order: "created_at:desc",
|
||||
});
|
||||
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it("enables the invoice shortcut when at least one invoice exists", async () => {
|
||||
mocks.authenticatedRequest.mockResolvedValue({
|
||||
data: {
|
||||
data: [{ id: 501 }],
|
||||
meta: {
|
||||
pagination: {
|
||||
total: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const wrapper = mountDashboard();
|
||||
await flushDashboard();
|
||||
|
||||
const link = wrapper.get("a#download-invoices-button");
|
||||
expect(link.attributes("href")).toBe("/user/invoices");
|
||||
expect(wrapper.find("button#download-invoices-button").exists()).toBe(false);
|
||||
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it("fails closed when invoice availability cannot be loaded", async () => {
|
||||
mocks.authenticatedRequest.mockRejectedValue(new Error("Network unavailable"));
|
||||
|
||||
const wrapper = mountDashboard();
|
||||
await flushDashboard();
|
||||
|
||||
const button = wrapper.get("button#download-invoices-button");
|
||||
expect(button.attributes("disabled")).toBeDefined();
|
||||
expect(wrapper.find("a#download-invoices-button").exists()).toBe(false);
|
||||
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user