Add CollectedOrderInvoicesListPagination and CollectedOrderInvoicesDefaultTable components for handling and displaying collected order invoices with advanced filtering and pagination options
This commit is contained in:
+99
@@ -0,0 +1,99 @@
|
||||
<script setup>
|
||||
|
||||
import CollectedOrderInvoicesDefaultTable from "@/components/displays/superuser/tables/CollectedOrderInvoicesDefaultTable.vue";
|
||||
const props = defineProps({
|
||||
setCustomerFilter: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
hideSearch: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
autoLoad: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
onlyReadyToInvoice: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
tableProps: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
displayClosed: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
displayBooked: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
});
|
||||
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();
|
||||
if (!props.onlyReadyToInvoice || props.onlyReadyToInvoice === false) {
|
||||
setEndpoint("/collected-invoices", false);
|
||||
} else {
|
||||
setEndpoint("/collected-invoices/ready-to-invoice", false);
|
||||
}
|
||||
setOrder("closed_at", "asc", false);
|
||||
// Hide the search field if the prop is set to true
|
||||
setHideSearchField(props.hideSearch);
|
||||
|
||||
if (props.setCustomerFilter) {
|
||||
setFilter("customer_number", props.setCustomerFilter, false);
|
||||
}
|
||||
|
||||
if (!props.displayClosed) {
|
||||
setFilter("closed_at", 'is_null', false);
|
||||
}
|
||||
|
||||
if (!props.displayBooked) {
|
||||
setFilter("booked_invoice_id", 'is_null', false);
|
||||
}
|
||||
|
||||
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"/>
|
||||
<CollectedOrderInvoicesDefaultTable v-bind: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>
|
||||
@@ -0,0 +1,89 @@
|
||||
<script setup>
|
||||
import { defineProps } from 'vue';
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
||||
import ActionSettingsWheelItem from "@/components/displays/buttons/ActionSettingsWheelItem.vue";
|
||||
|
||||
const props = defineProps({
|
||||
objects: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const redirect = (path) => {
|
||||
window.open(path, '_blank');
|
||||
}
|
||||
|
||||
const parseProcessor = (value) => {
|
||||
if (value === null) return SessionUser.objects.global.language.no_data;
|
||||
if (value === 1) return 'E-conomic';
|
||||
return SessionUser.objects.global.language.other;
|
||||
}
|
||||
|
||||
const parseDate = (value) => {
|
||||
if (value === null) return '-';
|
||||
return value;
|
||||
}
|
||||
|
||||
const parseClosedAt = (value) => {
|
||||
if (value === null) return 'Åben';
|
||||
return 'Lukket ' + value;
|
||||
}
|
||||
</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>{{ SessionUser.objects.collectedOrderInvoices.columns.external_id.label }}</th>
|
||||
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.po_number.label }}</th>
|
||||
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.closed_at.label }}</th>
|
||||
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.created_at.label }}</th>
|
||||
<th>{{ SessionUser.objects.collectedOrderInvoices.columns.updated_at.label }}</th>
|
||||
<th class="has-text-right">Handlinger</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="object in props.objects" :key="object.id">
|
||||
<td>{{ object.id }}</td>
|
||||
<td>{{ object.customer_number }}</td>
|
||||
<td>{{ object.name ?? '-' }}</td>
|
||||
<td>{{ object.notes ?? '-' }}</td>
|
||||
<td>{{ parseProcessor(object.processor) }}</td>
|
||||
<td>{{ object.external_id ?? '-' }}</td>
|
||||
<td>{{ object.po_number ?? '-' }}</td>
|
||||
<td>{{ parseClosedAt(object.closed_at) }}</td>
|
||||
<td>{{ parseDate(object.created_at) }}</td>
|
||||
<td>{{ parseDate(object.updated_at) }}</td>
|
||||
<td>
|
||||
<div class="buttons is-float-right">
|
||||
<ActionSettingsWheelButton>
|
||||
<template #actions>
|
||||
<ActionSettingsWheelItem
|
||||
icon="fas fa-eye"
|
||||
@click="redirect('/superuser/invoices/' + object.id)"
|
||||
label="Vis"
|
||||
/>
|
||||
</template>
|
||||
</ActionSettingsWheelButton>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="objects.length === 0">
|
||||
<td colspan="11">
|
||||
Ingen {{ SessionUser.objects.collectedOrderInvoices.meta.labels.multiple }} fundet
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -345,6 +345,38 @@ export const CollectedOrderInvoices = {
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
compareToEconomic: async (id) => {
|
||||
/**
|
||||
* Result example:
|
||||
* {
|
||||
* "success": true,
|
||||
* "data": {
|
||||
* "collected_invoice_id": 10133,
|
||||
* "draft_id": null,
|
||||
* "booked_id": 28368,
|
||||
* "warnings": [
|
||||
* "Error fetching draft ID: Invoice draft with external id (2ced7a3f-fab2-edbd-075f-ce981867c340) not found"
|
||||
* ],
|
||||
* "draft_total": null,
|
||||
* "booked_total": 694,
|
||||
* "difference": null,
|
||||
* "internal_total": 694
|
||||
* },
|
||||
* "meta": [],
|
||||
* "includes": []
|
||||
* }
|
||||
*/
|
||||
// Send the request
|
||||
return authenticatedRequest('/collected-invoices/economic/compare', 'GET', {
|
||||
collected_invoice_id: parseInt(id)
|
||||
}).then((response) => {
|
||||
console.warn(response);
|
||||
return response;
|
||||
}).catch((error) => {
|
||||
console.warn(error);
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
// The additionalBody can contain:
|
||||
// - send_as_is: boolean (default: false) - If true, the invoice will be sent to E-conomic as is, without any modifications made by fixed pricing or vehicle subscriptions.
|
||||
invoice: async (invoiceId, additionalBody = {
|
||||
|
||||
@@ -4,6 +4,8 @@ import RestrictedPageWrapper from "@/components/page/wrappers/RestrictedPageWrap
|
||||
import {SessionUser} from "@/components/session/token/SessionUser.vue";
|
||||
import CollectedOrderInvoicesPagination
|
||||
from "@/components/displays/pagination/models/SuperUserDashboard/CollectedOrderInvoicesPagination.vue";
|
||||
import CollectedOrderInvoicesListPagination
|
||||
from "@/components/displays/pagination/models/SuperUserDashboard/CollectedOrderInvoicesListPagination.vue";
|
||||
import PageTitle from "@/components/global/PageTitle.vue";
|
||||
import ElementTabsBox from "@/components/displays/boxes/ElementTabsBox.vue";
|
||||
import {onMounted, ref, watch} from "vue";
|
||||
@@ -17,6 +19,7 @@ import InvoicingBillingPeriod
|
||||
|
||||
const tabs = ref([
|
||||
{ name: 'Overblik', slot: 'overview', icon: 'fas fa-chart-pie', hidden: false },
|
||||
{ name: 'Fakturaer', slot: 'invoices', icon: 'fas fa-list', hidden: false },
|
||||
//{ name: SessionUser.objects.orders.meta.title, slot: 'transactions', icon: 'fas fa-shopping-cart', hidden: false },
|
||||
{ name: 'Periode', slot: 'period', icon: 'fas fa-calendar-alt', hidden: false },
|
||||
//{ name: 'Faktura pr. måned', slot: 'monthly', icon: 'fas fa-list', hidden: false },
|
||||
@@ -70,6 +73,9 @@ onMounted(() => {
|
||||
<template #overview>
|
||||
<CollectedOrderInvoicesOverview />
|
||||
</template>
|
||||
<template #invoices>
|
||||
<CollectedOrderInvoicesListPagination :auto-load="true" />
|
||||
</template>
|
||||
<!--<template #transactions>
|
||||
<InvoiceOrdersPagination :auto-load="true" :invoice-view="true"/>
|
||||
</template>-->
|
||||
|
||||
Reference in New Issue
Block a user