Add invoice management and improve POS functionality
Introduced "CollectedOrderInvoices" for better invoice handling, including UI components, pagination, and back-end setup. Improved user feedback in POS steps, enhanced form behaviors with new props and watchers, and refined visual styles across components.
This commit is contained in:
@@ -10,7 +10,7 @@ import { showPopper, popper, showPopperWithContent, removePopperIfOpen, popperBo
|
|||||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||||
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
||||||
import ActionSettingsWheelItem from "@/components/displays/buttons/ActionSettingsWheelItem.vue";
|
import ActionSettingsWheelItem from "@/components/displays/buttons/ActionSettingsWheelItem.vue";
|
||||||
import { customer_name, getOrderDetails, setOrderId, order_id, reference, order_notes } from "@/components/shop/POSDepartmentProcess.vue";
|
import { customer_name, getOrderDetails, setOrderId, order_id, reference, order_notes, reg_1, reg_3, reg_2 } from "@/components/shop/POSDepartmentProcess.vue";
|
||||||
import SpanSkeleton from "@/components/displays/skeletons/SpanSkeleton.vue";
|
import SpanSkeleton from "@/components/displays/skeletons/SpanSkeleton.vue";
|
||||||
import PosOrderLicensePlates from "@/components/displays/department/pos/order/PosOrderLicensePlates.vue";
|
import PosOrderLicensePlates from "@/components/displays/department/pos/order/PosOrderLicensePlates.vue";
|
||||||
import POSOrderReference from "@/components/displays/department/pos/order/POSOrderReference.vue";
|
import POSOrderReference from "@/components/displays/department/pos/order/POSOrderReference.vue";
|
||||||
@@ -80,13 +80,17 @@ const registration_numbers = ref({
|
|||||||
|
|
||||||
|
|
||||||
const loadOrder = () => {
|
const loadOrder = () => {
|
||||||
getOrderDetails().then((orderDetails) => {
|
// Wait 100ms before loading the order.
|
||||||
const reg_numbers = registration_numbers.value;
|
// This is to ensure that the order_id is set before loading the order.
|
||||||
reg_numbers[1] = orderDetails.reg_1;
|
setTimeout(() => {
|
||||||
reg_numbers[2] = orderDetails.reg_2;
|
setOrderId(props.orderId);
|
||||||
reg_numbers[3] = orderDetails.reg_3;
|
getOrderDetails().then((orderDetails) => {
|
||||||
});
|
const reg_numbers = registration_numbers.value;
|
||||||
console.log('order note',order_notes.value);
|
reg_numbers[1] = orderDetails.reg_1;
|
||||||
|
reg_numbers[2] = orderDetails.reg_2;
|
||||||
|
reg_numbers[3] = orderDetails.reg_3;
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isTabZeroExpanded = ref(false);
|
const isTabZeroExpanded = ref(false);
|
||||||
|
|||||||
@@ -115,16 +115,22 @@ const getRows = () => {
|
|||||||
const shortNote = ref('');
|
const shortNote = ref('');
|
||||||
|
|
||||||
watch(() => props.note, (value) => {
|
watch(() => props.note, (value) => {
|
||||||
let shownNote = '';
|
shortNote.value = generateShortNote();
|
||||||
if (value.length > 20 || value.split("\n").length > 1) {
|
|
||||||
// Get the first line, and add ...
|
|
||||||
shownNote = value.split("\n")[0].substring(0, 20) + '...';
|
|
||||||
} else {
|
|
||||||
shownNote = value;
|
|
||||||
}
|
|
||||||
console.log(shownNote);
|
|
||||||
shortNote.value = shownNote;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const generateShortNote = () => {
|
||||||
|
let shownNote = '';
|
||||||
|
if (input.value.length > 20 || input.value.split("\n").length > 1) {
|
||||||
|
// Get the first line, and add ...
|
||||||
|
shownNote = input.value.split("\n")[0].substring(0, 20) + '...';
|
||||||
|
} else {
|
||||||
|
shownNote = input.value;
|
||||||
|
}
|
||||||
|
shortNote.value = shownNote;
|
||||||
|
return shownNote;
|
||||||
|
}
|
||||||
|
|
||||||
|
generateShortNote();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -148,7 +154,7 @@ watch(() => props.note, (value) => {
|
|||||||
:readonly="true"
|
:readonly="true"
|
||||||
:rows="1"
|
:rows="1"
|
||||||
v-if="!isEditing"
|
v-if="!isEditing"
|
||||||
v-text="shortNote"
|
v-model="shortNote"
|
||||||
placeholder="Ordre note, denne bliver inkluderet i fakturaen"
|
placeholder="Ordre note, denne bliver inkluderet i fakturaen"
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -115,16 +115,21 @@ const getRows = () => {
|
|||||||
const shortReference = ref('');
|
const shortReference = ref('');
|
||||||
|
|
||||||
watch(() => props.reference, (value) => {
|
watch(() => props.reference, (value) => {
|
||||||
let shownReference = '';
|
generateShortReference();
|
||||||
if (value.length > 20 || value.split("\n").length > 1) {
|
|
||||||
// Get the first line, and add ...
|
|
||||||
shownReference = value.split("\n")[0].substring(0, 20) + '...';
|
|
||||||
} else {
|
|
||||||
shownReference = value;
|
|
||||||
}
|
|
||||||
console.log(shownReference);
|
|
||||||
shortReference.value = shownReference;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const generateShortReference = () => {
|
||||||
|
let shownReference = '';
|
||||||
|
if (input.value.length > 20 || input.value.split("\n").length > 1) {
|
||||||
|
// Get the first line, and add ...
|
||||||
|
shownReference = input.value.split("\n")[0].substring(0, 20) + '...';
|
||||||
|
} else {
|
||||||
|
shownReference = input.value;
|
||||||
|
}
|
||||||
|
shortReference.value = shownReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
generateShortReference();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ const right_tabs = ref([
|
|||||||
<ButtonsBox>
|
<ButtonsBox>
|
||||||
<NextStep class="is-fullwidth" tabindex="6"/>
|
<NextStep class="is-fullwidth" tabindex="6"/>
|
||||||
</ButtonsBox>
|
</ButtonsBox>
|
||||||
<NextStepError class="is-fullwidth" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ defineProps(['currentPage', 'totalPages', 'setPage', 'loadFunction', 'isLoading'
|
|||||||
>Forrige side</a>
|
>Forrige side</a>
|
||||||
<!-- Pagination skeleton while loading -->
|
<!-- Pagination skeleton while loading -->
|
||||||
<!-- Pagination (IF there's less than 20 pages) -->
|
<!-- Pagination (IF there's less than 20 pages) -->
|
||||||
<ul class="pagination-list">
|
<ul class="pagination-list mt-1">
|
||||||
<li v-for="page in totalPages" :key="page" v-if="totalPages <= 15">
|
<li v-for="page in totalPages" :key="page" v-if="totalPages <= 15">
|
||||||
<a class="pagination-link"
|
<a class="pagination-link"
|
||||||
@click="setPage(page); loadFunction()"
|
@click="setPage(page); loadFunction()"
|
||||||
|
|||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
<script setup>
|
||||||
|
|
||||||
|
import CollectedOrderInvoicesTable from "@/components/displays/superuser/tables/collectedOrderInvoicesTable.vue";
|
||||||
|
|
||||||
|
let props = defineProps(["setCustomerFilter", "hideSearch", "autoLoad"]);
|
||||||
|
import { defineProps } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import {
|
||||||
|
isLoaded,
|
||||||
|
isLoading,
|
||||||
|
list,
|
||||||
|
loadList,
|
||||||
|
metaCurrentPage,
|
||||||
|
metaItemsPerPage,
|
||||||
|
metaTotalItems,
|
||||||
|
setEndpoint,
|
||||||
|
setMetaItemsPerPage,
|
||||||
|
setPage,
|
||||||
|
metaSearch,
|
||||||
|
search,
|
||||||
|
setFilter,
|
||||||
|
setOrder,
|
||||||
|
hideSearchField,
|
||||||
|
setHideSearchField,
|
||||||
|
} from "@/components/pagination/paginatedList.vue";
|
||||||
|
import PaginationNavigation from "@/components/displays/pagination/PaginationNavigation.vue";
|
||||||
|
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||||
|
|
||||||
|
import LoadButtonWhileAwait from "@/components/request/LoadButtonWhileAwait.vue";
|
||||||
|
import PaginationDisplay from "@/components/displays/pagination/PaginationDisplay.vue";
|
||||||
|
import OrdersTable from "@/components/displays/department/pos/orders/ordersTable.vue";
|
||||||
|
import CategoriesTable from "@/components/displays/superuser/tables/categoriesTable.vue";
|
||||||
|
const router = useRouter();
|
||||||
|
setEndpoint("/collected-invoices", true);
|
||||||
|
|
||||||
|
// Hide the search field, if the hideSearch prop is set
|
||||||
|
if (props.hideSearch) {
|
||||||
|
setHideSearchField(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.autoLoad) {
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<input @input="search($event.target.value)" class="input" type="text" :placeholder="'Søg efter ' + SessionUser.objects.collectedOrderInvoices.meta.labels.single" v-if="!hideSearchField"/>
|
||||||
|
<PaginationDisplay :metaItemsPerPage="metaItemsPerPage" :loadFunction="loadList" :isLoading="isLoading" :setMetaItemsPerPage="setMetaItemsPerPage"/>
|
||||||
|
<collected-order-invoices-table :objects="list" />
|
||||||
|
<PaginationNavigation :currentPage="metaCurrentPage" :totalPages="Math.ceil(metaTotalItems / metaItemsPerPage)" :loadFunction="loadList" :setPage="setPage" :isLoading="isLoading" />
|
||||||
|
<LoadButtonWhileAwait class="is-dark" :isLoading="isLoading" :loadFunction="loadList" icon="fas fa-sync-alt">Reload</LoadButtonWhileAwait>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -157,8 +157,8 @@ window.addEventListener('resize', () => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</PaginationDisplay>
|
</PaginationDisplay>
|
||||||
<BookingsTable :objects="list" :meta="meta" />
|
<BookingsTable :objects="list" :meta="meta" class="mb-4" />
|
||||||
<PaginationNavigation :currentPage="metaCurrentPage" :totalPages="Math.ceil(metaTotalItems / metaItemsPerPage)" :loadFunction="loadList" :setPage="setPage" :isLoading="isLoading" />
|
<PaginationNavigation :currentPage="metaCurrentPage" :totalPages="Math.ceil(metaTotalItems / metaItemsPerPage)" :loadFunction="loadList" :setPage="setPage" :isLoading="isLoading" class="mt-3" />
|
||||||
<LoadButtonWhileAwait class="is-dark" :isLoading="isLoading" :loadFunction="loadList" icon="fas fa-sync-alt">Opdater</LoadButtonWhileAwait>
|
<LoadButtonWhileAwait class="is-dark" :isLoading="isLoading" :loadFunction="loadList" icon="fas fa-sync-alt">Opdater</LoadButtonWhileAwait>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
<script setup>
|
||||||
|
import EditableTableColumn from "@/components/displays/buttons/EditableTableColumn.vue";
|
||||||
|
import {getCustomerName} from "@/components/shop/POSDepartmentProcess.vue";
|
||||||
|
|
||||||
|
defineProps(['objects']);
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { loadList } from "@/components/pagination/paginatedList.vue";
|
||||||
|
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||||
|
|
||||||
|
const redirect = (path) => {
|
||||||
|
window.location = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<table class="table is-fullwidth is-hoverable is-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.id.label }}</th>
|
||||||
|
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.customer_number.label }}</th>
|
||||||
|
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.name.label }}</th>
|
||||||
|
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.notes.label }}</th>
|
||||||
|
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.processor.label }}</th>
|
||||||
|
<th>Transaktioner</th>
|
||||||
|
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.closed_at.label }}</th>
|
||||||
|
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.created_at.label }}</th>
|
||||||
|
<th><!-- Actions --></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="object in objects" :key="object.id">
|
||||||
|
<td>{{ object.id }}</td>
|
||||||
|
<!-- Customer number -->
|
||||||
|
<EditableTableColumn
|
||||||
|
:object="object"
|
||||||
|
:loadList="loadList"
|
||||||
|
column="customer_number"
|
||||||
|
/>
|
||||||
|
<!-- Name -->
|
||||||
|
<EditableTableColumn
|
||||||
|
:object="object"
|
||||||
|
:loadList="loadList"
|
||||||
|
:editFunction="SessionUser.objects.collectedOrderInvoices.showEditObjectFieldForm"
|
||||||
|
column="name"
|
||||||
|
/>
|
||||||
|
<!-- Notes -->
|
||||||
|
<EditableTableColumn
|
||||||
|
:object="object"
|
||||||
|
:loadList="loadList"
|
||||||
|
:editFunction="SessionUser.objects.collectedOrderInvoices.showEditObjectFieldForm"
|
||||||
|
column="notes"
|
||||||
|
/>
|
||||||
|
<!-- Processor -->
|
||||||
|
<EditableTableColumn
|
||||||
|
:object="object"
|
||||||
|
:loadList="loadList"
|
||||||
|
:editFunction="SessionUser.objects.collectedOrderInvoices.showEditObjectFieldForm"
|
||||||
|
column="processor"
|
||||||
|
/>
|
||||||
|
<!-- Transactions -->
|
||||||
|
<EditableTableColumn
|
||||||
|
:object="object"
|
||||||
|
:loadList="loadList"
|
||||||
|
column="orders"
|
||||||
|
/>
|
||||||
|
<!-- Closed at -->
|
||||||
|
<EditableTableColumn
|
||||||
|
:object="object"
|
||||||
|
:loadList="loadList"
|
||||||
|
column="closed_at"
|
||||||
|
/>
|
||||||
|
<!-- Created at -->
|
||||||
|
<EditableTableColumn
|
||||||
|
:object="object"
|
||||||
|
:loadList="loadList"
|
||||||
|
column="created_at"
|
||||||
|
/>
|
||||||
|
</tr>
|
||||||
|
<!-- If the list is empty -->
|
||||||
|
<tr v-if="objects.length === 0">
|
||||||
|
<td colspan="9">
|
||||||
|
Ingen {{ SessionUser.objects.collectedOrderInvoices.meta.labels.multiple }} fundet
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- Show a count of the total number of objects -->
|
||||||
|
<tr>
|
||||||
|
<td colspan="9">Viser {{ objects.length }} {{ SessionUser.objects.collectedOrderInvoices.meta.labels.multiple }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -134,20 +134,24 @@ const keyDownNextTabIndexButton = (event, tabIndex) => {
|
|||||||
@keydown="keyDownNextInput($event, 'reg_2')"
|
@keydown="keyDownNextInput($event, 'reg_2')"
|
||||||
input-id="reg_1"
|
input-id="reg_1"
|
||||||
v-model:inputModel="reg_1"
|
v-model:inputModel="reg_1"
|
||||||
|
v-bind:actual-value="reg_1"
|
||||||
:customer_number="parseInt(customer_id) || 0"
|
:customer_number="parseInt(customer_id) || 0"
|
||||||
class="has-sharp-edges"
|
class="has-sharp-edges"
|
||||||
/>
|
/>
|
||||||
|
{{ reg_1}}
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Reg 2</label>
|
<label class="label">Reg 2</label>
|
||||||
<LicensePlateInput :tab-index="4" @keydown="keyDownNextInput($event, 'reg_3')" input-id="reg_2" v-model:inputModel="reg_2" :customer_number="parseInt(customer_id) || 0" />
|
<LicensePlateInput :tab-index="4" @keydown="keyDownNextInput($event, 'reg_3')" input-id="reg_2" v-model:inputModel="reg_2" :customer_number="parseInt(customer_id) || 0" v-bind:actual-value="reg_2" />
|
||||||
|
{{ reg_2}}
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Reg 3</label>
|
<label class="label">Reg 3</label>
|
||||||
<!--<div class="control">
|
<!--<div class="control">
|
||||||
<input class="input reg-input" type="text" v-model="reg_3" tabindex="5" @keydown="keyDownNextTabIndexButton($event, 6)" id="reg_3" />
|
<input class="input reg-input" type="text" v-model="reg_3" tabindex="5" @keydown="keyDownNextTabIndexButton($event, 6)" id="reg_3" />
|
||||||
</div> -->
|
</div> -->
|
||||||
<LicensePlateInput :tab-index="5" @keydown="keyDownNextTabIndexButton($event, 6)" input-id="reg_3" v-model:inputModel="reg_3" :customer_number="parseInt(customer_id) || 0" />
|
<LicensePlateInput :tab-index="5" @keydown="keyDownNextTabIndexButton($event, 6)" input-id="reg_3" v-model:inputModel="reg_3" :customer_number="parseInt(customer_id) || 0" v-bind:actual-value="reg_3" />
|
||||||
|
{{ reg_3}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<PosNotes :notes="notes" :is-loading="false" :isAddFormVisible="SessionUser.adminUser" :isOldNotesVisible="false" :is-label-visible="true" class="mt-3" v-if="isCustomerSelected()" />
|
<PosNotes :notes="notes" :is-loading="false" :isAddFormVisible="SessionUser.adminUser" :isOldNotesVisible="false" :is-label-visible="true" class="mt-3" v-if="isCustomerSelected()" />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {defineEmits, defineProps, ref} from 'vue';
|
import {defineEmits, defineProps, ref, watch} from 'vue';
|
||||||
import {SessionUser} from "@/components/session/token/SessionUser.vue";
|
import {SessionUser} from "@/components/session/token/SessionUser.vue";
|
||||||
import {getError, parseError} from "@/components/request/HandleGlobalError.vue";
|
import {getError, parseError} from "@/components/request/HandleGlobalError.vue";
|
||||||
|
|
||||||
@@ -17,6 +17,10 @@ const props = defineProps(
|
|||||||
type: String,
|
type: String,
|
||||||
required: false
|
required: false
|
||||||
},
|
},
|
||||||
|
actualValue: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
customer_number: {
|
customer_number: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: false
|
required: false
|
||||||
@@ -203,6 +207,20 @@ const setInputValue = (licensePlate) => {
|
|||||||
const isDropdownItemSelected = (registrationNumber) => {
|
const isDropdownItemSelected = (registrationNumber) => {
|
||||||
return registrationNumber === customerRegistrationNumbers.value[selectedDropdownItem.value];
|
return registrationNumber === customerRegistrationNumbers.value[selectedDropdownItem.value];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const inputField = ref(null);
|
||||||
|
|
||||||
|
watch(() => props.actualValue, (newValue) => {
|
||||||
|
if (newValue === currentFieldVal.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Set the value of the input field
|
||||||
|
inputField.value.value = newValue;
|
||||||
|
currentFieldVal.value = newValue;
|
||||||
|
checkLicensePlateValid(newValue);
|
||||||
|
searchCustomerRegistrationNumbers(newValue);
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -218,6 +236,7 @@ const isDropdownItemSelected = (registrationNumber) => {
|
|||||||
:tabindex="props.tabIndex"
|
:tabindex="props.tabIndex"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
@keydown="pressedKey($event)"
|
@keydown="pressedKey($event)"
|
||||||
|
ref="inputField"
|
||||||
/>
|
/>
|
||||||
<span class="icon is-small is-right" v-if="isValueValid()">
|
<span class="icon is-small is-right" v-if="isValueValid()">
|
||||||
<i class="fas fa-check"></i>
|
<i class="fas fa-check"></i>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {EconomicDepartments} from "@/components/session/token/SessionUser/Object
|
|||||||
import {EconomicProducts} from "@/components/session/token/SessionUser/Objects/economicProducts.vue";
|
import {EconomicProducts} from "@/components/session/token/SessionUser/Objects/economicProducts.vue";
|
||||||
import {Roles} from "@/components/session/token/SessionUser/Objects/Roles.vue";
|
import {Roles} from "@/components/session/token/SessionUser/Objects/Roles.vue";
|
||||||
import {Permissions} from "@/components/session/token/SessionUser/Objects/Permissions.vue";
|
import {Permissions} from "@/components/session/token/SessionUser/Objects/Permissions.vue";
|
||||||
|
import {CollectedOrderInvoices} from "@/components/session/token/SessionUser/Objects/CollectedOrderInvoices.vue";
|
||||||
import {ObjectsGlobal} from "@/components/session/token/SessionUser/Objects/ObjectsGlobal.vue";
|
import {ObjectsGlobal} from "@/components/session/token/SessionUser/Objects/ObjectsGlobal.vue";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
|
|
||||||
@@ -175,6 +176,7 @@ export const SessionUser = {
|
|||||||
economic_products: EconomicProducts,
|
economic_products: EconomicProducts,
|
||||||
roles: Roles,
|
roles: Roles,
|
||||||
permissions: Permissions,
|
permissions: Permissions,
|
||||||
|
collectedOrderInvoices: CollectedOrderInvoices,
|
||||||
global: ObjectsGlobal,
|
global: ObjectsGlobal,
|
||||||
},
|
},
|
||||||
/** The user's token & authentication status */
|
/** The user's token & authentication status */
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
<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";
|
||||||
|
import {ref} from "vue";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CollectOrderInvoices object
|
||||||
|
*/
|
||||||
|
export const CollectedOrderInvoices = {
|
||||||
|
meta: {
|
||||||
|
title: "Samlede ordrefakturaer",
|
||||||
|
icon: "fas fa-list",
|
||||||
|
description: "Oversigt over samlede ordrefakturaer",
|
||||||
|
endpoint: "/collected-invoices",
|
||||||
|
labels: {
|
||||||
|
single: "samlet ordrefaktura",
|
||||||
|
multiple: "samlede ordrefakturaer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
label: "ID",
|
||||||
|
type: "number",
|
||||||
|
sortable: true,
|
||||||
|
creation: {
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
customer_number: {
|
||||||
|
label: "E-conomic kundenummer",
|
||||||
|
type: "number",
|
||||||
|
sortable: true,
|
||||||
|
creation: {
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
label: "Navn",
|
||||||
|
type: "string",
|
||||||
|
sortable: true,
|
||||||
|
creation: {
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
notes: {
|
||||||
|
label: "Noter",
|
||||||
|
type: "string",
|
||||||
|
sortable: true,
|
||||||
|
creation: {
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
processor: {
|
||||||
|
label: "Faktureringsprocessor",
|
||||||
|
type: "number",
|
||||||
|
sortable: true,
|
||||||
|
creation: {
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
external_id: {
|
||||||
|
label: "Eksternt ID",
|
||||||
|
type: "number",
|
||||||
|
sortable: true,
|
||||||
|
creation: {
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closed_at: {
|
||||||
|
label: "Lukket",
|
||||||
|
type: "date",
|
||||||
|
sortable: true,
|
||||||
|
creation: {
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created_at: {
|
||||||
|
label: "Oprettet",
|
||||||
|
type: "date",
|
||||||
|
sortable: true,
|
||||||
|
creation: {
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updated_at: {
|
||||||
|
label: "Opdateret",
|
||||||
|
type: "date",
|
||||||
|
sortable: true,
|
||||||
|
creation: {
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
add: async (name, description) => {
|
||||||
|
return ObjectsGlobal.add.object(
|
||||||
|
CollectedOrderInvoices.meta.endpoint,
|
||||||
|
{
|
||||||
|
name: name,
|
||||||
|
description: description
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
set: {
|
||||||
|
name: async (id, name) => {
|
||||||
|
return ObjectsGlobal.set.column(
|
||||||
|
CollectedOrderInvoices.meta.endpoint,
|
||||||
|
id,
|
||||||
|
"name",
|
||||||
|
name
|
||||||
|
)
|
||||||
|
},
|
||||||
|
notes: async (id, notes) => {
|
||||||
|
return ObjectsGlobal.set.column(
|
||||||
|
CollectedOrderInvoices.meta.endpoint,
|
||||||
|
id,
|
||||||
|
"notes",
|
||||||
|
notes
|
||||||
|
)
|
||||||
|
},
|
||||||
|
processor: async (id, processor = null) => {
|
||||||
|
return ObjectsGlobal.set.column(
|
||||||
|
CollectedOrderInvoices.meta.endpoint,
|
||||||
|
id,
|
||||||
|
"processor",
|
||||||
|
processor ? parseInt(processor) : null
|
||||||
|
)
|
||||||
|
},
|
||||||
|
external_id: async (id, external_id) => {
|
||||||
|
return ObjectsGlobal.set.column(
|
||||||
|
CollectedOrderInvoices.meta.endpoint,
|
||||||
|
id,
|
||||||
|
"external_id",
|
||||||
|
parseInt(external_id)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
get: {
|
||||||
|
all: async () => {
|
||||||
|
return ObjectsGlobal.get.objects(CollectedOrderInvoices.meta.endpoint);
|
||||||
|
},
|
||||||
|
single: async (id) => {
|
||||||
|
return ObjectsGlobal.get.object(CollectedOrderInvoices.meta.endpoint, id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
functions: {},
|
||||||
|
/**
|
||||||
|
* Show the create object form
|
||||||
|
* @param onAfterSubmit
|
||||||
|
* @returns {Promise<SweetAlertResult<Awaited<any>>>}
|
||||||
|
*/
|
||||||
|
showCreateObjectForm: (onAfterSubmit = null) => {
|
||||||
|
return ObjectsGlobal.showCreateObjectForm(CollectedOrderInvoices, onAfterSubmit);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Show the edit object field form
|
||||||
|
* @param id
|
||||||
|
* @param column
|
||||||
|
* @param value
|
||||||
|
* @param onAfterSubmit
|
||||||
|
* @returns {Promise<SweetAlertResult<Awaited<any>>>}
|
||||||
|
*/
|
||||||
|
showEditObjectFieldForm: (id, column, value, onAfterSubmit = null) => {
|
||||||
|
return ObjectsGlobal.showEditObjectFieldForm(
|
||||||
|
CollectedOrderInvoices,
|
||||||
|
id,
|
||||||
|
column,
|
||||||
|
value,
|
||||||
|
onAfterSubmit
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -80,8 +80,17 @@ export const nextStep = async () => {
|
|||||||
setProductsCategory(4);
|
setProductsCategory(4);
|
||||||
}
|
}
|
||||||
if (step.value === 3) {
|
if (step.value === 3) {
|
||||||
// If the current step is 3, redirect to the /admin/:departmentId/modules/pos/orders/:orderId page
|
// Show a "Success" dialog, that closes after 2 seconds, then redirects to the next page
|
||||||
window.location.href = `/admin/${department_id.value}/modules/pos/orders/${order_id.value}`;
|
Swal.fire({
|
||||||
|
title: 'Fuldført',
|
||||||
|
text: 'Transaktionen er fuldført, omdirigerer automatisk...',
|
||||||
|
icon: 'success',
|
||||||
|
showConfirmButton: false,
|
||||||
|
timer: 2000
|
||||||
|
}).then(() => {
|
||||||
|
// Redirect to the next page
|
||||||
|
window.location.href = '/admin/' + department_id.value + '/modules/pos';
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
step.value++;
|
step.value++;
|
||||||
@@ -566,9 +575,19 @@ export const canBuyTankCleaning = () => {
|
|||||||
return !hasAttribute('restrictTankCleaning');
|
return !hasAttribute('restrictTankCleaning');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function loadOrderDetails() {
|
||||||
|
getOrderDetails().then((response) => {
|
||||||
|
console.log(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** Set the order id */
|
/** Set the order id */
|
||||||
export const setOrderId = (id) => {
|
export const setOrderId = (id) => {
|
||||||
order_id.value = id;
|
order_id.value = id;
|
||||||
|
// Load the order details
|
||||||
|
loadOrderDetails();
|
||||||
|
// Load the order items
|
||||||
|
loadOrderItems();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Delete everything button */
|
/** Delete everything button */
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ import Roles from "@/views/dashboards/superUserDashboard/roles/Roles.vue";
|
|||||||
import SuperUserRolesPermissions from "@/views/dashboards/superUserDashboard/roles/SuperUserRolesPermissions.vue";
|
import SuperUserRolesPermissions from "@/views/dashboards/superUserDashboard/roles/SuperUserRolesPermissions.vue";
|
||||||
import DepartmentStripeTerminalsReaders from "@/views/dashboards/superUserDashboard/department/stripe/DepartmentStripeTerminalsReaders.vue";
|
import DepartmentStripeTerminalsReaders from "@/views/dashboards/superUserDashboard/department/stripe/DepartmentStripeTerminalsReaders.vue";
|
||||||
import DepartmentStripeSetup from "@/views/dashboards/superUserDashboard/department/stripe/DepartmentStripeSetup.vue";
|
import DepartmentStripeSetup from "@/views/dashboards/superUserDashboard/department/stripe/DepartmentStripeSetup.vue";
|
||||||
|
import CollectedOrderInvoices from "@/views/dashboards/superUserDashboard/CollectedOrderInvoices.vue";
|
||||||
|
|
||||||
// Export the router as router
|
// Export the router as router
|
||||||
export const router = createRouter({
|
export const router = createRouter({
|
||||||
@@ -241,6 +242,12 @@ export const router = createRouter({
|
|||||||
component: Products,
|
component: Products,
|
||||||
meta: { middleware: superUserMiddleware }
|
meta: { middleware: superUserMiddleware }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'collectedorderinvoices',
|
||||||
|
path: '/superuser/invoices',
|
||||||
|
component: CollectedOrderInvoices,
|
||||||
|
meta: { middleware: superUserMiddleware }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'orders',
|
name: 'orders',
|
||||||
path: '/superuser/orders',
|
path: '/superuser/orders',
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const slots = defineSlots()
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Left menu -->
|
<!-- Left menu -->
|
||||||
<div class="column is-2 is-auto-height-fill"
|
<div class="column is-2 is-continuous-to-bottom"
|
||||||
:style="{ 'background-color': Colors.menus.parentBackgroundColor, 'color': Colors.menus.textColor }"
|
:style="{ 'background-color': Colors.menus.parentBackgroundColor, 'color': Colors.menus.textColor }"
|
||||||
>
|
>
|
||||||
<slot name="left-menu"></slot>
|
<slot name="left-menu"></slot>
|
||||||
@@ -63,6 +63,7 @@ const slots = defineSlots()
|
|||||||
<div
|
<div
|
||||||
class="column is-10"
|
class="column is-10"
|
||||||
:style="{ 'background-color': Colors.global.backgroundColor, 'color': Colors.global.textColor }"
|
:style="{ 'background-color': Colors.global.backgroundColor, 'color': Colors.global.textColor }"
|
||||||
|
style="min-height: 100vh;"
|
||||||
>
|
>
|
||||||
<div class="pl-6 pr-6 pb-6">
|
<div class="pl-6 pr-6 pb-6">
|
||||||
<!-- Buttons slot -->
|
<!-- Buttons slot -->
|
||||||
@@ -78,18 +79,12 @@ const slots = defineSlots()
|
|||||||
<slot name="without-formatting"></slot>
|
<slot name="without-formatting"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Footer -->
|
<!-- Footer
|
||||||
<div class="column is-12">
|
<div class="column is-12">
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.is-auto-height-fill {
|
|
||||||
height: auto;
|
|
||||||
max-height: 100vh;
|
|
||||||
min-height: 100vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script setup>
|
||||||
|
import SuperUserDashboardNavigation from "@/views/dashboards/superUserDashboard/SuperUserDashboardNavigation.vue";
|
||||||
|
import RestrictedPageWrapper from "@/components/page/wrappers/RestrictedPageWrapper.vue";
|
||||||
|
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||||
|
import CollectedOrderInvoicesPagination
|
||||||
|
from "@/components/displays/pagination/models/SuperUserDashboard/CollectedOrderInvoicesPagination.vue";
|
||||||
|
import PageTitle from "@/components/global/PageTitle.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<RestrictedPageWrapper :hasPermission="SessionUser.canAccessSuperUser()">
|
||||||
|
<SuperUserDashboardNavigation />
|
||||||
|
<PageTitle title="Fakturaer" subtitle="Her kan du se en liste over alle fakturaer i systemet" />
|
||||||
|
<CollectedOrderInvoicesPagination />
|
||||||
|
</RestrictedPageWrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -14,6 +14,7 @@ const tabs = [
|
|||||||
{ name: 'Medarbejdere', path: '/superuser/users' },
|
{ name: 'Medarbejdere', path: '/superuser/users' },
|
||||||
{ name: 'Customers', path: '/superuser/customers' },
|
{ name: 'Customers', path: '/superuser/customers' },
|
||||||
{ name: 'Products', path: '/superuser/products' },
|
{ name: 'Products', path: '/superuser/products' },
|
||||||
|
{ name: 'Fakturaer', path: '/superuser/invoices' },
|
||||||
{ name: 'Transaktionshistorik', path: '/superuser/orders' },
|
{ name: 'Transaktionshistorik', path: '/superuser/orders' },
|
||||||
{ name: 'Scanners', path: '/superuser/scanners' },
|
{ name: 'Scanners', path: '/superuser/scanners' },
|
||||||
{ name: 'Roles', path: '/superuser/roles' },
|
{ name: 'Roles', path: '/superuser/roles' },
|
||||||
|
|||||||
Reference in New Issue
Block a user