Files
mleczarnia-kuzma-zamowienia-ui/src/components/SummaryComponent.vue
2025-03-17 13:25:51 +01:00

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>