415 lines
15 KiB
Vue
415 lines
15 KiB
Vue
<script setup lang="ts">
|
|
import { useOrdersStore } from '@/stores/orders.store'
|
|
import { storeToRefs } from 'pinia'
|
|
import VueDatePicker from '@vuepic/vue-datepicker'
|
|
import { useSiteControlStore } from '@/stores/siteControl.store'
|
|
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
import { useCategoriesStore } from '@/stores/categories.store'
|
|
import type { Order, OrderProduct, Product } from '@/main'
|
|
import { useRoutesStore } from '@/stores/routes.store'
|
|
import { bool } from 'yup'
|
|
|
|
const ordersStore = useOrdersStore()
|
|
const categoriesStore = useCategoriesStore()
|
|
const routeStore = useRoutesStore()
|
|
|
|
const { orders, dates } = storeToRefs(ordersStore)
|
|
const { routes } = storeToRefs(routeStore)
|
|
const searchDate = ref<Date>(new Date(Date.now()))
|
|
const confirmedOrders = ref<boolean>()
|
|
const isSummed = ref<boolean>(true)
|
|
const nipGrouped = ref(false)
|
|
const isLoading = ref<boolean>(true)
|
|
const summedProducts = ref<Array<Product>>([])
|
|
const products = ref<Array<Object>>()
|
|
const ordersByRoute = ref<Map<string, Array<Order>>>(new Map<string, Array<Order>>())
|
|
const orderByRouteAndNipRef = ref<Map<string, Map<number, {
|
|
orders: Order[];
|
|
products: OrderProduct[]
|
|
}>>>(new Map<string, Map<number, { orders: Order[]; products: OrderProduct[] }>>)
|
|
const activeButton = ref(null)
|
|
|
|
const watchSearchDate = watch(searchDate, async (oldSearchDate, newSeatchDate) => {
|
|
if (oldSearchDate != newSeatchDate) {
|
|
await fetchOrders()
|
|
}
|
|
})
|
|
|
|
const watchConfirmedOrders = watch(confirmedOrders, async (oldConfirmedOrders, newConfirmedOrders) => {
|
|
if (oldConfirmedOrders != newConfirmedOrders) {
|
|
await fetchOrders()
|
|
}
|
|
})
|
|
const setActive = (button) => {
|
|
activeButton.value = button;
|
|
|
|
if (button === 'separate') {
|
|
isSummed.value = false;
|
|
nipGrouped.value = false;
|
|
} else if (button === 'grouped') {
|
|
isSummed.value = false;
|
|
nipGrouped.value = true;
|
|
} else if (button === 'summed') {
|
|
isSummed.value = true;
|
|
nipGrouped.value = false;
|
|
}
|
|
};
|
|
async function fetchOrders() {
|
|
isLoading.value = true
|
|
orders.value = await ordersStore.fetchOrdersByDateStartAndEnd(searchDate.value != undefined ? searchDate.value : new Date(Date.now()),
|
|
searchDate.value != undefined ? searchDate.value : new Date(Date.now()),
|
|
(confirmedOrders.value) ? false : null)
|
|
const productsMap = await categoriesStore.sumProductsFromOrders(orders.value)
|
|
summedProducts.value = []
|
|
for (const product of productsMap.values()) {
|
|
if (product.SummedQuantity > 0) {
|
|
summedProducts.value.push(product)
|
|
}
|
|
}
|
|
await prepareProductsFromOrders()
|
|
|
|
isLoading.value = false
|
|
}
|
|
|
|
function addRoutes() {
|
|
for (const route of routes.value) {
|
|
ordersByRoute.value.set(route.MZT_Nazwa1, [])
|
|
}
|
|
ordersByRoute.value.set('brak', [])
|
|
}
|
|
function updateProducts(order: UnwrapRefSimple<Order> | UnwrapRefSimple<UnwrapRefSimple<Order>>) {
|
|
for (const product of order.MZamElem) {
|
|
const newProduct = {
|
|
'kod': product.MZE_TwrKod,
|
|
'nazwa': product.MZE_TwrNazwa,
|
|
'ilosc': Number(product.MZE_TwrIlosc).toFixed(2),
|
|
'jm': product.MZE_TwrJm,
|
|
'cena': Number(product.MZE_TwrCena).toFixed(2),
|
|
'suma': Number(Number(product.MZE_TwrCena) * Number(product.MZE_TwrIlosc)).toFixed(2)
|
|
}
|
|
order.products.push(newProduct)
|
|
}
|
|
}
|
|
function prepareProductsFromOrders() {
|
|
products.value = []
|
|
if (orders.value == undefined || routes.value == undefined) {
|
|
return
|
|
}
|
|
addRoutes()
|
|
for (const order of orders.value) {
|
|
order.products = []
|
|
updateProducts(order)
|
|
const routeName = routes.value.find( route => {
|
|
return route.MZT_MZTID == order.MZN_MZTID
|
|
})?.MZT_Nazwa1;
|
|
|
|
ordersByRoute.value.get(routeName != undefined ? routeName : "brak")?.push(order);
|
|
}
|
|
console.log(orders.value)
|
|
console.log(ordersByRoute.value)
|
|
groupByNip()
|
|
}
|
|
|
|
function groupByNip() {
|
|
const orderByRouteAndNip = new Map<string, Map<number, { orders: Order[]; products: OrderProduct[] }>>()
|
|
|
|
for (const [route, orders] of ordersByRoute.value) {
|
|
const ordersByNip = new Map<number, { orders: Order[]; products: OrderProduct[] }>()
|
|
|
|
for (const order of orders) {
|
|
if (!ordersByNip.has(order.MZN_PodNipE)) {
|
|
ordersByNip.set(order.MZN_PodNipE, { orders: [], products: [] })
|
|
}
|
|
const entry = ordersByNip.get(order.MZN_PodNipE)
|
|
entry.orders.push(order)
|
|
|
|
for (const element of order.MZamElem) {
|
|
const existingProduct = entry.products.find(p => p.MZE_TwrId === element.MZE_TwrId)
|
|
if (existingProduct) {
|
|
existingProduct.MZE_TwrCena =String(Number(existingProduct.MZE_TwrCena).toFixed(2))
|
|
existingProduct.MZE_TwrIlosc = String(
|
|
Number(Number(existingProduct.MZE_TwrIlosc) + Number(element.MZE_TwrIlosc)).toFixed(2)
|
|
)
|
|
existingProduct.suma = Number(Number(existingProduct.MZE_TwrIlosc) * Number(existingProduct.MZE_TwrCena)).toFixed(2)
|
|
} else {
|
|
element.MZE_TwrCena = String(Number(element.MZE_TwrCena).toFixed(2))
|
|
element.MZE_TwrIlosc = String(Number(element.MZE_TwrIlosc).toFixed(2))
|
|
element.suma = Number(Number(element.MZE_TwrIlosc )*Number(element.MZE_TwrCena)).toFixed(2)
|
|
entry.products.push(element)
|
|
}
|
|
}
|
|
}
|
|
orderByRouteAndNip.set(route, ordersByNip)
|
|
}
|
|
orderByRouteAndNipRef.value = orderByRouteAndNip
|
|
console.log(orderByRouteAndNip)
|
|
|
|
}
|
|
|
|
onMounted(async () => {
|
|
orders.value = await ordersStore.fetchOrdersByDay(searchDate.value, null);
|
|
const productsMap = await categoriesStore.sumProductsFromOrders(orders.value);
|
|
summedProducts.value = [];
|
|
for(const product of productsMap.values()) {
|
|
if(product.SummedQuantity > 0) {
|
|
summedProducts.value.push(product);
|
|
}
|
|
}
|
|
console.log(summedProducts.value);
|
|
await prepareProductsFromOrders();
|
|
console.log(products.value);
|
|
isLoading.value=false;
|
|
|
|
console.log(ordersByRoute.value)
|
|
});
|
|
|
|
|
|
onBeforeUnmount(async function() {
|
|
const siteControlStore = useSiteControlStore();
|
|
await siteControlStore.newOrder(false);
|
|
})
|
|
|
|
function documnetType(order : Order):string {
|
|
if(order.MZN_TypDokumentu == 306) return ", Dokument WZ"
|
|
else return ""
|
|
}
|
|
function ifOneWZExists(orders: Array<UnwrapRefSimple<Order>> ):string {
|
|
for (const order of orders) {
|
|
console.log(order.MZN_TypDokumentu);
|
|
if (order.MZN_TypDokumentu === 306) return ". Dokument WZ"; // ❗ PRZERYWA funkcję natychmiast
|
|
}
|
|
return ""
|
|
}
|
|
|
|
function hasNonEmptyUwagi(item: any): boolean {
|
|
let found = false;
|
|
item.orders.forEach(order => {
|
|
if(order.MZN_Uwagi) {
|
|
found = true;
|
|
}
|
|
})
|
|
|
|
return found;
|
|
}
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<div class="columns box is-shadowless" style="margin: 0.5rem 0 0; padding: 0; min-height: 100%">
|
|
<div class="column">
|
|
<div class="box">
|
|
<h1 class="title is-4 mb-3">Opcje</h1>
|
|
<label class="label is-small">Data dostawy</label>
|
|
<VueDatePicker v-model="searchDate"
|
|
:enable-time-picker="false"
|
|
:clearable="true"
|
|
input-class-name="input is-small calendar-background"
|
|
menu-class-name="calendar-background"
|
|
:highlight = "dates"
|
|
/>
|
|
|
|
<div class="control mt-3">
|
|
<label class="checkbox mr-5">
|
|
<input type="checkbox" v-model="confirmedOrders"/>
|
|
Tylko potwierdzone zamówienia?
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="box mt-3">
|
|
|
|
<button
|
|
class="button is-fullwidth mb-3"
|
|
:class="{ 'is-active': activeButton === 'grouped' }"
|
|
@click="setActive('grouped')"
|
|
>
|
|
Zamówienia pogrupowane po NIP
|
|
</button>
|
|
|
|
<button
|
|
class="button is-fullwidth mb-3"
|
|
:class="{ 'is-active': activeButton === 'separate' }"
|
|
@click="setActive('separate')"
|
|
>
|
|
Rozdzielone zamówienia
|
|
</button>
|
|
|
|
|
|
<button
|
|
class="button is-fullwidth mb-3"
|
|
:class="{ 'is-active': activeButton === 'summed' }"
|
|
@click="setActive('summed')"
|
|
>
|
|
Zsumowane zamówienia
|
|
</button>
|
|
<button class="button is-fullwidth" v-print="'#printMe'">Drukuj</button>
|
|
</div>
|
|
</div>
|
|
<div class="column is-four-fifths">
|
|
<div class="box" style="width: 100%; height: 100%; padding: 0">
|
|
<div style="width: 100%; height: 100%">
|
|
<div v-if="isLoading == true" class="is-flex is-justify-content-center is-flex-direction-row" style="height: 100%; align-content:space-evenly">
|
|
<div class="title is-1 has-text-centered element is-loading" style="min-height: 150px; align-self: center;"></div>
|
|
</div>
|
|
<div v-else-if="orders != undefined && orders.length != 0 && !isSummed" id="printMe">
|
|
<div v-for="route in routes" :key="route.MZT_MZTID">
|
|
<div v-if="route.MZT_Nazwa1 != undefined && ordersByRoute != undefined && ordersByRoute.has(route.MZT_Nazwa1)">
|
|
<div v-if="
|
|
//@ts-ignore
|
|
ordersByRoute.has(route.MZT_Nazwa1) && ordersByRoute?.get(route.MZT_Nazwa1) != undefined && ordersByRoute?.get(route.MZT_Nazwa1).length > 0"
|
|
style="page-break-after: always;">
|
|
<h1 class="is-size-2 is-fullwidth has-text-centered">{{
|
|
//@ts-ignore
|
|
route.MZT_Nazwa1 + ' ' + ordersByRoute?.get(route.MZT_Nazwa1)[0].MZN_DataDos
|
|
}}</h1>
|
|
|
|
<div v-if="!nipGrouped" v-for="order of ordersByRoute.get(route.MZT_Nazwa1)" :key="order.MZN_MZNID"
|
|
class="pb-4" style="display: block; page-break-inside: avoid;">
|
|
<p class="is-size-6 px-2">NIP {{order.MZN_PodNipE}}</p>
|
|
<p class="is-size-6 px-2">{{order.MZN_PodNazwa1 + order.MZN_PodNazwa2 + order.MZN_PodNazwa3}}</p>
|
|
<p class="is-size-5 px-2">ZAMÓWIENIE NR {{order.MZN_MZNID}} {{documnetType(order)}}</p>
|
|
<DataTable :value="order.products" class="mb-3" style="padding:0" scrollable>
|
|
<Column field="kod" header="Indeks" frozen></Column>
|
|
<Column field="nazwa" header="Nazwa"/>
|
|
<Column field="ilosc" header="Ilość"/>
|
|
<Column field="jm" header="JM"/>
|
|
<Column field="cena" header="Cena"/>
|
|
<Column field="suma" header="Suma"/>
|
|
</DataTable>
|
|
<div v-if="order.MZN_Uwagi != undefined">
|
|
<p class="is-size-6 px-2">Uwagi</p>
|
|
<p class="is-size-6 px-2">{{order.MZN_Uwagi}}</p>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="nipGrouped"
|
|
v-for="[nip, item] in Array.from(orderByRouteAndNipRef.get(route.MZT_Nazwa1) || new Map())"
|
|
:key="nip" class="pb-4" style="display: block; page-break-inside: avoid;">
|
|
|
|
<p class="is-size-5 px-2">NIP: {{ nip }}</p>
|
|
|
|
<p class="is-size-6 px-2">
|
|
{{ item.orders[0].MZN_PodNazwa1 + item.orders[0].MZN_PodNazwa2 + item.orders[0].MZN_PodNazwa3
|
|
}}</p>
|
|
<p class="is-size-5 px-2"
|
|
v-if="orderByRouteAndNipRef.get(route.MZT_Nazwa1)?.get(nip)?.orders?.length > 1 ">
|
|
ZAMÓWIENIA NR
|
|
<span
|
|
v-for="(orderByNip, index) in orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders">{{ orderByNip.MZN_MZNID
|
|
}}
|
|
<span
|
|
v-if="index !== orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders.length - 1">, </span>
|
|
</span>
|
|
<span>{{ifOneWZExists(orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders)}}</span>
|
|
</p>
|
|
<p class="is-size-5 px-2"
|
|
v-else>
|
|
ZAMÓWIENIE NR
|
|
<span
|
|
v-for="(orderByNip, index) in orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders">{{ orderByNip.MZN_MZNID
|
|
}} TYP ZAMÓWIENIA {{orderByNip.MZN_TypDokumentu}}
|
|
<span
|
|
v-if="index !== orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders.length - 1">, </span>
|
|
</span>
|
|
</p>
|
|
<DataTable :value="orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).products"
|
|
class="mb-3" style="padding:0" scrollable>
|
|
<Column field="MZE_TwrKod" header="Indeks" frozen></Column>
|
|
<Column field="MZE_TwrNazwa" header="Nazwa" />
|
|
<Column field="MZE_TwrIlosc" header="Ilość" />
|
|
<Column field="MZE_TwrJm" header="JM" />
|
|
<Column field="MZE_TwrCena" header="Cena" />
|
|
<Column field="suma" header="Suma" />
|
|
</DataTable>
|
|
<div >
|
|
<p v-if="hasNonEmptyUwagi(item)" class="is-size-6 px-2">Uwagi</p>
|
|
<p v-for="order in item.orders" class="is-size-6 px-2">{{ order.MZN_Uwagi }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<DataTable :value="summedProducts" class="mb-3" style="padding:0" scrollable id="printMe" v-else-if="orders != undefined && orders.length != 0 && isSummed">
|
|
<Column field="Twr_Kod" header="Indeks" frozen></Column>
|
|
<Column field="Twr_Nazwa" header="Nazwa"/>
|
|
<Column field="SummedQuantity" header="Ilość">
|
|
<template #body="slotProps">
|
|
<span>{{ slotProps.data.SummedQuantity.toFixed(2)}}</span>
|
|
</template>
|
|
</Column>
|
|
<Column field="Twr_JM" header="JM">
|
|
</Column>
|
|
<Column field="SummedPrice" header="Suma">
|
|
<template #body="slotProps">
|
|
<span>{{ slotProps.data.SummedPrice.toFixed(2)}}</span>
|
|
</template>
|
|
</Column>
|
|
</DataTable>
|
|
<div v-else class="is-flex is-justify-content-center is-flex-direction-row" style="height: 100%">
|
|
<p class="title is-1 has-text-centered" style="height: min-content; align-self: center;">Brak zamówień</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
@media screen and (min-width: 500px) {
|
|
.box {
|
|
--bulma-box-padding: 1.5rem;
|
|
}
|
|
}
|
|
@media screen and (max-width: 500px) {
|
|
.box {
|
|
--bulma-box-padding: 0.75rem;
|
|
}
|
|
}
|
|
.is-active {
|
|
background-color: #66d1ff;
|
|
color: white;
|
|
}
|
|
.blackBorder {
|
|
--bulma-table-cell-border-color : black;
|
|
}
|
|
|
|
.tableOverflow {
|
|
overflow-x: scroll;
|
|
display: block;
|
|
padding: 0;
|
|
}
|
|
|
|
.test {
|
|
padding: 0.75rem;
|
|
}
|
|
|
|
tr th:first-child{
|
|
border-top-left-radius: 0.75rem;
|
|
}
|
|
|
|
tr th:last-child{
|
|
border-top-right-radius: 0.75rem;
|
|
}
|
|
|
|
.p-datatable-scrollable {
|
|
border-top-right-radius: 0.75rem;
|
|
border-top-left-radius: 0.75rem;
|
|
}
|
|
|
|
.p-datatable-table-container {
|
|
border-top-right-radius: 0.75rem;
|
|
border-top-left-radius: 0.75rem;
|
|
}
|
|
|
|
table {
|
|
border-top-right-radius: 0.75rem;
|
|
border-top-left-radius: 0.75rem;
|
|
}
|
|
|
|
|
|
@media print {
|
|
.dashedBorder{
|
|
border-style: dotted;
|
|
border-color: lightgray;
|
|
}
|
|
}
|
|
</style> |