fixing error in session refresh, fixing error in common.js/buildDate, added enhanced information to error log detail page
This commit is contained in:
parent
5d775a7dda
commit
2975c8c3a1
8 changed files with 466 additions and 28 deletions
|
|
@ -33,7 +33,7 @@ const trackActivity = () => {
|
|||
}
|
||||
|
||||
|
||||
export const startSessionRefresh = () => {
|
||||
const startSessionRefresh = () => {
|
||||
|
||||
['mousedown', 'keypress', 'scroll', 'touchstart'].forEach(event => {
|
||||
document.addEventListener(event, trackActivity);
|
||||
|
|
@ -53,7 +53,7 @@ export const startSessionRefresh = () => {
|
|||
}, 10 * 60 * 1000);
|
||||
}
|
||||
|
||||
export const stopSessionRefresh = () => {
|
||||
const stopSessionRefresh = () => {
|
||||
if (sessionRefreshInterval) {
|
||||
clearInterval(sessionRefreshInterval);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,17 +161,20 @@ export class UrlSafeBase64 {
|
|||
}
|
||||
}
|
||||
|
||||
export const buildDate = (date, time) => {
|
||||
if (!date) return 'unkown';
|
||||
export const buildDate = (dateStr, time) => {
|
||||
if (!dateStr) return 'unknown';
|
||||
|
||||
const date = new Date(dateStr);
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
|
||||
if (!time) return `${year}/${month}/${day}`;
|
||||
const hours = time.getHours().toString().padStart(2, '0');
|
||||
const minutes = time.getMinutes().toString().padStart(2, '0');
|
||||
const seconds = time.getSeconds().toString().padStart(2, '0');
|
||||
|
||||
const hours = date.getHours().toString().padStart(2, '0');
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
const seconds = date.getSeconds().toString().padStart(2, '0');
|
||||
return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
|
||||
|
||||
}
|
||||
|
|
|
|||
91
src/frontend/src/components/layout/error/ErrorModal.vue
Normal file
91
src/frontend/src/components/layout/error/ErrorModal.vue
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
<template>
|
||||
|
||||
<div class="error-modal-container">
|
||||
<div class="trace-view-header">
|
||||
<h3 class="sub-header"> Error Details <br><span class="trace-view-message">{{ message }}</span>
|
||||
</h3>
|
||||
<icon-button icon="x" @click="$emit('close')"></icon-button>
|
||||
</div>
|
||||
<div class="trace-view-body">
|
||||
<tab-container :tabs="tabsError" class="tab-container" @tab-changed="handleTabChange">
|
||||
</tab-container>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import TabContainer from "@/components/UI/TabContainer.vue";
|
||||
import {markRaw} from "vue";
|
||||
import ErrorModalTraceView from "@/components/layout/error/ErrorModalTraceView.vue";
|
||||
import IconButton from "@/components/UI/IconButton.vue";
|
||||
import ErrorModalOverview from "@/components/layout/error/ErrorModalOverview.vue";
|
||||
import ErrorModalPiniaStore from "@/components/layout/error/ErrorModalPiniaStore.vue";
|
||||
|
||||
export default {
|
||||
name: "ErrorModal",
|
||||
components: {IconButton, TabContainer},
|
||||
emits: ["close"],
|
||||
props: {
|
||||
error: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tabsError() {
|
||||
return [
|
||||
{
|
||||
title: 'Overview',
|
||||
component: markRaw(ErrorModalOverview),
|
||||
props: {isSelected: false, error: this.error},
|
||||
},
|
||||
{
|
||||
title: 'Stack trace',
|
||||
component: markRaw(ErrorModalTraceView),
|
||||
props: {isSelected: false, error: this.error},
|
||||
},
|
||||
{
|
||||
title: 'Pinia store',
|
||||
component: markRaw(ErrorModalPiniaStore),
|
||||
props: {isSelected: false, error: this.error},
|
||||
},
|
||||
]
|
||||
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.error-modal-container {
|
||||
height: 90vh;
|
||||
width: 80vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden; /* Verhindert Overflow */
|
||||
}
|
||||
|
||||
.trace-view-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0; /* Header soll nicht schrumpfen */
|
||||
padding-bottom: 1.6rem; /* Optional: etwas Abstand */
|
||||
}
|
||||
|
||||
.trace-view-body {
|
||||
flex: 1; /* Nimmt den restlichen Platz ein */
|
||||
min-height: 0; /* Wichtig für Flexbox-Scrolling */
|
||||
overflow: hidden; /* Container selbst soll nicht scrollen */
|
||||
}
|
||||
|
||||
.tab-container {
|
||||
height: 100%; /* Füllt die trace-view-body aus */
|
||||
}
|
||||
|
||||
</style>
|
||||
252
src/frontend/src/components/layout/error/ErrorModalOverview.vue
Normal file
252
src/frontend/src/components/layout/error/ErrorModalOverview.vue
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
<template>
|
||||
<div class="error-overview-container">
|
||||
<div class="error-overview">
|
||||
<div class="error-section">
|
||||
<div class="error-label">Type</div>
|
||||
<div class="error-value">
|
||||
<basic-badge :variant="badgeVariant">{{ error.type || 'UNKNOWN' }}</basic-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error-section">
|
||||
<div class="error-label">Title</div>
|
||||
<div class="error-value">
|
||||
{{ error.title || 'No title provided' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error-section">
|
||||
<div class="error-label">Details</div>
|
||||
<div class="error-value">
|
||||
{{ error.message || 'No details available' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error-section">
|
||||
<div class="error-label">Exception</div>
|
||||
<div class="error-value">
|
||||
{{ error.code || 'N/A' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error-section">
|
||||
<div class="error-label">Timestamp</div>
|
||||
<div class="error-value">
|
||||
{{ formattedTimestamp }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error-section">
|
||||
<div class="error-label">User ID</div>
|
||||
<div class="error-value">
|
||||
{{ error.user_id || 'N/A' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error-section" v-if="errorLocation">
|
||||
<div class="error-label">File</div>
|
||||
<div class="error-value">
|
||||
{{ errorLocation }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error-section" v-if="errorMethod">
|
||||
<div class="error-label">Method</div>
|
||||
<div class="error-value">
|
||||
{{ errorMethod }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error-section" v-if="error.calculation_job_id">
|
||||
<div class="error-label">Calculation Job ID</div>
|
||||
<div class="error-value">
|
||||
{{ error.calculation_job_id }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="error-section" v-if="error.bulk_operation_id">
|
||||
<div class="error-label">Bulk Operation ID</div>
|
||||
<div class="error-value">
|
||||
{{ error.bulk_operation_id }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import BasicBadge from "@/components/UI/BasicBadge.vue";
|
||||
import {buildDate} from "@/common.js";
|
||||
|
||||
export default {
|
||||
name: "ErrorModalOverview",
|
||||
components: {BasicBadge},
|
||||
props: {
|
||||
isSelected: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
error: {
|
||||
type: Object,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
badgeVariant() {
|
||||
switch (this.error.type) {
|
||||
case "FRONTEND":
|
||||
return "primary";
|
||||
case "BACKEND":
|
||||
return "secondary";
|
||||
default:
|
||||
return "grey";
|
||||
}
|
||||
|
||||
},
|
||||
formattedTimestamp() {
|
||||
if (!this.error.timestamp) return 'N/A';
|
||||
|
||||
try {
|
||||
return buildDate(this.error.timestamp, true);
|
||||
} catch (e) {
|
||||
return this.error.timestamp;
|
||||
}
|
||||
},
|
||||
errorLocation() {
|
||||
if (!this.error.trace || this.error.trace.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const firstTrace = this.error.trace[0];
|
||||
|
||||
|
||||
return `${firstTrace.file}:${firstTrace.line}`;
|
||||
},
|
||||
errorMethod() {
|
||||
if (!this.error.trace || this.error.trace.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const firstTrace = this.error.trace[0];
|
||||
|
||||
return `${firstTrace.method}`;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
code {
|
||||
font-family: Roboto Mono, monospace;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.error-overview-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.error-overview {
|
||||
overflow: auto;
|
||||
padding: 1.6rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.6rem;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.error-section {
|
||||
display: grid;
|
||||
grid-template-columns: 20rem 1fr;
|
||||
align-items: center;
|
||||
padding: 1.6rem;
|
||||
gap: 0.6rem;
|
||||
border-bottom: 0.16rem solid #f3f4f6;
|
||||
}
|
||||
|
||||
.error-label {
|
||||
font-weight: 500;
|
||||
font-size: 1.4rem;
|
||||
color: #6B869C;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05rem;
|
||||
}
|
||||
|
||||
.error-value {
|
||||
color: #6b7280;
|
||||
font-size: 1.4rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.error-title {
|
||||
font-weight: 500;
|
||||
color: #d32f2f;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.error-code {
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
background-color: #f5f5f5;
|
||||
padding: 0.8rem 1.2rem;
|
||||
border-radius: 0.4rem;
|
||||
border: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.error-code code {
|
||||
color: #c7254e;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.error-location {
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
background-color: #f5f5f5;
|
||||
padding: 0.8rem 1.2rem;
|
||||
border-radius: 0.4rem;
|
||||
border: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.error-location code {
|
||||
color: #1976d2;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.type-badge {
|
||||
display: inline-block;
|
||||
padding: 0.6rem 1.2rem;
|
||||
border-radius: 0.4rem;
|
||||
font-weight: 600;
|
||||
font-size: 1.3rem;
|
||||
width: fit-content;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05rem;
|
||||
}
|
||||
|
||||
.type-backend {
|
||||
background-color: #ffebee;
|
||||
color: #c62828;
|
||||
border: 1px solid #ef5350;
|
||||
}
|
||||
|
||||
.type-frontend {
|
||||
background-color: #fff3e0;
|
||||
color: #e65100;
|
||||
border: 1px solid #ff9800;
|
||||
}
|
||||
|
||||
.type-unknown {
|
||||
background-color: #f5f5f5;
|
||||
color: #757575;
|
||||
border: 1px solid #bdbdbd;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<template>
|
||||
<div v-if="piniaData" class="pinia-store-viewer">
|
||||
<div class="store-content">
|
||||
<pre class="json-display">{{ formattedPiniaData }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="no-data">
|
||||
<p>No pinia data</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
import logger from "@/logger.js";
|
||||
|
||||
export default {
|
||||
name: "ErrorModalPiniaStore",
|
||||
props: {
|
||||
error: {
|
||||
type: Object,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
piniaData() {
|
||||
if (!this.error?.pinia) return null;
|
||||
|
||||
if (typeof this.error.pinia === 'object') {
|
||||
return this.error.pinia;
|
||||
}
|
||||
|
||||
if (typeof this.error.pinia === 'string') {
|
||||
try {
|
||||
return JSON.parse(this.error.pinia);
|
||||
} catch (e) {
|
||||
logger.error('Error parsing error.pinia:', e);
|
||||
return { raw: this.error.pinia };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
formattedPiniaData() {
|
||||
if (!this.piniaData) return '';
|
||||
return JSON.stringify(this.piniaData, null, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Cal+Sans&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap');
|
||||
|
||||
.pinia-store-viewer {
|
||||
margin-top: 1rem;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.75rem;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
.store-content {
|
||||
height: 100%
|
||||
}
|
||||
|
||||
.json-display {
|
||||
margin: 0;
|
||||
font-family: 'Roboto mono', monospace;
|
||||
font-size: 1.2rem;
|
||||
flex: 1;
|
||||
padding: 0 1.6rem;
|
||||
color: #002F54;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
height: 100%
|
||||
}
|
||||
|
||||
.no-data {
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
color: #6b7280;
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,9 +2,8 @@
|
|||
|
||||
<div class="trace-view-container" :class="trace ? '' : 'trace-view-container--no-trace'">
|
||||
<div class="trace-view-header">
|
||||
<h3 class="sub-header">{{ title }} <br><span class="trace-view-message">{{ message }}</span>
|
||||
</h3>
|
||||
<icon-button icon="x" @click="$emit('close')"></icon-button>
|
||||
<div class="trace-view-exception">{{ title }} - {{ message }}</div>
|
||||
|
||||
</div>
|
||||
<div v-if="trace" class="trace-view">
|
||||
<div class="trace-view-exception">{{ exception }}</div>
|
||||
|
|
@ -73,7 +72,6 @@ export default {
|
|||
@import url('https://fonts.googleapis.com/css2?family=Cal+Sans&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap');
|
||||
|
||||
.highlight-trace-item {
|
||||
|
||||
color: #002F54;
|
||||
background-color: #F2F2F2;
|
||||
padding-left: 1.6rem;
|
||||
|
|
@ -89,12 +87,16 @@ export default {
|
|||
font-size: 1.2rem;
|
||||
flex: 1;
|
||||
padding: 0 1.6rem;
|
||||
min-height: 0; /* Wichtig für Flexbox-Scrolling */
|
||||
}
|
||||
|
||||
.trace-view-header {
|
||||
font-family: Roboto Mono, monospace;
|
||||
font-size: 1.2rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0; /* Header soll nicht schrumpfen */
|
||||
}
|
||||
|
||||
.trace-view-message {
|
||||
|
|
@ -107,16 +109,16 @@ export default {
|
|||
}
|
||||
|
||||
.trace-view-exception {
|
||||
|
||||
|
||||
/* Dein Styling hier */
|
||||
}
|
||||
|
||||
.trace-view-container {
|
||||
height: 90vh;
|
||||
width: 80vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.6rem;
|
||||
height: 100%; /* Parent-Höhe ausfüllen */
|
||||
width: 100%; /* Parent-Breite ausfüllen */
|
||||
overflow: hidden; /* Container selbst soll nicht scrollen */
|
||||
}
|
||||
|
||||
.trace-view-container--no-trace {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<modal :state="showModal">
|
||||
<error-log-modal :error="error" @close="showModal = false"></error-log-modal>
|
||||
<error-modal :error="error" @close="showModal = false"></error-modal>
|
||||
</modal>
|
||||
<table-view :columns="columns" :data-source="fetchData" :page="pagination.page" :page-size="pageSize" :page-count="pagination.pageCount" :total-count="pagination.totalCount" @row-click="showDetails" :mouse-over="true"></table-view>
|
||||
|
||||
|
|
@ -16,18 +16,18 @@ import {useErrorLogStore} from "@/store/errorLog.js";
|
|||
import {mapStores} from "pinia";
|
||||
import Modal from "@/components/UI/Modal.vue";
|
||||
import TraceView from "@/components/layout/TraceView.vue";
|
||||
import ErrorLogModal from "@/components/layout/ErrorLogModal.vue";
|
||||
import {buildDate} from "@/common.js";
|
||||
import ErrorModal from "@/components/layout/error/ErrorModal.vue";
|
||||
|
||||
export default {
|
||||
name: "ErrorLog",
|
||||
components: {ErrorLogModal, TraceView, Modal, TableView},
|
||||
components: {ErrorModal, TraceView, Modal, TableView},
|
||||
data() {
|
||||
return {
|
||||
showModal: false,
|
||||
error: null,
|
||||
pageSize: 20,
|
||||
pagination: { page: 1, pageCount: 10, totalCount: 1 },
|
||||
pagination: { page: 1, pageCount: 1, totalCount: 1 },
|
||||
columns: [
|
||||
{key: 'type', label: 'Type', align: "center", iconResolver: (rawValue, item) => {
|
||||
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@ public class HandlingCostCalculationService {
|
|||
this.shippingFrequencyCalculationService = shippingFrequencyCalculationService;
|
||||
}
|
||||
|
||||
public HandlingResult doCalculation(Integer setId, Premise premise, Destination destination, Boolean addRepackingCosts) {
|
||||
public HandlingResult doCalculation(Integer setId, Premise premise, Destination destination, Boolean addRepackingAndDisposalCost) {
|
||||
|
||||
var hu = premiseToHuService.createHuFromPremise(premise);
|
||||
return (LoadCarrierType.SLC == hu.getLoadCarrierType() ? getSLCCost(setId, destination, hu, hu.getLoadCarrierType(), addRepackingCosts) : getLLCCost(setId, destination, hu, hu.getLoadCarrierType(), addRepackingCosts));
|
||||
return (LoadCarrierType.SLC == hu.getLoadCarrierType() ? getSLCCost(setId, destination, hu, hu.getLoadCarrierType(), addRepackingAndDisposalCost) : getLLCCost(setId, destination, hu, hu.getLoadCarrierType(), addRepackingAndDisposalCost));
|
||||
}
|
||||
|
||||
private HandlingResult getSLCCost(Integer setId, Destination destination, PackagingDimension hu, LoadCarrierType loadCarrierType, boolean addRepackingCosts) {
|
||||
private HandlingResult getSLCCost(Integer setId, Destination destination, PackagingDimension hu, LoadCarrierType loadCarrierType, boolean addRepackingAndDisposalCost) {
|
||||
|
||||
var destinationHandling = destination.getHandlingCost();
|
||||
var destinationDisposal = destination.getDisposalCost();
|
||||
|
|
@ -46,16 +46,16 @@ public class HandlingCostCalculationService {
|
|||
BigDecimal handling = destinationHandling != null ? destinationHandling : BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_HANDLING, setId).orElseThrow().getCurrentValue()));
|
||||
BigDecimal release = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_RELEASE, setId).orElseThrow().getCurrentValue()));
|
||||
BigDecimal dispatch = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_DISPATCH, setId).orElseThrow().getCurrentValue()));
|
||||
BigDecimal disposal = destinationDisposal != null ? destinationDisposal : BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.DISPOSAL, setId).orElseThrow().getCurrentValue()));
|
||||
BigDecimal disposal = destinationDisposal != null ? destinationDisposal : (addRepackingAndDisposalCost ? BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.DISPOSAL, setId).orElseThrow().getCurrentValue())) : BigDecimal.ZERO);
|
||||
|
||||
BigDecimal wageFactor = BigDecimal.valueOf(Double.parseDouble(countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.WAGE, setId, destination.getCountryId()).orElseThrow().getCurrentValue()));
|
||||
BigDecimal booking = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.BOOKING_KLT, setId).orElseThrow().getCurrentValue()));
|
||||
|
||||
return new HandlingResult(LoadCarrierType.SLC,
|
||||
getRepackingCost(setId, hu, loadCarrierType, addRepackingCosts, destinationRepacking).multiply(huAnnualAmount),
|
||||
getRepackingCost(setId, hu, loadCarrierType, addRepackingAndDisposalCost, destinationRepacking).multiply(huAnnualAmount),
|
||||
handling.multiply(huAnnualAmount),
|
||||
destinationDisposal == null ? BigDecimal.ZERO : (disposal.multiply(huAnnualAmount)), //TODO: disposal SLC, ignore?
|
||||
huAnnualAmount.multiply((handling.add(booking).add(release).add(dispatch).add(getRepackingCost(setId, hu, loadCarrierType, addRepackingCosts, destinationRepacking)))).multiply(wageFactor));
|
||||
huAnnualAmount.multiply((handling.add(booking).add(release).add(dispatch).add(getRepackingCost(setId, hu, loadCarrierType, addRepackingAndDisposalCost, destinationRepacking)))).multiply(wageFactor));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ public class HandlingCostCalculationService {
|
|||
}
|
||||
|
||||
|
||||
private HandlingResult getLLCCost(Integer setId, Destination destination, PackagingDimension hu, LoadCarrierType type, boolean addRepackingCosts) {
|
||||
private HandlingResult getLLCCost(Integer setId, Destination destination, PackagingDimension hu, LoadCarrierType type, boolean addRepackingAndDisposalCost) {
|
||||
|
||||
var destinationHandling = destination.getHandlingCost();
|
||||
var destinationDisposal = destination.getDisposalCost();
|
||||
|
|
@ -87,12 +87,12 @@ public class HandlingCostCalculationService {
|
|||
BigDecimal handling = destinationHandling != null ? destinationHandling : BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_HANDLING, setId).orElseThrow().getCurrentValue()));
|
||||
BigDecimal release = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_RELEASE, setId).orElseThrow().getCurrentValue()));
|
||||
BigDecimal dispatch = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_DISPATCH, setId).orElseThrow().getCurrentValue()));
|
||||
BigDecimal disposal = destinationDisposal != null ? destinationDisposal : BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.DISPOSAL, setId).orElseThrow().getCurrentValue()));
|
||||
BigDecimal disposal = destinationDisposal != null ? destinationDisposal : (addRepackingAndDisposalCost ? BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.DISPOSAL, setId).orElseThrow().getCurrentValue())) : BigDecimal.ZERO);
|
||||
|
||||
BigDecimal wageFactor = BigDecimal.valueOf(Double.parseDouble(countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.WAGE, setId, destination.getCountryId()).orElseThrow().getCurrentValue()));
|
||||
BigDecimal booking = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.BOOKING, setId).orElseThrow().getCurrentValue()));
|
||||
|
||||
var annualRepacking = getRepackingCost(setId, hu, type, addRepackingCosts, destinationRepacking).multiply(wageFactor).multiply( huAnnualAmount);
|
||||
var annualRepacking = getRepackingCost(setId, hu, type, addRepackingAndDisposalCost, destinationRepacking).multiply(wageFactor).multiply( huAnnualAmount);
|
||||
var annualHandling = ((handling.add(dispatch).add(release)).multiply(wageFactor).multiply(huAnnualAmount)).add(booking.multiply(BigDecimal.valueOf(shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount.doubleValue()))));
|
||||
var annualDisposal = (disposal.multiply(huAnnualAmount));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue