Integrated tariff rate calculations and customs API:
- **Backend**: Introduced `EUTaxationApiService` for TARIC data retrieval and integrated tariff rate lookup functionality. Added supporting DTOs and updated services to handle custom measures and updated logic for material and supplier changes. - **Frontend**: Enhanced mass and single edit calculation components to include tariff rate lookup functionality and warnings. Introduced `useCustomsStore` for state management of customs data. - **Database**: Added `nomenclature` table for storing HS code-related information. - **Other**: Configured SOAP client for TARIC API and added logging for debugging.
This commit is contained in:
parent
be1ef5091b
commit
ce6b8dd9b0
58 changed files with 19749 additions and 51 deletions
34
pom.xml
34
pom.xml
|
|
@ -49,6 +49,11 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web-services</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.azure.spring</groupId>
|
||||
<artifactId>spring-cloud-azure-starter</artifactId>
|
||||
|
|
@ -162,6 +167,15 @@
|
|||
<artifactId>flyway-mysql</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>4.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
|
|
@ -179,6 +193,26 @@
|
|||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jvnet.jaxb</groupId>
|
||||
<artifactId>jaxb-maven-plugin</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
|
||||
<schemaIncludes>
|
||||
<include>*.wsdl</include>
|
||||
</schemaIncludes>
|
||||
<generatePackage>eu.europa.ec.taxation.taric.client</generatePackage>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.2.5</version>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<div class="edit-calculation-cell-line">{{ premise.material.part_number }}</div>
|
||||
<div class="edit-calculation-cell-line edit-calculation-cell-subline" v-if="premise.hs_code">
|
||||
HS Code:
|
||||
{{ premise.material.hs_code }}
|
||||
{{ premise.hs_code }}
|
||||
</div>
|
||||
<div class="edit-calculation-cell-line edit-calculation-cell-subline"
|
||||
v-if="premise.tariff_rate && premise.tariff_rate > 0">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<div class="container" :class="{ 'responsive': responsive }" @focusout="focusLost">
|
||||
|
||||
|
||||
<div class="field-group" v-if="!hideDescription">
|
||||
<div class="caption-column">Part number</div>
|
||||
<div class="input-column">
|
||||
|
|
@ -19,24 +20,61 @@
|
|||
<div class="caption-column">HS code</div>
|
||||
<div class="input-column">
|
||||
<div class="hs-code-container">
|
||||
<autosuggest-searchbar :activate-watcher="true" :fetch-suggestions="fetchHsCode" :initial-value="hsCode"
|
||||
<autosuggest-searchbar ref="hsCodeSearchbar" :activate-watcher="true" :fetch-suggestions="fetchHsCode"
|
||||
:initial-value="hsCode"
|
||||
@selected="hsCodeSelected" @blur="hsCodeChanged"
|
||||
placeholder="Find hs code" no-results-text="Not found."></autosuggest-searchbar>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field-group">
|
||||
|
||||
|
||||
|
||||
<div class="field-group" :class="{ 'disabled': !disableTariff }">
|
||||
<div class="caption-column">Tariff rate [%]</div>
|
||||
<div class="input-column">
|
||||
<div class="text-container input-field-tariffrate">
|
||||
<input ref="tariffRateInput" :value="tariffRatePercent" @blur="validateTariffRate"
|
||||
<input ref="tariffRateInput" :value="tariffRatePercent" @blur="validateTariffRateEvent"
|
||||
class="input-field"
|
||||
:disabled="!disableTariff"
|
||||
autocomplete="off"/>
|
||||
<ph-warning v-if="showTariffWarning" size="18" class="warning-icon"></ph-warning>
|
||||
<div v-if="showTariffWarning" class="tariff-rate-info">
|
||||
<div>
|
||||
<div class="tariff-rate-info-header">
|
||||
<ph-warning size="24"></ph-warning>
|
||||
<div v-if="tariffIsDefault">
|
||||
<div>Using default value</div>
|
||||
<div class="tariff-rate-info-headerbox">Automatic determination failed</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div>More than one custom measure found</div>
|
||||
<div class="tariff-rate-info-headerbox">Please review carefully</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tariff-rate-info-container">
|
||||
<template v-for="measure in measures" :key="measure.code">
|
||||
<div class="tariff-rate-info-cell-measure">Measure {{ measure.code }}</div>
|
||||
<div>Regulation {{ measure.regulation }}</div>
|
||||
<div class="tariff-rate-info-cell-tariffrate">{{ measure.tariffRate }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field-group" v-if="showCheckbox">
|
||||
<div class="caption-column"></div>
|
||||
<div class="input-column">
|
||||
<checkbox :checked="false" @checkbox-changed="checkBoxChanged">tariff lookup on close</checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -48,21 +86,24 @@ import Flag from "@/components/UI/Flag.vue";
|
|||
import InputField from "@/components/UI/InputField.vue";
|
||||
import AutosuggestSearchbar from "@/components/UI/AutoSuggestSearchBar.vue";
|
||||
import ModalDialog from "@/components/UI/ModalDialog.vue";
|
||||
import {PhArrowCounterClockwise} from "@phosphor-icons/vue";
|
||||
import {PhArrowCounterClockwise, PhWarning} from "@phosphor-icons/vue";
|
||||
import {useMaterialStore} from "@/store/material.js";
|
||||
import {mapStores} from "pinia";
|
||||
import {parseNumberFromString} from "@/common.js";
|
||||
import Modal from "@/components/UI/Modal.vue";
|
||||
import SelectMaterial from "@/components/layout/material/SelectMaterial.vue";
|
||||
import {useCustomsStore} from "@/store/customs.js";
|
||||
import Checkbox from "@/components/UI/Checkbox.vue";
|
||||
|
||||
export default {
|
||||
name: "MaterialEdit",
|
||||
components: {
|
||||
Checkbox,
|
||||
PhWarning,
|
||||
SelectMaterial,
|
||||
Modal, PhArrowCounterClockwise, ModalDialog, AutosuggestSearchbar, InputField, Flag, IconButton
|
||||
},
|
||||
emits: ["update:tariffRate", "updateMaterial", "update:partNumber", "update:hsCode", "save", "close"],
|
||||
emits: ["update:tariffRate", "updateMaterial", "update:partNumber", "update:hsCode", "save", "close", "startLookup"],
|
||||
props: {
|
||||
description: {
|
||||
type: [String, null],
|
||||
|
|
@ -72,6 +113,10 @@ export default {
|
|||
required: true,
|
||||
validator: (value) => value === null || typeof value === 'string'
|
||||
},
|
||||
countryId: {
|
||||
required: true,
|
||||
validator: (value) => value === null || typeof value === 'number'
|
||||
},
|
||||
tariffRate: {
|
||||
required: true,
|
||||
validator: (value) => value === null || typeof value === 'number'
|
||||
|
|
@ -93,11 +138,29 @@ export default {
|
|||
...mapStores(useMaterialStore, useCustomsStore),
|
||||
tariffRatePercent() {
|
||||
return ((this.tariffRate ?? null) !== null) ? (this.tariffRate * 100).toFixed(2) : '';
|
||||
},
|
||||
showTariffWarning() {
|
||||
return this.customsStore.showWarning(this.countryId);
|
||||
},
|
||||
tariffIsDefault() {
|
||||
return this.tariffInfo?.default ?? false;
|
||||
},
|
||||
tariffInfo() {
|
||||
return this.customsStore.findByCountryId(this.countryId);
|
||||
},
|
||||
measures() {
|
||||
return this.tariffInfo.measures;
|
||||
},
|
||||
showCheckbox() {
|
||||
return this.countryId === null;
|
||||
},
|
||||
disableTariff() {
|
||||
return !this.doLookup;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
doLookup: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
|
@ -115,22 +178,54 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
validateTariffRate(event) {
|
||||
const percentValue = parseNumberFromString(event.target.value, 2, true);
|
||||
validateTariffRateEvent(event) {
|
||||
event.target.value = this.validateTariffRate(event.target.value);
|
||||
},
|
||||
validateTariffRate(value) {
|
||||
const percentValue = parseNumberFromString(value, 2, true);
|
||||
|
||||
const validatedPercent = (percentValue === null) ? null : Math.max(0, Math.min(999.99, percentValue));
|
||||
const validatedDecimal = (validatedPercent === null) ? null : validatedPercent / 100;
|
||||
|
||||
if (validatedDecimal !== this.tariffRate) {
|
||||
this.$emit('update:tariffRate', validatedDecimal);
|
||||
this.$emit('update:tariffRate', this.roundNumber(validatedDecimal, 4));
|
||||
}
|
||||
|
||||
event.target.value = validatedPercent === null ? null : validatedPercent.toFixed(2);
|
||||
return validatedPercent === null ? null : validatedPercent.toFixed(2);
|
||||
|
||||
},
|
||||
roundNumber(number, digits) {
|
||||
const multiple = Math.pow(10, digits);
|
||||
return Math.round(number * multiple) / multiple;
|
||||
},
|
||||
async fetchHsCode(query) {
|
||||
const hsCodeQuery = {searchTerm: query};
|
||||
await this.customsStore.setQuery(hsCodeQuery);
|
||||
return this.customsStore.hsCodes;
|
||||
return await this.customsStore.findHsCode(query);
|
||||
},
|
||||
hsCodeChanged() {
|
||||
const currentValue = this.$refs.hsCodeSearchbar.searchQuery;
|
||||
this.$emit("update:hsCode", currentValue);
|
||||
},
|
||||
async hsCodeSelected(hsCode) {
|
||||
let save = false;
|
||||
|
||||
if (hsCode !== this.hsCode) {
|
||||
this.$emit("update:hsCode", hsCode)
|
||||
save = true;
|
||||
}
|
||||
|
||||
if ((this.countryId ?? null) !== null) {
|
||||
const query = {hsCode: hsCode, countryIds: [this.countryId]};
|
||||
await this.customsStore.findTariffRate(query);
|
||||
this.validateTariffRate((this.customsStore.findByCountryId(this.countryId)?.value ?? 0.03) * 100);
|
||||
save = true;
|
||||
}
|
||||
|
||||
if (save)
|
||||
this.$emit('save', 'material');
|
||||
},
|
||||
checkBoxChanged(checked) {
|
||||
this.doLookup = checked
|
||||
this.$emit('startLookup', checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -139,11 +234,42 @@ export default {
|
|||
|
||||
<style scoped>
|
||||
|
||||
|
||||
.field-group.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.field-group.disabled .caption-column,
|
||||
.field-group.disabled .input-field {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.field-group.disabled .text-container {
|
||||
background-color: #f3f4f6;
|
||||
cursor: not-allowed;
|
||||
border-color: #f3f4f6;
|
||||
}
|
||||
|
||||
.input-field:disabled {
|
||||
cursor: not-allowed;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.warning-icon {
|
||||
color: #002F54;
|
||||
}
|
||||
|
||||
.text-container:hover .warning-icon {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.hs-code-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.8rem;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.container {
|
||||
|
|
@ -165,7 +291,7 @@ export default {
|
|||
minmax(auto, max-content) /* Spalte 5: Label */
|
||||
minmax(120px, 1fr) /* Spalte 6: Input */
|
||||
minmax(auto, max-content) /* Spalte 7: Label */
|
||||
minmax(120px, 1fr); /* Spalte 8: Input/Dropdown */
|
||||
minmax(120px, 1fr); /* Spalte 8: Input/Dropdown */
|
||||
grid-template-rows: auto;
|
||||
gap: 1.2rem 1rem;
|
||||
align-items: center;
|
||||
|
|
@ -230,12 +356,15 @@ export default {
|
|||
border: 0.2rem solid #E3EDFF;
|
||||
transition: all 0.1s ease;
|
||||
flex: 1 1 auto;
|
||||
position: relative; /* Hinzufügen */
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.text-container:hover {
|
||||
background: #EEF4FF;
|
||||
border: 0.2rem solid #8DB3FE;
|
||||
transform: scale(1.01);
|
||||
|
||||
}
|
||||
|
||||
.caption-column {
|
||||
|
|
@ -250,6 +379,74 @@ export default {
|
|||
.input-field-tariffrate {
|
||||
min-width: 20rem;
|
||||
flex: 0 1 10rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tariff-rate-info {
|
||||
position: absolute;
|
||||
top: 3rem;
|
||||
left: -3rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 1.2rem;
|
||||
z-index: 5000;
|
||||
background-color: #fff;
|
||||
border-radius: 0.8rem;
|
||||
border: 0.1rem solid #E3EDFF;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
padding: 1.6rem 2.4rem;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
min-width: 40rem;
|
||||
}
|
||||
|
||||
.input-field-tariffrate:hover .tariff-rate-info {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
transition: opacity 0.5s ease, transform 0.5s ease;
|
||||
}
|
||||
|
||||
.tariff-rate-info-cell-measure {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
color: #002F54;
|
||||
justify-self: flex-end;
|
||||
}
|
||||
|
||||
.tariff-rate-info-cell-tariffrate {
|
||||
justify-self: flex-end;
|
||||
}
|
||||
|
||||
.tariff-rate-info-container {
|
||||
margin-top: 2.4rem;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr 1fr;
|
||||
gap: 0.8rem;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tariff-rate-info-headerbox {
|
||||
color: #002F54;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tariff-rate-info-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.8rem;
|
||||
justify-content: flex-start;
|
||||
font-size: 1.4rem;
|
||||
font-weight: 500;
|
||||
background-color: #c3cfdf;
|
||||
color: #002F54;
|
||||
border-radius: 0.8rem;
|
||||
padding: 1.6rem;
|
||||
margin-bottom: 1.6rem;
|
||||
}
|
||||
|
||||
/* Optimierung für kleinere Bildschirme unter 1500px - nur wenn responsive aktiviert ist */
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
<modal :z-index="3000" :state="showProcessingModal">
|
||||
<div class="edit-calculation-spinner-container space-around">
|
||||
<spinner></spinner>
|
||||
<span>{{ processingMessage }}</span>
|
||||
<span>{{ shownProcessingMessage }}</span>
|
||||
</div>
|
||||
</modal>
|
||||
|
||||
|
|
@ -86,8 +86,10 @@
|
|||
v-model:mixable="componentProps.mixable"
|
||||
v-model:stackable="componentProps.stackable"
|
||||
v-model:hideDescription="componentProps.hideDescription"
|
||||
:countryId=null
|
||||
:responsive="false"
|
||||
@close="closeEditModalAction('cancel')"
|
||||
@start-lookup="doLookupOnClose"
|
||||
|
||||
>
|
||||
</component>
|
||||
|
|
@ -122,6 +124,7 @@ import DestinationListView from "@/components/layout/edit/DestinationListView.vu
|
|||
import SelectNode from "@/components/layout/node/SelectNode.vue";
|
||||
import Toast from "@/components/UI/Toast.vue";
|
||||
import logger from "@/logger.js";
|
||||
import {useCustomsStore} from "@/store/customs.js";
|
||||
|
||||
|
||||
const COMPONENT_TYPES = {
|
||||
|
|
@ -146,7 +149,7 @@ export default {
|
|||
BasicButton
|
||||
},
|
||||
computed: {
|
||||
...mapStores(usePremiseEditStore),
|
||||
...mapStores(usePremiseEditStore, useCustomsStore),
|
||||
hasSelection() {
|
||||
if (this.premiseEditStore.isLoading || this.premiseEditStore.selectedLoading) {
|
||||
return false;
|
||||
|
|
@ -190,7 +193,14 @@ export default {
|
|||
return this.modalType ? this.componentsData[this.modalType] : null;
|
||||
},
|
||||
showProcessingModal() {
|
||||
return this.premiseEditStore.showProcessingModal || this.showCalculationModal;
|
||||
return this.premiseEditStore.showProcessingModal || this.showCalculationModal || this.customsStore.loadingTariff;
|
||||
},
|
||||
shownProcessingMessage() {
|
||||
if(this.customsStore.loadingTariff)
|
||||
return "Looking up tariff rate ..."
|
||||
|
||||
return this.processingMessage;
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
|
@ -201,6 +211,7 @@ export default {
|
|||
|
||||
data() {
|
||||
return {
|
||||
doLookup: false,
|
||||
ids: [],
|
||||
bulkQuery: null,
|
||||
modalType: null,
|
||||
|
|
@ -225,7 +236,7 @@ export default {
|
|||
editIds: null,
|
||||
dataSourceId: null,
|
||||
processingMessage: "Please wait. Calculating ...",
|
||||
showCalculationModal: false
|
||||
showCalculationModal: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -290,6 +301,9 @@ export default {
|
|||
logger.info("open modal", massEdit, this.modalType, this.editIds, this.dataSourceId)
|
||||
|
||||
},
|
||||
doLookupOnClose(doLookup) {
|
||||
this.doLookup = doLookup;
|
||||
},
|
||||
async closeEditModalAction(action) {
|
||||
if (this.modalType === "destinations") {
|
||||
if (action === "accept") {
|
||||
|
|
@ -305,7 +319,11 @@ export default {
|
|||
await this.premiseEditStore.batchUpdatePrice(this.editIds, props);
|
||||
break;
|
||||
case "material":
|
||||
await this.premiseEditStore.batchUpdateMaterial(this.editIds, props);
|
||||
let tariffRates = null;
|
||||
if (this.doLookup) {
|
||||
tariffRates = await this.tariffLookUp(props.hsCode);
|
||||
}
|
||||
await this.premiseEditStore.batchUpdateMaterial(this.editIds, props, tariffRates);
|
||||
break;
|
||||
case "packaging":
|
||||
await this.premiseEditStore.batchUpdatePackaging(this.editIds, props);
|
||||
|
|
@ -317,6 +335,23 @@ export default {
|
|||
this.fillData(this.modalType);
|
||||
this.modalType = null;
|
||||
},
|
||||
async tariffLookUp(hsCode) {
|
||||
|
||||
const countryIds = this.premiseEditStore.getCountryIdByPremiseIds(this.editIds);
|
||||
|
||||
const query = {hsCode: hsCode, countryIds: [...new Set(Array.from(countryIds.values()))]};
|
||||
const tariffRates = await this.customsStore.findTariffRate(query);
|
||||
|
||||
const found = new Map();
|
||||
for(const editId of this.editIds) {
|
||||
const countryId = countryIds.get(editId);
|
||||
|
||||
|
||||
found.set(editId, tariffRates.find(rate => rate.countryId === countryId).value);
|
||||
}
|
||||
|
||||
return found;
|
||||
},
|
||||
fillData(type, id = -1, hideDescription = false) {
|
||||
|
||||
if (id === -1) {
|
||||
|
|
@ -360,7 +395,7 @@ export default {
|
|||
|
||||
this.componentsData.material.props = {
|
||||
partNumber: premise.material.part_number,
|
||||
hsCode: premise.material.hs_code,
|
||||
hsCode: premise.hs_code,
|
||||
tariffRate: premise.tariff_rate ?? 0.00,
|
||||
description: premise.material.name ?? "",
|
||||
hideDescription: hideDescription
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
:id="premise.material.id"
|
||||
v-model:hs-code="premise.hs_code"
|
||||
v-model:tariff-rate="premise.tariff_rate"
|
||||
v-model:country-id="premise.supplier.country.id"
|
||||
@update-material="updateMaterial"
|
||||
@save="save"></material-edit>
|
||||
</box>
|
||||
|
|
@ -89,7 +90,7 @@
|
|||
<modal :z-index="3000" :state="showProcessingModal">
|
||||
<div class="edit-calculation-spinner-container space-around">
|
||||
<spinner></spinner>
|
||||
<span>{{ processingMessage }}</span>
|
||||
<span>{{ shownProcessingMessage }}</span>
|
||||
</div>
|
||||
</modal>
|
||||
|
||||
|
|
@ -115,6 +116,7 @@ import TraceView from "@/components/layout/TraceView.vue";
|
|||
import IconButton from "@/components/UI/IconButton.vue";
|
||||
import Toast from "@/components/UI/Toast.vue";
|
||||
import {UrlSafeBase64} from "@/common.js";
|
||||
import {useCustomsStore} from "@/store/customs.js";
|
||||
|
||||
export default {
|
||||
name: "SingleEdit",
|
||||
|
|
@ -143,7 +145,7 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
...mapStores(usePremiseEditStore),
|
||||
...mapStores(usePremiseEditStore, useCustomsStore),
|
||||
premise() {
|
||||
return this.premiseEditStore.singleSelectedPremise;
|
||||
},
|
||||
|
|
@ -151,8 +153,15 @@ export default {
|
|||
return this.bulkEditQuery !== null;
|
||||
},
|
||||
showProcessingModal() {
|
||||
return this.premiseEditStore.showProcessingModal || this.showCalculationModal;
|
||||
return this.premiseEditStore.showProcessingModal || this.showCalculationModal || this.customsStore.loadingTariff;
|
||||
},
|
||||
shownProcessingMessage() {
|
||||
if(this.customsStore.loadingTariff)
|
||||
return "Looking up tariff rate ..."
|
||||
|
||||
return this.processingMessage;
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,53 @@
|
|||
import {defineStore} from 'pinia'
|
||||
import {config} from '@/config'
|
||||
import performRequest from "@/backend.js";
|
||||
|
||||
export const useCustomsStore = defineStore('customs', {
|
||||
state() {
|
||||
return {
|
||||
hsCodes: [],
|
||||
query: null
|
||||
tariffInfo: null,
|
||||
loadingTariff: false,
|
||||
|
||||
}
|
||||
},
|
||||
getters: {},
|
||||
actions: {
|
||||
async setQuery(query) {
|
||||
this.query = query;
|
||||
getters: {
|
||||
showWarning(state) {
|
||||
return function (countryId) {
|
||||
const info = state.tariffInfo?.find(t => t.countryId === countryId);
|
||||
|
||||
if ((info ?? null) !== null) {
|
||||
return info.default || info.measures?.length > 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
async queryCustomApi(query) {
|
||||
findByCountryId(state) {
|
||||
return function (countryId) {
|
||||
return state.tariffInfo?.find(t => t.countryId === countryId);
|
||||
}
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async findTariffRate(query) {
|
||||
this.loadingTariff = true;
|
||||
const url = `${config.backendUrl}/customs?hs_code=${query.hsCode}&country_ids=${query.countryIds}`;
|
||||
const resp = await performRequest(this, 'GET', url, null).catch(() => {
|
||||
this.tariffInfo = null;
|
||||
this.loadingTariff = false;
|
||||
})
|
||||
this.tariffInfo = resp.data;
|
||||
|
||||
this.loadingTariff = false;
|
||||
return this.tariffInfo;
|
||||
},
|
||||
async findHsCode(query) {
|
||||
|
||||
const url = `${config.backendUrl}/customs/search?hs_code=${query}`;
|
||||
const resp = await performRequest(this, 'GET', url, null);
|
||||
this.hsCodes = resp.data;
|
||||
return this.hsCodes;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,28 @@ export const usePremiseEditStore = defineStore('premiseEdit', {
|
|||
},
|
||||
getters: {
|
||||
|
||||
getCountryIdByPremiseIds(state) {
|
||||
return function (ids) {
|
||||
if (state.loading) {
|
||||
if (state.throwsException)
|
||||
throw new Error("Premises are accessed while still loading.");
|
||||
return null;
|
||||
}
|
||||
|
||||
const premiss = state.premisses?.filter(p => ids.some(id => id === p.id));
|
||||
|
||||
const premiseCountryMap = new Map();
|
||||
premiss?.forEach(premise => {
|
||||
premiseCountryMap.set(premise.id, premise.supplier?.country?.id);
|
||||
});
|
||||
|
||||
return premiseCountryMap;
|
||||
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the ids of all premises.
|
||||
* @param state
|
||||
|
|
@ -266,23 +288,24 @@ export const usePremiseEditStore = defineStore('premiseEdit', {
|
|||
|
||||
return await this.savePrice(ids, priceData);
|
||||
},
|
||||
async batchUpdateMaterial(ids, materialData) {
|
||||
async batchUpdateMaterial(ids, materialData, tariffRates = null) {
|
||||
const updatedPremises = this.premisses.map(p => {
|
||||
if (ids.includes(p.id)) {
|
||||
return {
|
||||
...p,
|
||||
material: {
|
||||
...p.material,
|
||||
...(materialData.hsCode !== null && {hs_code: materialData.hsCode})
|
||||
},
|
||||
...(materialData.tariffRate !== null && {tariff_rate: materialData.tariffRate})
|
||||
...(materialData.hsCode !== null && {hs_code: materialData.hsCode}),
|
||||
...((tariffRates !== null) ? tariffRates.get(p.id) : (materialData.tariffRate !== null && {tariff_rate: materialData.tariffRate}))
|
||||
};
|
||||
}
|
||||
return p;
|
||||
});
|
||||
this.premisses = updatedPremises;
|
||||
|
||||
return await this.saveMaterial(ids, materialData);
|
||||
|
||||
return await this.saveMaterial(ids, materialData, tariffRates);
|
||||
},
|
||||
async batchUpdatePackaging(ids, packagingData) {
|
||||
|
||||
|
|
@ -759,7 +782,7 @@ export const usePremiseEditStore = defineStore('premiseEdit', {
|
|||
return success;
|
||||
|
||||
},
|
||||
async saveMaterial(ids = null, materialData = null) {
|
||||
async saveMaterial(ids = null, materialData = null, tariffRates = null) {
|
||||
let success = true;
|
||||
const toBeUpdated = this.premisses ? (ids ? (ids.map(id => this.premisses.find(p => String(p.id) === String(id)))) : (this.premisses.filter(p => p.selected))) : null;
|
||||
|
||||
|
|
@ -771,6 +794,7 @@ export const usePremiseEditStore = defineStore('premiseEdit', {
|
|||
|
||||
hs_code: materialData === null ? toBeUpdated[0].hs_code : materialData.hsCode,
|
||||
tariff_rate: materialData === null ? toBeUpdated[0].tariff_rate : materialData.tariffRate,
|
||||
tariff_rates: (null === tariffRates) ? null : Object.fromEntries(tariffRates),
|
||||
};
|
||||
|
||||
await performRequest(this, 'POST', `${config.backendUrl}/calculation/material/`, body, false).catch(() => {
|
||||
|
|
|
|||
38
src/main/java/de/avatic/lcc/config/SoapConfig.java
Normal file
38
src/main/java/de/avatic/lcc/config/SoapConfig.java
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package de.avatic.lcc.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
import org.springframework.ws.client.core.WebServiceTemplate;
|
||||
import org.springframework.ws.soap.SoapVersion;
|
||||
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
public class SoapConfig {
|
||||
|
||||
@Bean
|
||||
public Jaxb2Marshaller marshaller() {
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setContextPath("eu.europa.ec.taxation.taric.client");
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SaajSoapMessageFactory messageFactory() {
|
||||
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
|
||||
messageFactory.setSoapVersion(SoapVersion.SOAP_11);
|
||||
return messageFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller, SaajSoapMessageFactory messageFactory) {
|
||||
WebServiceTemplate template = new WebServiceTemplate(messageFactory);
|
||||
template.setMarshaller(marshaller);
|
||||
template.setUnmarshaller(marshaller);
|
||||
template.setDefaultUri("https://ec.europa.eu/taxation_customs/dds2/taric/services/goods");
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,18 @@
|
|||
package de.avatic.lcc.controller.custom;
|
||||
|
||||
import de.avatic.lcc.dto.custom.CustomDTO;
|
||||
import de.avatic.lcc.model.taric.Nomenclature;
|
||||
import de.avatic.lcc.service.api.CustomApiService;
|
||||
import de.avatic.lcc.service.api.EUTaxationApiWrapperService;
|
||||
import de.avatic.lcc.service.calculation.NomenclatureService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controller for handling custom tariff related requests.
|
||||
* Provides endpoints for retrieving tariff rates based on HS code and country ID.
|
||||
|
|
@ -17,26 +23,36 @@ public class CustomController {
|
|||
|
||||
|
||||
private final CustomApiService customApiService;
|
||||
private final NomenclatureService nomenclatureService;
|
||||
private final EUTaxationApiWrapperService eUTaxationApiWrapperService;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of CustomController with the given service.
|
||||
*
|
||||
* @param customApiService the service responsible for custom tariff calculations
|
||||
*/
|
||||
public CustomController(CustomApiService customApiService) {
|
||||
public CustomController(CustomApiService customApiService, NomenclatureService nomenclatureService, EUTaxationApiWrapperService eUTaxationApiWrapperService) {
|
||||
this.customApiService = customApiService;
|
||||
this.nomenclatureService = nomenclatureService;
|
||||
this.eUTaxationApiWrapperService = eUTaxationApiWrapperService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the tariff rate for the specified HS code and country ID.
|
||||
*
|
||||
* @param hsCode the HS code representing the product classification
|
||||
* @param countryId the ID of the country for which the tariff rate is required
|
||||
* @param countryIds the ID of the country for which the tariff rate is required
|
||||
* @return a {@code ResponseEntity} containing the tariff rate as a {@code Number}
|
||||
*/
|
||||
@GetMapping("/")
|
||||
public ResponseEntity<Number> getTariffRate(@RequestParam(value = "hs_code") String hsCode, @RequestParam(value = "country_id") Integer countryId) {
|
||||
return ResponseEntity.ok(customApiService.getTariffRate(hsCode, countryId));
|
||||
@GetMapping({"/",""})
|
||||
public ResponseEntity<List<CustomDTO>> getTariffRate(@RequestParam(value = "hs_code") String hsCode, @RequestParam(value = "country_ids") List<Integer> countryIds) {
|
||||
var res = eUTaxationApiWrapperService.getTariffRates(hsCode, countryIds);
|
||||
return ResponseEntity.ok(res);
|
||||
}
|
||||
|
||||
@GetMapping({"/search", "/search/"})
|
||||
public ResponseEntity<List<String>> getNomenclature(@RequestParam(value = "hs_code") String hsCode) {
|
||||
return ResponseEntity.ok(nomenclatureService.getNomenclature(hsCode));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||
import jakarta.validation.constraints.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class MaterialUpdateDTO {
|
||||
|
|
@ -21,6 +22,9 @@ public class MaterialUpdateDTO {
|
|||
@Digits(integer = 4, fraction = 4, message = "Tariff rate must have at most 4 decimal places")
|
||||
private Number tariffRate;
|
||||
|
||||
@JsonProperty("tariff_rates")
|
||||
private Map<Integer, Number> tariffRates;
|
||||
|
||||
public String getHsCode() {
|
||||
return hsCode;
|
||||
}
|
||||
|
|
@ -44,4 +48,12 @@ public class MaterialUpdateDTO {
|
|||
public void setPremiseIds(List<Integer> premiseIds) {
|
||||
this.premiseIds = premiseIds;
|
||||
}
|
||||
|
||||
public Map<Integer, Number> getTariffRates() {
|
||||
return tariffRates;
|
||||
}
|
||||
|
||||
public void setTariffRates(Map<Integer, Number> tariffRates) {
|
||||
this.tariffRates = tariffRates;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
64
src/main/java/de/avatic/lcc/dto/custom/CustomDTO.java
Normal file
64
src/main/java/de/avatic/lcc/dto/custom/CustomDTO.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package de.avatic.lcc.dto.custom;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CustomDTO {
|
||||
|
||||
private boolean isDefault;
|
||||
|
||||
private Double value;
|
||||
|
||||
private List<CustomMeasureDTO> measures;
|
||||
|
||||
private Integer countryId;
|
||||
|
||||
public CustomDTO(Double value, List<CustomMeasureDTO> measures, Integer countryId) {
|
||||
this(true, value, measures, countryId);
|
||||
}
|
||||
|
||||
public CustomDTO(boolean isDefault, Double value, List<CustomMeasureDTO> measures, Integer countryId) {
|
||||
this.isDefault = isDefault;
|
||||
this.value = value;
|
||||
this.measures = measures;
|
||||
this.countryId = countryId;
|
||||
}
|
||||
|
||||
public CustomDTO(Double value, Integer countryId) {
|
||||
this(value, null, countryId);
|
||||
}
|
||||
|
||||
|
||||
public boolean isDefault() {
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
public void setDefault(boolean aDefault) {
|
||||
isDefault = aDefault;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public List<CustomMeasureDTO> getMeasures() {
|
||||
return measures;
|
||||
}
|
||||
|
||||
public void setMeasures(List<CustomMeasureDTO> measures) {
|
||||
this.measures = measures;
|
||||
}
|
||||
|
||||
public Integer getCountryId() {
|
||||
return countryId;
|
||||
}
|
||||
|
||||
public void setCountryId(Integer countryId) {
|
||||
this.countryId = countryId;
|
||||
}
|
||||
}
|
||||
54
src/main/java/de/avatic/lcc/dto/custom/CustomMeasureDTO.java
Normal file
54
src/main/java/de/avatic/lcc/dto/custom/CustomMeasureDTO.java
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package de.avatic.lcc.dto.custom;
|
||||
|
||||
public class CustomMeasureDTO {
|
||||
|
||||
private String code;
|
||||
|
||||
private String description;
|
||||
|
||||
private String regulation;
|
||||
|
||||
private String tariffRate;
|
||||
|
||||
public CustomMeasureDTO(String code, String description, String regulation, String tariffRate) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
this.regulation = regulation;
|
||||
this.tariffRate = tariffRate;
|
||||
}
|
||||
|
||||
public CustomMeasureDTO() {
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getRegulation() {
|
||||
return regulation;
|
||||
}
|
||||
|
||||
public void setRegulation(String regulation) {
|
||||
this.regulation = regulation;
|
||||
}
|
||||
|
||||
public String getTariffRate() {
|
||||
return tariffRate;
|
||||
}
|
||||
|
||||
public void setTariffRate(String tariffRate) {
|
||||
this.tariffRate = tariffRate;
|
||||
}
|
||||
}
|
||||
209
src/main/java/de/avatic/lcc/model/custom/MeasureType.java
Normal file
209
src/main/java/de/avatic/lcc/model/custom/MeasureType.java
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
package de.avatic.lcc.model.custom;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public enum MeasureType {
|
||||
|
||||
// Serie C - Applicable duty (Anwendbare Zollsätze)
|
||||
APPL("103", true), // Third country duty - Standard-Drittlandszollsatz
|
||||
APPEU("105", true), // Non preferential duty under end-use - Zollsatz unter End-Use
|
||||
CUD("106", true), // Customs Union Duty - Zollunionszollsatz
|
||||
S("112", true), // Autonomous tariff suspension - Autonome Zollaussetzung
|
||||
SUSEU("115", true), // Autonomous suspension under end-use - Aussetzung unter End-Use
|
||||
SUSSH("117", false), // Suspension - ships/boats/vessels - Aussetzung für Schiffe (nicht relevant)
|
||||
AIRWO("119", false), // Airworthiness tariff suspension - Lufttüchtigkeits-Zollaussetzung (nicht relevant)
|
||||
K_122("122", true), // Non preferential tariff quota - Nichtpräferenzielles Zollkontingent
|
||||
KEU("123", true), // Non preferential tariff quota under end-use - Kontingent unter End-Use
|
||||
OPQ("140", true), // Outward processing tariff preference - Passive Veredelung
|
||||
S_141("141", true), // Preferential suspension - Präferenzielle Aussetzung
|
||||
PREF("142", true), // Tariff preference - Zollpräferenz
|
||||
K_143("143", true), // Preferential tariff quota - Präferenzielles Zollkontingent
|
||||
C("144", true), // Preferential ceiling - Präferenzplafond
|
||||
PRFEU("145", true), // Preference under end-use - Präferenz unter End-Use
|
||||
PRKEU("146", true), // Preferential tariff quota under end-use - Präferenzkontingent unter End-Use
|
||||
CUQ("147", true), // Customs Union Quota - Zollunionskontingent
|
||||
|
||||
// Serie A - Import/Export prohibited (Verbote)
|
||||
PRO("277", false), // Import prohibition - Einfuhrverbot
|
||||
PRX("278", false), // Export prohibition - Ausfuhrverbot
|
||||
RSUBH("481", false), // Declaration of subheading submitted to restrictions (import) - Einfuhrbeschränkung
|
||||
RSHEX("485", false), // Declaration of subheading submitted to restrictions (export) - Ausfuhrbeschränkung
|
||||
|
||||
// Serie P - VAT (Mehrwertsteuer)
|
||||
TVA("305", false), // Value added tax - Mehrwertsteuer
|
||||
|
||||
// Serie Q - Excises (Verbrauchssteuern)
|
||||
ACC("306", false), // Excises - Verbrauchssteuern
|
||||
|
||||
// Serie O - Supplementary unit (Besondere Maßeinheiten)
|
||||
SUPUN("109", false), // Supplementary unit - Besondere Maßeinheit
|
||||
USIMP("110", false), // Supplementary unit import - Besondere Maßeinheit Einfuhr
|
||||
USEXP("111", false), // Supplementary unit export - Besondere Maßeinheit Ausfuhr
|
||||
|
||||
// Serie B - Entry subject to conditions (Einfuhr unter Bedingungen)
|
||||
VETCTR("410", false), // Veterinary control - Veterinärkontrolle (nicht relevant für Gabelstapler)
|
||||
PRIOR_SURV("420", true), // Entry into free circulation (prior surveillance) - Vorherige Überwachung
|
||||
REU("464", true), // Declaration of subheading submitted to end-use provisions - End-Use-Erklärung
|
||||
LPS("465", true), // Restriction on entry into free circulation - Einfuhrbeschränkung
|
||||
SPX("467", false), // Restriction on export - Ausfuhrbeschränkung
|
||||
QX("473", false), // Export authorization - Ausfuhrgenehmigung
|
||||
LPQ("474", true), // Entry into free circulation (quantitative limitation) - Mengenmäßige Beschränkung
|
||||
LPR("475", true), // Restriction on entry into free circulation - Einfuhrbeschränkung
|
||||
RX("476", false), // Restriction on export - Ausfuhrbeschränkung
|
||||
OPT("477", true), // Entry into free circulation (outward processing traffic) - Passive Veredelung
|
||||
DURX("478", false), // Export authorization (Dual use) - Ausfuhrgenehmigung Dual-Use
|
||||
CHMEX("479", false), // Export control on dangerous chemicals - Exportkontrolle gefährliche Chemikalien
|
||||
LCRED_M1("482", false), // Declaration submitted to legal restrictions (net weight/supplementary unit) - Rechtliche Beschränkungen
|
||||
LCRED_V1("483", false), // Declaration submitted to legal restrictions (unit price) - Rechtliche Beschränkungen
|
||||
PCRED_M1("484", false), // Declaration submitted to physical restrictions (net weight/supplementary unit) - Physische Beschränkungen
|
||||
PCRED_V("491", false), // Declaration submitted to physical restrictions (declared statistical value) - Physische Beschränkungen
|
||||
PCRED_M("492", false), // Declaration submitted to physical restrictions (declared net mass) - Physische Beschränkungen
|
||||
PCRED_S("493", false), // Declaration submitted to physical restrictions (declared supplementary unit) - Physische Beschränkungen
|
||||
LCRED_V("494", false), // Declaration submitted to legal restrictions (declared statistical value) - Rechtliche Beschränkungen
|
||||
LCRED_M("495", false), // Declaration submitted to legal restrictions (declared net mass) - Rechtliche Beschränkungen
|
||||
LCRED_S("496", false), // Declaration submitted to legal restrictions (declared supplementary unit) - Rechtliche Beschränkungen
|
||||
TRIMP("705", false), // Import prohibition on goods for torture and repression - Folter-/Repressionsgüter
|
||||
TREXP("706", false), // Export prohibition - torture/repression goods - Ausfuhrverbot Folter-/Repressionsgüter
|
||||
IMPORT_CTRL("707", true), // Import control - Einfuhrkontrolle (potentiell relevant für Bauteile)
|
||||
TRRX("708", false), // Export restriction - torture/repression goods - Ausfuhrbeschränkung
|
||||
EXPCTRL("709", false), // Export control - Ausfuhrkontrolle
|
||||
CITESIMP("710", false), // Import control - CITES - CITES-Kontrolle (nicht relevant)
|
||||
MILIM("711", false), // Import control on restricted goods and technologies - Militärgüter (nicht relevant)
|
||||
IAS("712", false), // Import control - IAS - Invasive Arten (nicht relevant)
|
||||
IMPORT_CTRL_GMO("713", false), // Import control on GMOs - GMO-Kontrolle (nicht relevant)
|
||||
IMPCTRL("714", true), // Import control - Einfuhrkontrolle (potentiell relevant)
|
||||
CITESEX("715", false), // Export control - CITES - CITES-Ausfuhrkontrolle
|
||||
CFISH("716", false), // Export control - Fish - Fischereikontrolle (nicht relevant)
|
||||
MILEX("717", false), // Export control on restricted goods and technologies - Militärgüter
|
||||
LUXEX("718", false), // Export control on luxury goods - Luxusgüter (nicht relevant)
|
||||
CIUUF("719", false), // Control on illegal fishing - Illegale Fischerei (nicht relevant)
|
||||
FFIM("722", false), // Entry restriction - feed and food - Futter-/Lebensmittel (nicht relevant)
|
||||
FGGIMP("724", false), // Import control of fluorinated greenhouse gases - Treibhausgase
|
||||
OZEXP("725", false), // Export control on ozone-depleting substances - Ozonschicht
|
||||
OZIMP("726", false), // Import control on ozone-depleting substances - Ozonschicht
|
||||
LUXIM("728", false), // Import control on luxury goods - Luxusgüter (nicht relevant)
|
||||
EXPCHE("730", false), // Compliance with pre-export checks requirements - Vorausfuhrkontrollen
|
||||
IMPORT_CTRL_731("731", true), // Import control - Einfuhrkontrolle (potentiell relevant)
|
||||
IMPORT_CTRL_732("732", true), // Import control - Einfuhrkontrolle (potentiell relevant)
|
||||
CGIMP("734", false), // Import control on cultural goods - Kulturgüter (nicht relevant)
|
||||
CGEXP("735", false), // Export control on cultural goods - Kulturgüter (nicht relevant)
|
||||
EXPORT_CTRL_736("736", false), // Export control - Ausfuhrkontrolle
|
||||
EXPORT_CTRL_737("737", false), // Export control - Ausfuhrkontrolle
|
||||
IMPORT_EXPORT_CML("738", false), // Import/export restriction - Common Military List goods - Militärgüter
|
||||
FUREX("740", false), // Export control on cat and dog fur - Katzen-/Hundefell (nicht relevant)
|
||||
FURIM("745", false), // Import control on cat and dog fur - Katzen-/Hundefell (nicht relevant)
|
||||
SEAL("746", false), // Import control on seal products - Robbenprodukte (nicht relevant)
|
||||
FLEGT("747", false), // Import control of timber - FLEGT licensing - Holzprodukte (nicht relevant)
|
||||
MERIM("748", false), // Import control of mercury - Quecksilber
|
||||
MEREX("749", false), // Export control of mercury - Quecksilber
|
||||
ORGANIC("750", false), // Import control of organic products - Bio-Produkte (nicht relevant)
|
||||
WSTEX("751", false), // Export control - Waste - Abfall
|
||||
WSTIM("755", false), // Import control - Waste - Abfall
|
||||
IMPCTRL_760("760", true), // Import control - Einfuhrkontrolle (potentiell relevant)
|
||||
CHMIM("761", false), // Import control on REACH - Chemikalien
|
||||
IMPORT_CTRL_762("762", true), // Import control - Einfuhrkontrolle (potentiell relevant)
|
||||
IMPORT_CTRL_763("763", true), // Import control - Einfuhrkontrolle (potentiell relevant)
|
||||
FGEXP("765", false), // Export control of fluorinated greenhouse gases - Treibhausgase
|
||||
EXPORT_CTRL_766("766", false), // Export control - Ausfuhrkontrolle
|
||||
EXPORT_CTRL_767("767", false), // Export control - Ausfuhrkontrolle
|
||||
EXPORT_CTRL_768("768", false), // Export control - Ausfuhrkontrolle
|
||||
IMPOP("769", false), // Import control on persistent organic pollutants - Organische Schadstoffe
|
||||
FLEGT_GHANA("770", false), // Import control timber - FLEGT Ghana - Holzprodukte (nicht relevant)
|
||||
FLEGT_CAMEROON("771", false), // Import control timber - FLEGT Cameroon - Holzprodukte (nicht relevant)
|
||||
FLEGT_CONGO("772", false), // Import control timber - FLEGT Congo - Holzprodukte (nicht relevant)
|
||||
FLEGT_CAR("773", false), // Import control timber - FLEGT Central Africa - Holzprodukte (nicht relevant)
|
||||
FLEGT_VIETNAM("774", false), // Import control timber - FLEGT Vietnam - Holzprodukte (nicht relevant)
|
||||
CBAM("775", false), // Carbon Border Adjustment Mechanism - CO2-Grenzausgleich
|
||||
DFRSTIM("776", false), // Import control on deforestation - Entwaldung
|
||||
DFRSEXP("777", false), // Export control on deforestation - Entwaldung
|
||||
EXPORT_CTRL_780("780", false), // Export control - Ausfuhrkontrolle
|
||||
EXPORT_CTRL_781("781", false), // Export control - Ausfuhrkontrolle
|
||||
|
||||
// Serie N - Posterior surveillance (Nachträgliche Überwachung)
|
||||
PIM("440", false), // Public Import Monitoring - Öffentliche Einfuhrüberwachung
|
||||
PEM("445", false), // Public Export Monitoring - Öffentliche Ausfuhrüberwachung
|
||||
SUB("450", false), // Statistical surveillance - Statistische Überwachung
|
||||
SUA("460", false), // Computer surveillance - Computerüberwachung
|
||||
SQR("461", false), // Community surveillance - reference quantities - Referenzmengen
|
||||
SUR("462", false), // Posterior import surveillance - Nachträgliche Einfuhrüberwachung
|
||||
SUX("463", false), // Posterior export surveillance - Nachträgliche Ausfuhrüberwachung
|
||||
SUREX("470", false), // Export surveillance - Ausfuhrüberwachung
|
||||
SUEX("471", false), // Export surveillance (TQS) - Ausfuhrüberwachung
|
||||
IMPMNTR_702("702", false), // Import Monitoring - Einfuhrüberwachung
|
||||
IMPMNTR_703("703", false), // Import Monitoring - Einfuhrüberwachung
|
||||
IMPMNTR_704("704", false), // Import Monitoring - Einfuhrüberwachung
|
||||
|
||||
// Serie M - Unit price, standard import value (Preise und Werte)
|
||||
VU("488", false), // Unit price - Stückpreis
|
||||
REPSU("489", false), // Representative price - Repräsentativer Preis
|
||||
SIV("490", false), // Standard import value - Standard-Einfuhrwert
|
||||
|
||||
// Serie D - Anti-dumping or countervailing duties (Anti-Dumping/Ausgleichszölle)
|
||||
DUMPP("551", true), // Provisional anti-dumping duty - Vorläufiger Anti-Dumping-Zoll
|
||||
DUMPD("552", true), // Definitive anti-dumping duty - Endgültiger Anti-Dumping-Zoll
|
||||
COMPP("553", true), // Provisional countervailing duty - Vorläufiger Ausgleichszoll
|
||||
COMPD("554", true), // Definitive countervailing duty - Endgültiger Ausgleichszoll
|
||||
PCDUM("555", true), // Anti-dumping/countervailing duty - Pending collection - Schwebende Erhebung
|
||||
NTDUM("561", false), // Notice of initiation of anti-dumping proceeding - Verfahrenseröffnung
|
||||
SPDUM("562", true), // Suspended anti-dumping/countervailing duty - Ausgesetzter Zoll
|
||||
RGDUM("564", false), // Anti-dumping/countervailing registration - Registrierung
|
||||
REDUM("565", false), // Anti-dumping/countervailing review - Überprüfung
|
||||
STDUM("566", false), // Anti-dumping/countervailing statistic - Statistik
|
||||
CTDUM("570", false), // Anti-dumping/countervailing duty - Control - Kontrolle
|
||||
|
||||
// Serie S - Supplementary amount (Zusätzliche Beträge)
|
||||
ASURE("651", false), // Security based on representative price - Sicherheit basierend auf Preis
|
||||
ASUCI("652", false), // Additional duty based on CIF price - Zusatzzoll basierend auf CIF-Preis
|
||||
SECQ("653", false), // Security reduced under tariff quota - Reduzierte Sicherheit
|
||||
ADQ("654", false), // Additional duty reduced under tariff quota - Reduzierter Zusatzzoll
|
||||
SECPO("655", false), // Security (poultry) based on representative price - Sicherheit Geflügel
|
||||
ADPOC("656", false), // Additional duty (poultry) based on CIF price - Zusatzzoll Geflügel
|
||||
RESEC("657", false), // Reduced security based on representative price - Reduzierte Sicherheit
|
||||
READ("658", false), // Reduced additional duty based on CIF price - Reduzierter Zusatzzoll
|
||||
|
||||
// Serie F - Additional duty on sugar, flour (Zusatzzölle Zucker/Mehl)
|
||||
AD_SZ("672", false), // Amount of additional duty on sugar - Zusatzzoll Zucker (nicht relevant)
|
||||
AD_FM("673", false), // Amount of additional duty on flour - Zusatzzoll Mehl (nicht relevant)
|
||||
|
||||
// Serie E - Levies, export refunds (Abgaben, Ausfuhrerstattungen)
|
||||
EA("674", false), // Agricultural component - Landwirtschaftliche Komponente (nicht relevant)
|
||||
|
||||
// Serie J - Countervailing charge (Ausgleichsabgaben)
|
||||
TC("690", false), // Countervailing charge - Ausgleichsabgabe
|
||||
DR("695", true), // Additional duties - Zusatzzölle
|
||||
SAFDU("696", true); // Additional duties (safeguard) - Schutzmaßnahmen-Zusatzzölle
|
||||
|
||||
|
||||
private final String measureCode;
|
||||
private final boolean containsRelevantDuty;
|
||||
|
||||
MeasureType(String measureCode, boolean containsRelevantDuty) {
|
||||
this.measureCode = measureCode;
|
||||
this.containsRelevantDuty = containsRelevantDuty;
|
||||
}
|
||||
|
||||
public String getMeasureCode() {
|
||||
return measureCode;
|
||||
}
|
||||
|
||||
public boolean containsRelevantDuty() {
|
||||
return containsRelevantDuty;
|
||||
}
|
||||
|
||||
public static Optional<MeasureType> fromMeasureCode(String measureCode) {
|
||||
for (MeasureType type : values()) {
|
||||
if (type.measureCode.equals(measureCode)) {
|
||||
return Optional.of(type);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static MeasureType fromShortName(String shortName) {
|
||||
try {
|
||||
return valueOf(shortName.toUpperCase().replace(" ", "_"));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Unknown short name: " + shortName);
|
||||
}
|
||||
}
|
||||
}
|
||||
100
src/main/java/de/avatic/lcc/model/taric/AppliedMeasure.java
Normal file
100
src/main/java/de/avatic/lcc/model/taric/AppliedMeasure.java
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class AppliedMeasure {
|
||||
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private LocalDate endDate;
|
||||
|
||||
private String amount;
|
||||
|
||||
private Integer orderNumber;
|
||||
|
||||
private Set<MeasureFootnote> measureFootnotes;
|
||||
|
||||
private Measure measure;
|
||||
|
||||
private LegalBase legalBase;
|
||||
|
||||
private Set<MeasureExclusion> exclusions;
|
||||
|
||||
private Set<AppliedMeasureCondition> conditions;
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(LocalDate endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public String getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(String amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public Integer getOrderNumber() {
|
||||
return orderNumber;
|
||||
}
|
||||
|
||||
public void setOrderNumber(Integer orderNumber) {
|
||||
this.orderNumber = orderNumber;
|
||||
}
|
||||
|
||||
public Set<MeasureFootnote> getMeasureFootnotes() {
|
||||
return measureFootnotes;
|
||||
}
|
||||
|
||||
public void setMeasureFootnotes(Set<MeasureFootnote> measureFootnotes) {
|
||||
this.measureFootnotes = measureFootnotes;
|
||||
}
|
||||
|
||||
|
||||
public Set<MeasureExclusion> getExclusions() {
|
||||
return exclusions;
|
||||
}
|
||||
|
||||
public void setExclusions(Set<MeasureExclusion> exclusions) {
|
||||
this.exclusions = exclusions;
|
||||
}
|
||||
|
||||
public Set<AppliedMeasureCondition> getConditions() {
|
||||
return conditions;
|
||||
}
|
||||
|
||||
public void setConditions(Set<AppliedMeasureCondition> conditions) {
|
||||
this.conditions = conditions;
|
||||
}
|
||||
|
||||
public Measure getMeasure() {
|
||||
return measure;
|
||||
}
|
||||
|
||||
public void setMeasure(Measure measure) {
|
||||
this.measure = measure;
|
||||
}
|
||||
|
||||
public LegalBase getLegalBase() {
|
||||
return legalBase;
|
||||
}
|
||||
|
||||
public void setLegalBase(LegalBase legalBase) {
|
||||
this.legalBase = legalBase;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
public class AppliedMeasureCondition {
|
||||
|
||||
private Integer sequenceNo;
|
||||
|
||||
private String amount;
|
||||
|
||||
private MeasureAction measureAction;
|
||||
|
||||
private MonetaryUnit monetaryUnit;
|
||||
|
||||
private Unit unit;
|
||||
|
||||
private Certificate certificate;
|
||||
|
||||
private ConditionType conditionType;
|
||||
|
||||
|
||||
public Integer getSequenceNo() {
|
||||
return sequenceNo;
|
||||
}
|
||||
|
||||
public void setSequenceNo(Integer sequenceNo) {
|
||||
this.sequenceNo = sequenceNo;
|
||||
}
|
||||
|
||||
public String getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(String amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public MeasureAction getMeasureAction() {
|
||||
return measureAction;
|
||||
}
|
||||
|
||||
public void setMeasureAction(MeasureAction measureAction) {
|
||||
this.measureAction = measureAction;
|
||||
}
|
||||
|
||||
public MonetaryUnit getMonetaryUnit() {
|
||||
return monetaryUnit;
|
||||
}
|
||||
|
||||
public void setMonetaryUnit(MonetaryUnit monetaryUnit) {
|
||||
this.monetaryUnit = monetaryUnit;
|
||||
}
|
||||
|
||||
public Unit getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public void setUnit(Unit unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
public Certificate getCertificate() {
|
||||
return certificate;
|
||||
}
|
||||
|
||||
public void setCertificate(Certificate certificate) {
|
||||
this.certificate = certificate;
|
||||
}
|
||||
|
||||
public ConditionType getConditionType() {
|
||||
return conditionType;
|
||||
}
|
||||
|
||||
public void setConditionType(ConditionType conditionType) {
|
||||
this.conditionType = conditionType;
|
||||
}
|
||||
}
|
||||
56
src/main/java/de/avatic/lcc/model/taric/Certificate.java
Normal file
56
src/main/java/de/avatic/lcc/model/taric/Certificate.java
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class Certificate {
|
||||
|
||||
private String certificateCode;
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private LocalDate endDate;
|
||||
|
||||
private CertificateType certificateType;
|
||||
|
||||
private CertificateDesc certificateDesc;
|
||||
|
||||
public String getCertificateCode() {
|
||||
return certificateCode;
|
||||
}
|
||||
|
||||
public void setCertificateCode(String certificateCode) {
|
||||
this.certificateCode = certificateCode;
|
||||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(LocalDate endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public CertificateType getCertificateType() {
|
||||
return certificateType;
|
||||
}
|
||||
|
||||
public void setCertificateType(CertificateType certificateType) {
|
||||
this.certificateType = certificateType;
|
||||
}
|
||||
|
||||
public CertificateDesc getCertificateDesc() {
|
||||
return certificateDesc;
|
||||
}
|
||||
|
||||
public void setCertificateDesc(CertificateDesc certificateDesc) {
|
||||
this.certificateDesc = certificateDesc;
|
||||
}
|
||||
}
|
||||
36
src/main/java/de/avatic/lcc/model/taric/CertificateDesc.java
Normal file
36
src/main/java/de/avatic/lcc/model/taric/CertificateDesc.java
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class CertificateDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
24
src/main/java/de/avatic/lcc/model/taric/CertificateType.java
Normal file
24
src/main/java/de/avatic/lcc/model/taric/CertificateType.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
public class CertificateType {
|
||||
|
||||
private String certificateTypeCode;
|
||||
|
||||
private CertificateTypeDesc certificateTypeDesc;
|
||||
|
||||
public String getCertificateTypeCode() {
|
||||
return certificateTypeCode;
|
||||
}
|
||||
|
||||
public void setCertificateTypeCode(String certificateTypeCode) {
|
||||
this.certificateTypeCode = certificateTypeCode;
|
||||
}
|
||||
|
||||
public CertificateTypeDesc getCertificateTypeDesc() {
|
||||
return certificateTypeDesc;
|
||||
}
|
||||
|
||||
public void setCertificateTypeDesc(CertificateTypeDesc certificateTypeDesc) {
|
||||
this.certificateTypeDesc = certificateTypeDesc;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class CertificateTypeDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
24
src/main/java/de/avatic/lcc/model/taric/ConditionType.java
Normal file
24
src/main/java/de/avatic/lcc/model/taric/ConditionType.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
public class ConditionType {
|
||||
|
||||
private String conditionTypeCode;
|
||||
|
||||
private ConditionTypeDesc conditionTypeDesc;
|
||||
|
||||
public String getConditionTypeCode() {
|
||||
return conditionTypeCode;
|
||||
}
|
||||
|
||||
public void setConditionTypeCode(String conditionTypeCode) {
|
||||
this.conditionTypeCode = conditionTypeCode;
|
||||
}
|
||||
|
||||
public ConditionTypeDesc getConditionTypeDesc() {
|
||||
return conditionTypeDesc;
|
||||
}
|
||||
|
||||
public void setConditionTypeDesc(ConditionTypeDesc conditionTypeDesc) {
|
||||
this.conditionTypeDesc = conditionTypeDesc;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class ConditionTypeDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
57
src/main/java/de/avatic/lcc/model/taric/Footnote.java
Normal file
57
src/main/java/de/avatic/lcc/model/taric/Footnote.java
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents a footnote reference
|
||||
*/
|
||||
public class Footnote {
|
||||
|
||||
|
||||
private String footnote;
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private LocalDate endDate;
|
||||
|
||||
private FootnotesDesc footnotesDesc;
|
||||
|
||||
public String getFootnote() {
|
||||
return footnote;
|
||||
}
|
||||
|
||||
public void setFootnote(String footnote) {
|
||||
this.footnote = footnote;
|
||||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(LocalDate endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public FootnotesDesc getFootnotesDesc() {
|
||||
return footnotesDesc;
|
||||
}
|
||||
|
||||
public void setFootnotesDesc(FootnotesDesc footnotesDesc) {
|
||||
this.footnotesDesc = footnotesDesc;
|
||||
}
|
||||
}
|
||||
40
src/main/java/de/avatic/lcc/model/taric/FootnotesDesc.java
Normal file
40
src/main/java/de/avatic/lcc/model/taric/FootnotesDesc.java
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class FootnotesDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
31
src/main/java/de/avatic/lcc/model/taric/Geo.java
Normal file
31
src/main/java/de/avatic/lcc/model/taric/Geo.java
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class Geo {
|
||||
|
||||
private String iso3166Code;
|
||||
|
||||
private GeoDesc geoDesc;
|
||||
|
||||
public String getIso3166Code() {
|
||||
return iso3166Code;
|
||||
}
|
||||
|
||||
public void setIso3166Code(String iso3166Code) {
|
||||
this.iso3166Code = iso3166Code;
|
||||
}
|
||||
|
||||
public GeoDesc getGeoDesc() {
|
||||
return geoDesc;
|
||||
}
|
||||
|
||||
public void setGeoDesc(GeoDesc geoDesc) {
|
||||
this.geoDesc = geoDesc;
|
||||
}
|
||||
}
|
||||
41
src/main/java/de/avatic/lcc/model/taric/GeoDesc.java
Normal file
41
src/main/java/de/avatic/lcc/model/taric/GeoDesc.java
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class GeoDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
50
src/main/java/de/avatic/lcc/model/taric/LegalBase.java
Normal file
50
src/main/java/de/avatic/lcc/model/taric/LegalBase.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class LegalBase {
|
||||
|
||||
private String legalBase;
|
||||
|
||||
private String journal;
|
||||
|
||||
private Integer page;
|
||||
|
||||
private LocalDate date;
|
||||
|
||||
public String getLegalBase() {
|
||||
return legalBase;
|
||||
}
|
||||
|
||||
public void setLegalBase(String legalBase) {
|
||||
this.legalBase = legalBase;
|
||||
}
|
||||
|
||||
public String getJournal() {
|
||||
return journal;
|
||||
}
|
||||
|
||||
public void setJournal(String journal) {
|
||||
this.journal = journal;
|
||||
}
|
||||
|
||||
public Integer getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setPage(Integer page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
}
|
||||
66
src/main/java/de/avatic/lcc/model/taric/Measure.java
Normal file
66
src/main/java/de/avatic/lcc/model/taric/Measure.java
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class Measure {
|
||||
|
||||
private String measureCode;
|
||||
|
||||
private String shortDesc;
|
||||
|
||||
private Integer tmCode;
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private MeasureDesc measureDesc;
|
||||
|
||||
private MeasureSeries measureSeries;
|
||||
|
||||
public String getMeasureCode() {
|
||||
return measureCode;
|
||||
}
|
||||
|
||||
public void setMeasureCode(String measureCode) {
|
||||
this.measureCode = measureCode;
|
||||
}
|
||||
|
||||
public String getShortDesc() {
|
||||
return shortDesc;
|
||||
}
|
||||
|
||||
public void setShortDesc(String shortDesc) {
|
||||
this.shortDesc = shortDesc;
|
||||
}
|
||||
|
||||
public Integer getTmCode() {
|
||||
return tmCode;
|
||||
}
|
||||
|
||||
public void setTmCode(Integer tmCode) {
|
||||
this.tmCode = tmCode;
|
||||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public MeasureDesc getMeasureDesc() {
|
||||
return measureDesc;
|
||||
}
|
||||
|
||||
public void setMeasureDesc(MeasureDesc measureDesc) {
|
||||
this.measureDesc = measureDesc;
|
||||
}
|
||||
|
||||
public MeasureSeries getMeasureSeries() {
|
||||
return measureSeries;
|
||||
}
|
||||
|
||||
public void setMeasureSeries(MeasureSeries measureSeries) {
|
||||
this.measureSeries = measureSeries;
|
||||
}
|
||||
}
|
||||
24
src/main/java/de/avatic/lcc/model/taric/MeasureAction.java
Normal file
24
src/main/java/de/avatic/lcc/model/taric/MeasureAction.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
public class MeasureAction {
|
||||
|
||||
private String measureActionCode;
|
||||
|
||||
private MeasureActionDesc measureActionDesc;
|
||||
|
||||
public String getMeasureActionCode() {
|
||||
return measureActionCode;
|
||||
}
|
||||
|
||||
public void setMeasureActionCode(String measureActionCode) {
|
||||
this.measureActionCode = measureActionCode;
|
||||
}
|
||||
|
||||
public MeasureActionDesc getMeasureActionDesc() {
|
||||
return measureActionDesc;
|
||||
}
|
||||
|
||||
public void setMeasureActionDesc(MeasureActionDesc measureActionDesc) {
|
||||
this.measureActionDesc = measureActionDesc;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class MeasureActionDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* Represents a measure component (duty rate, etc.)
|
||||
*/
|
||||
public class MeasureComponent {
|
||||
|
||||
@JsonProperty("duty_expression_id")
|
||||
private String dutyExpressionId;
|
||||
|
||||
@JsonProperty("duty_amount")
|
||||
private BigDecimal dutyAmount;
|
||||
|
||||
@JsonProperty("monetary_unit_code")
|
||||
private String monetaryUnitCode;
|
||||
|
||||
@JsonProperty("measurement_unit_code")
|
||||
private String measurementUnitCode;
|
||||
|
||||
@JsonProperty("measurement_unit_qualifier_code")
|
||||
private String measurementUnitQualifierCode;
|
||||
|
||||
@JsonProperty("duty_expression_description")
|
||||
private String dutyExpressionDescription;
|
||||
|
||||
@JsonProperty("duty_expression_abbreviation")
|
||||
private String dutyExpressionAbbreviation;
|
||||
|
||||
// Getters and Setters
|
||||
|
||||
public String getDutyExpressionId() {
|
||||
return dutyExpressionId;
|
||||
}
|
||||
|
||||
public void setDutyExpressionId(String dutyExpressionId) {
|
||||
this.dutyExpressionId = dutyExpressionId;
|
||||
}
|
||||
|
||||
public BigDecimal getDutyAmount() {
|
||||
return dutyAmount;
|
||||
}
|
||||
|
||||
public void setDutyAmount(BigDecimal dutyAmount) {
|
||||
this.dutyAmount = dutyAmount;
|
||||
}
|
||||
|
||||
public String getMonetaryUnitCode() {
|
||||
return monetaryUnitCode;
|
||||
}
|
||||
|
||||
public void setMonetaryUnitCode(String monetaryUnitCode) {
|
||||
this.monetaryUnitCode = monetaryUnitCode;
|
||||
}
|
||||
|
||||
public String getMeasurementUnitCode() {
|
||||
return measurementUnitCode;
|
||||
}
|
||||
|
||||
public void setMeasurementUnitCode(String measurementUnitCode) {
|
||||
this.measurementUnitCode = measurementUnitCode;
|
||||
}
|
||||
|
||||
public String getMeasurementUnitQualifierCode() {
|
||||
return measurementUnitQualifierCode;
|
||||
}
|
||||
|
||||
public void setMeasurementUnitQualifierCode(String measurementUnitQualifierCode) {
|
||||
this.measurementUnitQualifierCode = measurementUnitQualifierCode;
|
||||
}
|
||||
|
||||
public String getDutyExpressionDescription() {
|
||||
return dutyExpressionDescription;
|
||||
}
|
||||
|
||||
public void setDutyExpressionDescription(String dutyExpressionDescription) {
|
||||
this.dutyExpressionDescription = dutyExpressionDescription;
|
||||
}
|
||||
|
||||
public String getDutyExpressionAbbreviation() {
|
||||
return dutyExpressionAbbreviation;
|
||||
}
|
||||
|
||||
public void setDutyExpressionAbbreviation(String dutyExpressionAbbreviation) {
|
||||
this.dutyExpressionAbbreviation = dutyExpressionAbbreviation;
|
||||
}
|
||||
}
|
||||
135
src/main/java/de/avatic/lcc/model/taric/MeasureCondition.java
Normal file
135
src/main/java/de/avatic/lcc/model/taric/MeasureCondition.java
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a measure condition
|
||||
*/
|
||||
public class MeasureCondition {
|
||||
|
||||
@JsonProperty("condition_code")
|
||||
private String conditionCode;
|
||||
|
||||
@JsonProperty("condition_sequence_number")
|
||||
private Integer conditionSequenceNumber;
|
||||
|
||||
@JsonProperty("condition_duty_amount")
|
||||
private BigDecimal conditionDutyAmount;
|
||||
|
||||
@JsonProperty("condition_monetary_unit_code")
|
||||
private String conditionMonetaryUnitCode;
|
||||
|
||||
@JsonProperty("condition_measurement_unit_code")
|
||||
private String conditionMeasurementUnitCode;
|
||||
|
||||
@JsonProperty("condition_measurement_unit_qualifier_code")
|
||||
private String conditionMeasurementUnitQualifierCode;
|
||||
|
||||
@JsonProperty("action_code")
|
||||
private String actionCode;
|
||||
|
||||
@JsonProperty("certificate_type_code")
|
||||
private String certificateTypeCode;
|
||||
|
||||
@JsonProperty("certificate_code")
|
||||
private String certificateCode;
|
||||
|
||||
@JsonProperty("certificate_description")
|
||||
private String certificateDescription;
|
||||
|
||||
@JsonProperty("condition_components")
|
||||
private List<MeasureComponent> conditionComponents;
|
||||
|
||||
// Getters and Setters
|
||||
|
||||
public String getConditionCode() {
|
||||
return conditionCode;
|
||||
}
|
||||
|
||||
public void setConditionCode(String conditionCode) {
|
||||
this.conditionCode = conditionCode;
|
||||
}
|
||||
|
||||
public Integer getConditionSequenceNumber() {
|
||||
return conditionSequenceNumber;
|
||||
}
|
||||
|
||||
public void setConditionSequenceNumber(Integer conditionSequenceNumber) {
|
||||
this.conditionSequenceNumber = conditionSequenceNumber;
|
||||
}
|
||||
|
||||
public BigDecimal getConditionDutyAmount() {
|
||||
return conditionDutyAmount;
|
||||
}
|
||||
|
||||
public void setConditionDutyAmount(BigDecimal conditionDutyAmount) {
|
||||
this.conditionDutyAmount = conditionDutyAmount;
|
||||
}
|
||||
|
||||
public String getConditionMonetaryUnitCode() {
|
||||
return conditionMonetaryUnitCode;
|
||||
}
|
||||
|
||||
public void setConditionMonetaryUnitCode(String conditionMonetaryUnitCode) {
|
||||
this.conditionMonetaryUnitCode = conditionMonetaryUnitCode;
|
||||
}
|
||||
|
||||
public String getConditionMeasurementUnitCode() {
|
||||
return conditionMeasurementUnitCode;
|
||||
}
|
||||
|
||||
public void setConditionMeasurementUnitCode(String conditionMeasurementUnitCode) {
|
||||
this.conditionMeasurementUnitCode = conditionMeasurementUnitCode;
|
||||
}
|
||||
|
||||
public String getConditionMeasurementUnitQualifierCode() {
|
||||
return conditionMeasurementUnitQualifierCode;
|
||||
}
|
||||
|
||||
public void setConditionMeasurementUnitQualifierCode(String conditionMeasurementUnitQualifierCode) {
|
||||
this.conditionMeasurementUnitQualifierCode = conditionMeasurementUnitQualifierCode;
|
||||
}
|
||||
|
||||
public String getActionCode() {
|
||||
return actionCode;
|
||||
}
|
||||
|
||||
public void setActionCode(String actionCode) {
|
||||
this.actionCode = actionCode;
|
||||
}
|
||||
|
||||
public String getCertificateTypeCode() {
|
||||
return certificateTypeCode;
|
||||
}
|
||||
|
||||
public void setCertificateTypeCode(String certificateTypeCode) {
|
||||
this.certificateTypeCode = certificateTypeCode;
|
||||
}
|
||||
|
||||
public String getCertificateCode() {
|
||||
return certificateCode;
|
||||
}
|
||||
|
||||
public void setCertificateCode(String certificateCode) {
|
||||
this.certificateCode = certificateCode;
|
||||
}
|
||||
|
||||
public String getCertificateDescription() {
|
||||
return certificateDescription;
|
||||
}
|
||||
|
||||
public void setCertificateDescription(String certificateDescription) {
|
||||
this.certificateDescription = certificateDescription;
|
||||
}
|
||||
|
||||
public List<MeasureComponent> getConditionComponents() {
|
||||
return conditionComponents;
|
||||
}
|
||||
|
||||
public void setConditionComponents(List<MeasureComponent> conditionComponents) {
|
||||
this.conditionComponents = conditionComponents;
|
||||
}
|
||||
}
|
||||
37
src/main/java/de/avatic/lcc/model/taric/MeasureDesc.java
Normal file
37
src/main/java/de/avatic/lcc/model/taric/MeasureDesc.java
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class MeasureDesc {
|
||||
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class MeasureExclusion {
|
||||
|
||||
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private LocalDate endDate;
|
||||
|
||||
private Geo geo;
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(LocalDate endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public Geo getGeo() {
|
||||
return geo;
|
||||
}
|
||||
|
||||
public void setGeo(Geo geo) {
|
||||
this.geo = geo;
|
||||
}
|
||||
}
|
||||
38
src/main/java/de/avatic/lcc/model/taric/MeasureFootnote.java
Normal file
38
src/main/java/de/avatic/lcc/model/taric/MeasureFootnote.java
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class MeasureFootnote {
|
||||
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private LocalDate endDate;
|
||||
|
||||
private Footnote footnote;
|
||||
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(LocalDate endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public Footnote getFootnote() {
|
||||
return footnote;
|
||||
}
|
||||
|
||||
public void setFootnote(Footnote footnote) {
|
||||
this.footnote = footnote;
|
||||
}
|
||||
}
|
||||
24
src/main/java/de/avatic/lcc/model/taric/MeasureSeries.java
Normal file
24
src/main/java/de/avatic/lcc/model/taric/MeasureSeries.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
public class MeasureSeries {
|
||||
|
||||
private String measureSeriesCode;
|
||||
|
||||
private MeasureSeriesDesc measureSeriesDesc;
|
||||
|
||||
public String getMeasureSeriesCode() {
|
||||
return measureSeriesCode;
|
||||
}
|
||||
|
||||
public void setMeasureSeriesCode(String measureSeriesCode) {
|
||||
this.measureSeriesCode = measureSeriesCode;
|
||||
}
|
||||
|
||||
public MeasureSeriesDesc getMeasureSeriesDesc() {
|
||||
return measureSeriesDesc;
|
||||
}
|
||||
|
||||
public void setMeasureSeriesDesc(MeasureSeriesDesc measureSeriesDesc) {
|
||||
this.measureSeriesDesc = measureSeriesDesc;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class MeasureSeriesDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
30
src/main/java/de/avatic/lcc/model/taric/MonetaryUnit.java
Normal file
30
src/main/java/de/avatic/lcc/model/taric/MonetaryUnit.java
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class MonetaryUnit {
|
||||
|
||||
private String monetaryUnitCode;
|
||||
|
||||
private MonetaryUnitDesc monetaryUnitDesc;
|
||||
|
||||
public String getMonetaryUnitCode() {
|
||||
return monetaryUnitCode;
|
||||
}
|
||||
|
||||
public void setMonetaryUnitCode(String monetaryUnitCode) {
|
||||
this.monetaryUnitCode = monetaryUnitCode;
|
||||
}
|
||||
|
||||
public MonetaryUnitDesc getMonetaryUnitDesc() {
|
||||
return monetaryUnitDesc;
|
||||
}
|
||||
|
||||
public void setMonetaryUnitDesc(MonetaryUnitDesc monetaryUnitDesc) {
|
||||
this.monetaryUnitDesc = monetaryUnitDesc;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class MonetaryUnitDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
127
src/main/java/de/avatic/lcc/model/taric/Nomenclature.java
Normal file
127
src/main/java/de/avatic/lcc/model/taric/Nomenclature.java
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents a nomenclature entry in the TARIC system
|
||||
*/
|
||||
public class Nomenclature {
|
||||
|
||||
private String hscode;
|
||||
|
||||
private String suffix;
|
||||
|
||||
private Integer hierachy;
|
||||
|
||||
private Integer indent;
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private LocalDate endDate;
|
||||
|
||||
private Boolean isLeaf;
|
||||
|
||||
private LocalDate isLeafStartDate;
|
||||
|
||||
private Integer parentId;
|
||||
|
||||
private NomenclatureDesc nomenclatureDescs;
|
||||
|
||||
private Set<NomenclatureFootnote> footnotes;
|
||||
|
||||
public String getHscode() {
|
||||
return hscode;
|
||||
}
|
||||
|
||||
public void setHscode(String hscode) {
|
||||
this.hscode = hscode;
|
||||
}
|
||||
|
||||
public String getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
public void setSuffix(String suffix) {
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
public Integer getHierachy() {
|
||||
return hierachy;
|
||||
}
|
||||
|
||||
public void setHierachy(Integer hierachy) {
|
||||
this.hierachy = hierachy;
|
||||
}
|
||||
|
||||
public Integer getIndent() {
|
||||
return indent;
|
||||
}
|
||||
|
||||
public void setIndent(Integer indent) {
|
||||
this.indent = indent;
|
||||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(LocalDate endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public Boolean getLeaf() {
|
||||
return isLeaf;
|
||||
}
|
||||
|
||||
public void setLeaf(Boolean leaf) {
|
||||
isLeaf = leaf;
|
||||
}
|
||||
|
||||
public LocalDate getIsLeafStartDate() {
|
||||
return isLeafStartDate;
|
||||
}
|
||||
|
||||
public void setIsLeafStartDate(LocalDate isLeafStartDate) {
|
||||
this.isLeafStartDate = isLeafStartDate;
|
||||
}
|
||||
|
||||
public Integer getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(Integer parentId) {
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public NomenclatureDesc getNomenclatureDescs() {
|
||||
return nomenclatureDescs;
|
||||
}
|
||||
|
||||
public void setNomenclatureDescs(NomenclatureDesc nomenclatureDescs) {
|
||||
this.nomenclatureDescs = nomenclatureDescs;
|
||||
}
|
||||
|
||||
public Set<NomenclatureFootnote> getFootnotes() {
|
||||
return footnotes;
|
||||
}
|
||||
|
||||
public void setFootnotes(Set<NomenclatureFootnote> footnotes) {
|
||||
this.footnotes = footnotes;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
|
||||
public class NomenclatureDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a footnote reference for a nomenclature
|
||||
*/
|
||||
public class NomenclatureFootnote {
|
||||
|
||||
private Footnote footnote;
|
||||
|
||||
public Footnote getFootnote() {
|
||||
return footnote;
|
||||
}
|
||||
|
||||
public void setFootnote(Footnote footnote) {
|
||||
this.footnote = footnote;
|
||||
}
|
||||
}
|
||||
69
src/main/java/de/avatic/lcc/model/taric/TariffResponse.java
Normal file
69
src/main/java/de/avatic/lcc/model/taric/TariffResponse.java
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Wrapper for the TARIC API tariff response
|
||||
* Structure: { "measureType": { "additionalCode": [ AppliedMeasure... ] } }
|
||||
*/
|
||||
public class TariffResponse {
|
||||
|
||||
// Outer map: MeasureType -> Inner map
|
||||
// Inner map: AdditionalCode -> List of AppliedMeasures
|
||||
private Map<String, Map<String, List<AppliedMeasure>>> measures;
|
||||
|
||||
public TariffResponse() {
|
||||
}
|
||||
|
||||
public TariffResponse(Map<String, Map<String, List<AppliedMeasure>>> measures) {
|
||||
this.measures = measures;
|
||||
}
|
||||
|
||||
public Map<String, Map<String, List<AppliedMeasure>>> getMeasures() {
|
||||
return measures;
|
||||
}
|
||||
|
||||
public void setMeasures(Map<String, Map<String, List<AppliedMeasure>>> measures) {
|
||||
this.measures = measures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all measures as a flat list
|
||||
*/
|
||||
public List<AppliedMeasure> getAllMeasures() {
|
||||
if (measures == null) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
return measures.values().stream()
|
||||
.flatMap(innerMap -> innerMap.values().stream())
|
||||
.flatMap(List::stream)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get measures by measure type
|
||||
*/
|
||||
public List<AppliedMeasure> getMeasuresByType(String measureType) {
|
||||
if (measures == null || !measures.containsKey(measureType)) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
return measures.get(measureType).values().stream()
|
||||
.flatMap(List::stream)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get measures by measure type and additional code
|
||||
*/
|
||||
public List<AppliedMeasure> getMeasuresByTypeAndCode(String measureType, String additionalCode) {
|
||||
if (measures == null || !measures.containsKey(measureType)) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
Map<String, List<AppliedMeasure>> innerMap = measures.get(measureType);
|
||||
return innerMap.getOrDefault(additionalCode, List.of());
|
||||
}
|
||||
}
|
||||
51
src/main/java/de/avatic/lcc/model/taric/Unit.java
Normal file
51
src/main/java/de/avatic/lcc/model/taric/Unit.java
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class Unit {
|
||||
|
||||
private String unitCode;
|
||||
|
||||
private String unitQualifier;
|
||||
|
||||
private String label;
|
||||
|
||||
private UnitDesc unitDesc;
|
||||
|
||||
public String getUnitCode() {
|
||||
return unitCode;
|
||||
}
|
||||
|
||||
public void setUnitCode(String unitCode) {
|
||||
this.unitCode = unitCode;
|
||||
}
|
||||
|
||||
public String getUnitQualifier() {
|
||||
return unitQualifier;
|
||||
}
|
||||
|
||||
public void setUnitQualifier(String unitQualifier) {
|
||||
this.unitQualifier = unitQualifier;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public UnitDesc getUnitDesc() {
|
||||
return unitDesc;
|
||||
}
|
||||
|
||||
public void setUnitDesc(UnitDesc unitDesc) {
|
||||
this.unitDesc = unitDesc;
|
||||
}
|
||||
}
|
||||
37
src/main/java/de/avatic/lcc/model/taric/UnitDesc.java
Normal file
37
src/main/java/de/avatic/lcc/model/taric/UnitDesc.java
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package de.avatic.lcc.model.taric;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class UnitDesc {
|
||||
|
||||
private String lang;
|
||||
|
||||
private String desc;
|
||||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package de.avatic.lcc.repositories;
|
||||
|
||||
import de.avatic.lcc.service.api.EUTaxationApiService;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public class NomenclatureRepository {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final EUTaxationApiService eUTaxationApiService;
|
||||
|
||||
public NomenclatureRepository(JdbcTemplate jdbcTemplate, EUTaxationApiService eUTaxationApiService) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.eUTaxationApiService = eUTaxationApiService;
|
||||
}
|
||||
|
||||
public List<String> searchHsCode(String search) {
|
||||
String sql = """
|
||||
SELECT hs_code FROM nomenclature WHERE hs_code LIKE CONCAT(?, '%') LIMIT 10
|
||||
""";
|
||||
|
||||
return jdbcTemplate.queryForList (sql, String.class, search);
|
||||
}
|
||||
|
||||
public boolean validate(String hsCode) {
|
||||
try {
|
||||
var foundNomenclature = eUTaxationApiService.getGoodsDescription(hsCode, "en");
|
||||
return foundNomenclature.getReturn().getResult().getData().isDeclarable();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -209,6 +209,14 @@ public class PremisesService {
|
|||
if (!admin)
|
||||
premiseRepository.checkOwner(materialUpdateDTO.getPremiseIds(), userId);
|
||||
|
||||
|
||||
if(materialUpdateDTO.getTariffRates() != null) {
|
||||
var rates = materialUpdateDTO.getTariffRates();
|
||||
rates.keySet().forEach(id -> premiseRepository.updateMaterial(List.of(id), materialUpdateDTO.getHsCode(), rates.get(id) == null ? null : BigDecimal.valueOf(rates.get(id).doubleValue())));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var tariffRate = materialUpdateDTO.getTariffRate() == null ? null : BigDecimal.valueOf(materialUpdateDTO.getTariffRate().doubleValue());
|
||||
premiseRepository.updateMaterial(materialUpdateDTO.getPremiseIds(), materialUpdateDTO.getHsCode(), tariffRate);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,165 @@
|
|||
package de.avatic.lcc.service.api;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.avatic.lcc.dto.custom.CustomDTO;
|
||||
import de.avatic.lcc.dto.generic.PropertyDTO;
|
||||
import de.avatic.lcc.model.db.properties.SystemPropertyMappingId;
|
||||
import de.avatic.lcc.model.taric.AppliedMeasure;
|
||||
import de.avatic.lcc.model.taric.Nomenclature;
|
||||
import de.avatic.lcc.repositories.country.CountryRepository;
|
||||
import de.avatic.lcc.repositories.properties.PropertyRepository;
|
||||
import de.avatic.lcc.util.exception.base.InternalErrorException;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class CustomApiService {
|
||||
public BigDecimal getTariffRate(String hsCode, Integer countryId) {
|
||||
return BigDecimal.valueOf(0.03);
|
||||
|
||||
//TODO implement me
|
||||
private final CountryRepository countryRepository;
|
||||
private final RestTemplate restTemplate;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final String taricApiUrl;
|
||||
private final String taricApiKey;
|
||||
private final PropertyRepository propertyRepository;
|
||||
|
||||
public CustomApiService(@Value("${taric.api.key}") String taricApiKey, @Value("${taric.api.url}") String taricApiUrl, CountryRepository countryRepository, RestTemplate restTemplate, ObjectMapper objectMapper, PropertyRepository propertyRepository) {
|
||||
this.taricApiKey = taricApiKey;
|
||||
this.taricApiUrl = taricApiUrl;
|
||||
this.countryRepository = countryRepository;
|
||||
this.restTemplate = restTemplate;
|
||||
this.objectMapper = objectMapper;
|
||||
this.propertyRepository = propertyRepository;
|
||||
}
|
||||
|
||||
public CustomDTO getTariffRate(String hsCode, Integer countryId) {
|
||||
var country = countryRepository.getById(countryId);
|
||||
String iso = country.orElseThrow().getIsoCode().name();
|
||||
|
||||
try {
|
||||
URI uri = UriComponentsBuilder.fromUriString(taricApiUrl).queryParam("hscode", hsCode).queryParam("countryCode", iso).path("/api/v1/tariff").build().toUri();
|
||||
ResponseEntity<Map<String, Map<String, List<AppliedMeasure>>>> response = restTemplate.exchange(uri, HttpMethod.GET, createHttpEntity(), new ParameterizedTypeReference<>() {
|
||||
});
|
||||
|
||||
var applMeasure = response.getBody();
|
||||
|
||||
if (applMeasure != null) {
|
||||
List<String> sortedKeys = applMeasure.keySet().stream().sorted().toList().reversed();
|
||||
|
||||
for (String key : sortedKeys) {
|
||||
Map<String, List<AppliedMeasure>> geo = applMeasure.get(key);
|
||||
|
||||
if (geo.containsKey(iso)) {
|
||||
var rate = findMeasure(geo.get(iso));
|
||||
if (rate.isPresent()) return new CustomDTO(false, rate.get(), null, countryId);
|
||||
}
|
||||
|
||||
for (String geoKey : geo.keySet()) {
|
||||
if (!"ERGA OMNES".equals(geoKey)) {
|
||||
var rate = findMeasure(geo.get(geoKey));
|
||||
if (rate.isPresent()) return new CustomDTO(false, rate.get(), null, countryId);
|
||||
}
|
||||
}
|
||||
|
||||
for (String geoKey : geo.keySet()) {
|
||||
if ("ERGA OMNES".equals(geoKey)) {
|
||||
var rate = findMeasure(geo.get(geoKey));
|
||||
if (rate.isPresent()) return new CustomDTO(false, rate.get(), null, countryId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception _) {
|
||||
|
||||
}
|
||||
|
||||
return propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.TARIFF_RATE).map(PropertyDTO::getCurrentValue).map(Double::valueOf).map(aDouble -> new CustomDTO(aDouble, countryId)).orElseThrow(() -> new InternalErrorException("Unable to load default custom rate. Please contact support."));
|
||||
}
|
||||
|
||||
private Optional<Double> findMeasure(List<AppliedMeasure> appliedMeasures) {
|
||||
|
||||
var series = List.of("B", "C", "D");
|
||||
|
||||
for (var seriesCode : series) {
|
||||
|
||||
var measures = appliedMeasures.stream().filter(m -> m.getMeasure().getMeasureSeries().getMeasureSeriesCode().equals(seriesCode))
|
||||
.map(AppliedMeasure::getAmount).filter(str -> str != null && str.trim().matches("\\d+\\.\\d+\\s*%"))
|
||||
.map(str -> Double.parseDouble(str.trim().replace("%", "").trim()) / 100)
|
||||
.toList();
|
||||
|
||||
if (!measures.isEmpty())
|
||||
return Optional.of(measures.getFirst());
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
private HttpHeaders createHeaders() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("X-API-Key", taricApiKey);
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
return headers;
|
||||
}
|
||||
|
||||
private HttpEntity<Void> createHttpEntity() {
|
||||
return new HttpEntity<>(createHeaders());
|
||||
}
|
||||
|
||||
public List<String> getNomenclature(String searchTerm) {
|
||||
try {
|
||||
|
||||
URI uri = UriComponentsBuilder.fromUriString(taricApiUrl).path("/api/v1/nomenclature/declarable").queryParam("hscode", searchTerm).build().toUri();
|
||||
|
||||
ResponseEntity<List<Nomenclature>> response = restTemplate.exchange(uri, HttpMethod.GET, createHttpEntity(), new ParameterizedTypeReference<>() {
|
||||
});
|
||||
|
||||
return response.getBody().stream().map(Nomenclature::getHscode).toList();
|
||||
|
||||
} catch (Exception e) {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validate(String hsCode) {
|
||||
return true;
|
||||
try {
|
||||
|
||||
URI url = UriComponentsBuilder.fromUriString(taricApiUrl).queryParam("hscode", hsCode).buildAndExpand("/api/v1/nomenclature").encode().toUri();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("X-API-Key", taricApiKey);
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(headers);
|
||||
|
||||
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
|
||||
|
||||
// Check if response is valid (200) and parse to Nomenclature
|
||||
if (response.getStatusCode() == HttpStatus.OK) {
|
||||
Nomenclature nomenclature = objectMapper.readValue(response.getBody(), Nomenclature.class);
|
||||
|
||||
// Check if isLeaf is true
|
||||
return Boolean.TRUE.equals(nomenclature.getLeaf());
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (HttpClientErrorException.NotFound e) {
|
||||
// 404 - HS code not found
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package de.avatic.lcc.service.api;
|
||||
|
||||
import eu.europa.ec.taxation.taric.client.*;
|
||||
import jakarta.xml.bind.JAXBElement;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ws.client.core.WebServiceTemplate;
|
||||
|
||||
import javax.xml.datatype.DatatypeFactory;
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
@Service
|
||||
public class EUTaxationApiService {
|
||||
|
||||
private final WebServiceTemplate webServiceTemplate;
|
||||
private final ObjectFactory objectFactory;
|
||||
|
||||
public EUTaxationApiService(WebServiceTemplate webServiceTemplate) {
|
||||
this.webServiceTemplate = webServiceTemplate;
|
||||
this.objectFactory = new ObjectFactory();
|
||||
}
|
||||
|
||||
public GoodsDescrForWsResponse getGoodsDescription(String goodsCode, String languageCode) {
|
||||
GoodsDescrForWs request = new GoodsDescrForWs();
|
||||
request.setGoodsCode(goodsCode);
|
||||
request.setLanguageCode(languageCode);
|
||||
request.setReferenceDate(getCurrentDate());
|
||||
|
||||
JAXBElement<GoodsDescrForWs> requestElement = objectFactory.createGoodsDescrForWs(request);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
JAXBElement<GoodsDescrForWsResponse> responseElement =
|
||||
(JAXBElement<GoodsDescrForWsResponse>) webServiceTemplate.marshalSendAndReceive(requestElement);
|
||||
|
||||
return responseElement.getValue();
|
||||
}
|
||||
|
||||
public GoodsMeasForWsResponse getGoodsMeasures(String goodsCode, String countryCode, String tradeMovement) {
|
||||
GoodsMeasForWs request = new GoodsMeasForWs();
|
||||
request.setGoodsCode(goodsCode);
|
||||
request.setCountryCode(countryCode);
|
||||
request.setReferenceDate(getCurrentDate());
|
||||
request.setTradeMovement(TradeMovementCode.fromValue(tradeMovement));
|
||||
|
||||
JAXBElement<GoodsMeasForWs> requestElement = objectFactory.createGoodsMeasForWs(request);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
JAXBElement<GoodsMeasForWsResponse> responseElement =
|
||||
(JAXBElement<GoodsMeasForWsResponse>) webServiceTemplate.marshalSendAndReceive(requestElement);
|
||||
|
||||
return responseElement.getValue();
|
||||
}
|
||||
|
||||
private XMLGregorianCalendar getCurrentDate() {
|
||||
try {
|
||||
String currentDate = LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
|
||||
return DatatypeFactory.newInstance().newXMLGregorianCalendar(currentDate);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Fehler beim Erstellen des Datums", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package de.avatic.lcc.service.api;
|
||||
|
||||
import de.avatic.lcc.dto.custom.CustomDTO;
|
||||
import de.avatic.lcc.dto.custom.CustomMeasureDTO;
|
||||
import de.avatic.lcc.dto.generic.PropertyDTO;
|
||||
import de.avatic.lcc.model.custom.MeasureType;
|
||||
import de.avatic.lcc.model.db.properties.SystemPropertyMappingId;
|
||||
import de.avatic.lcc.repositories.country.CountryRepository;
|
||||
import de.avatic.lcc.repositories.properties.PropertyRepository;
|
||||
import de.avatic.lcc.util.exception.base.InternalErrorException;
|
||||
import eu.europa.ec.taxation.taric.client.GoodsMeasuresForWsResponse;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Service
|
||||
public class EUTaxationApiWrapperService {
|
||||
|
||||
private final CountryRepository countryRepository;
|
||||
private final EUTaxationApiService eUTaxationApiService;
|
||||
private final PropertyRepository propertyRepository;
|
||||
|
||||
public EUTaxationApiWrapperService(CountryRepository countryRepository, EUTaxationApiService eUTaxationApiService, PropertyRepository propertyRepository) {
|
||||
this.countryRepository = countryRepository;
|
||||
this.eUTaxationApiService = eUTaxationApiService;
|
||||
this.propertyRepository = propertyRepository;
|
||||
}
|
||||
|
||||
public List<CustomDTO> getTariffRates(String hsCode, List<Integer> countryId) {
|
||||
var futures = countryId.stream().map(country -> getTariffRate(hsCode, country)).toList();
|
||||
|
||||
return futures.stream().map(CompletableFuture::join).toList();
|
||||
}
|
||||
|
||||
@Async
|
||||
public CompletableFuture<CustomDTO> getTariffRate(String hsCode, Integer countryId) {
|
||||
var country = countryRepository.getById(countryId);
|
||||
String iso = country.orElseThrow().getIsoCode().name();
|
||||
|
||||
List<CustomMeasureDTO> customMeasures = new ArrayList<>();
|
||||
|
||||
try {
|
||||
var measForWsResponse = eUTaxationApiService.getGoodsMeasures(hsCode, iso.toUpperCase(), "I");
|
||||
|
||||
GoodsMeasuresForWsResponse.Measures.Measure selectedMeasure = null;
|
||||
Double selectedDuty = null;
|
||||
int rank = Integer.MAX_VALUE;
|
||||
|
||||
var measures = filterToNewestMeasuresPerType(measForWsResponse.getReturn().getResult().getMeasures().getMeasure());
|
||||
|
||||
|
||||
for (var measure : measures) {
|
||||
var measureType = MeasureType.fromMeasureCode(measure.getMeasureType().getMeasureType());
|
||||
boolean maybeRelevant = measureType.map(MeasureType::containsRelevantDuty).orElse(false);
|
||||
|
||||
if (maybeRelevant) {
|
||||
var duty = extractDuty(measure);
|
||||
|
||||
if (rank > measureType.get().ordinal() && duty.isPresent()) {
|
||||
rank = measureType.get().ordinal();
|
||||
selectedDuty = duty.get();
|
||||
selectedMeasure = measure;
|
||||
}
|
||||
}
|
||||
|
||||
customMeasures.add(new CustomMeasureDTO(
|
||||
measure.getMeasureType().getMeasureType(),
|
||||
measure.getMeasureType().getDescription(),
|
||||
measure.getRegulationId(),
|
||||
measure.getDutyRate()));
|
||||
}
|
||||
|
||||
if (selectedDuty != null) {
|
||||
return CompletableFuture.completedFuture(new CustomDTO(false, selectedDuty, customMeasures, countryId));
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
// just continue
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.TARIFF_RATE).map(PropertyDTO::getCurrentValue).map(Double::valueOf).map(d -> new CustomDTO(d, customMeasures, countryId)).orElseThrow(() -> new InternalErrorException("Unable to load default custom rate. Please contact support.")));
|
||||
|
||||
}
|
||||
|
||||
public List<GoodsMeasuresForWsResponse.Measures.Measure> filterToNewestMeasuresPerType(List<GoodsMeasuresForWsResponse.Measures.Measure> measures) {
|
||||
Map<String, GoodsMeasuresForWsResponse.Measures.Measure> newestByType = new HashMap<>();
|
||||
|
||||
for (GoodsMeasuresForWsResponse.Measures.Measure measure : measures) {
|
||||
String measureTypeKey = measure.getMeasureType().getMeasureType();
|
||||
|
||||
GoodsMeasuresForWsResponse.Measures.Measure existing = newestByType.get(measureTypeKey);
|
||||
|
||||
if (existing == null ||
|
||||
measure.getValidityStartDate().compare(existing.getValidityStartDate()) > 0) {
|
||||
newestByType.put(measureTypeKey, measure);
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(newestByType.values());
|
||||
}
|
||||
|
||||
private Optional<Double> extractDuty(GoodsMeasuresForWsResponse.Measures.Measure measure) {
|
||||
|
||||
var dutyRate = measure.getDutyRate();
|
||||
|
||||
if(dutyRate == null) return Optional.empty();
|
||||
|
||||
if (dutyRate.trim().matches("\\d+\\.\\d+\\s*%")) {
|
||||
return Optional.of(Double.parseDouble(dutyRate.trim().replace("%", "").trim()) / 100);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ import de.avatic.lcc.service.users.AuthorizationService;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
|
|
@ -84,7 +85,7 @@ public class ChangeMaterialService {
|
|||
for (var premise : premisesToProcess) {
|
||||
var countryId = dto.isUserSupplierNode() ? userNodeRepository.getById(premise.getUserSupplierNodeId()).orElseThrow().getCountryId() : nodeRepository.getById(premise.getSupplierNodeId()).orElseThrow().getCountryId();
|
||||
var tariffRate = customApiService.getTariffRate(material.getHsCode(), countryId);
|
||||
premiseRepository.updateMaterial(Collections.singletonList(premise.getId()), material.getHsCode(), tariffRate);
|
||||
premiseRepository.updateMaterial(Collections.singletonList(premise.getId()), material.getHsCode(), BigDecimal.valueOf(tariffRate.getValue()));
|
||||
|
||||
if (!dto.isUserSupplierNode()) {
|
||||
var packaging = packagingRepository.getByMaterialIdAndSupplierId(dto.getMaterialId(), premise.getSupplierNodeId());
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ public class ChangeSupplierService {
|
|||
if (dto.isUpdateMasterData()) {
|
||||
for (var premise : premisesToProcess) {
|
||||
var tariffRate = customApiService.getTariffRate(premise.getHsCode(), supplier.getCountryId());
|
||||
premiseRepository.updateTariffRate(premise.getId(), tariffRate);
|
||||
premiseRepository.updateTariffRate(premise.getId(), tariffRate.getValue());
|
||||
|
||||
if (!dto.isUserSupplierNode()) {
|
||||
var packaging = packagingRepository.getByMaterialIdAndSupplierId(premise.getMaterialId(), supplierNodeId);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package de.avatic.lcc.service.calculation;
|
||||
|
||||
import de.avatic.lcc.repositories.NomenclatureRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class NomenclatureService {
|
||||
|
||||
private final NomenclatureRepository nomenclatureRepository;
|
||||
|
||||
public NomenclatureService(NomenclatureRepository nomenclatureRepository) {
|
||||
this.nomenclatureRepository = nomenclatureRepository;
|
||||
}
|
||||
|
||||
|
||||
public List<String> getNomenclature(String hsCode) {
|
||||
return nomenclatureRepository.searchHsCode(hsCode);
|
||||
}
|
||||
}
|
||||
|
|
@ -124,7 +124,7 @@ public class PremiseCreationService {
|
|||
}
|
||||
|
||||
var material = materialRepository.getById(p.getMaterialId());
|
||||
material.ifPresent(value -> premiseRepository.updateMaterial(Collections.singletonList(p.getId()), value.getHsCode(), customApiService.getTariffRate(value.getHsCode(), getCountryId(p))));
|
||||
material.ifPresent(value -> premiseRepository.updateMaterial(Collections.singletonList(p.getId()), value.getHsCode(), BigDecimal.valueOf(customApiService.getTariffRate(value.getHsCode(), getCountryId(p)).getValue())));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public class CustomCostCalculationService {
|
|||
var shippingFrequency = shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount);
|
||||
var customFee = Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.CUSTOM_FEE, setId).orElseThrow().getCurrentValue());
|
||||
|
||||
var tariffRate = premise.getTariffRate() == null ? customApiService.getTariffRate(premise.getHsCode(), premise.getCountryId()) : premise.getTariffRate();
|
||||
var tariffRate = premise.getTariffRate();
|
||||
|
||||
var materialCost = premise.getMaterialCost().multiply(BigDecimal.valueOf(destination.getAnnualAmount()));
|
||||
var fcaFee = BigDecimal.ZERO;
|
||||
|
|
|
|||
|
|
@ -23,4 +23,7 @@ spring.flyway.baseline-on-migrate=true
|
|||
spring.sql.init.mode=never
|
||||
|
||||
lcc.allowed_cors=
|
||||
lcc.allowed_oauth_token_cors=*
|
||||
lcc.allowed_oauth_token_cors=*
|
||||
|
||||
logging.level.org.springframework.ws=DEBUG
|
||||
logging.level.org.springframework.oxm=DEBUG
|
||||
16929
src/main/resources/db/migration/V11__Nomenclature.sql
Normal file
16929
src/main/resources/db/migration/V11__Nomenclature.sql
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -59,6 +59,13 @@ CREATE TABLE IF NOT EXISTS `country`
|
|||
CHECK (`region_code` IN ('EMEA', 'LATAM', 'APAC', 'NAM'))
|
||||
) COMMENT 'Master data table for country information and regional classification';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `nomenclature`
|
||||
(
|
||||
`hs_code` VARCHAR(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
UNIQUE KEY `uk_nomenclature_name` (`hs_code`)
|
||||
) COMMENT 'Master data table for nomenclature information';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `country_property_type`
|
||||
(
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
|
|
|
|||
85
src/main/resources/wsdl/goods.wsdl
Normal file
85
src/main/resources/wsdl/goods.wsdl
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.3.0-wls122140-b230824.1031 svn-revision#e4bad6ac24018736698e2952f77e76e7f403a9f1. -->
|
||||
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://goodsNomenclatureForWS.ws.taric.dds.s/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://goodsNomenclatureForWS.ws.taric.dds.s/" name="GoodsNomenclatureForWS">
|
||||
<wsdl:types>
|
||||
<xsd:schema xmlns:ns0="http://goodsNomenclatureForWS.ws.taric.dds.s/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://goodsNomenclatureForWS.ws.taric.dds.s/">
|
||||
<xsd:include schemaLocation="https://ec.europa.eu/taxation_customs/dds2/taric/services/goods?xsd=1"/>
|
||||
<xsd:complexType name="goodsDescrForWs">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="ns0:goodsCode"/>
|
||||
<xsd:element ref="ns0:languageCode"/>
|
||||
<xsd:element ref="ns0:referenceDate" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="goodsDescrForWsResponse">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="return" type="ns0:goodsDescriptionForWsResult" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:element name="goodsDescrForWsResponse" type="ns0:goodsDescrForWsResponse"/>
|
||||
<xsd:element name="goodsDescrForWs" type="ns0:goodsDescrForWs"/>
|
||||
<xsd:complexType name="goodsMeasForWs">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="ns0:goodsCode"/>
|
||||
<xsd:element ref="ns0:countryCode"/>
|
||||
<xsd:element ref="ns0:referenceDate" minOccurs="0"/>
|
||||
<xsd:element ref="ns0:tradeMovement" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="goodsMeasForWsResponse">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="return" type="ns0:goodsMeasuresForWsResult" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:element name="goodsMeasForWsResponse" type="ns0:goodsMeasForWsResponse"/>
|
||||
<xsd:element name="goodsMeasForWs" type="ns0:goodsMeasForWs"/>
|
||||
</xsd:schema>
|
||||
</wsdl:types>
|
||||
<wsdl:message name="goodsDescrForWs">
|
||||
<wsdl:part name="parameters" element="tns:goodsDescrForWs"/>
|
||||
</wsdl:message>
|
||||
<wsdl:message name="goodsDescrForWsResponse">
|
||||
<wsdl:part name="parameters" element="tns:goodsDescrForWsResponse"/>
|
||||
</wsdl:message>
|
||||
<wsdl:message name="goodsMeasForWs">
|
||||
<wsdl:part name="parameters" element="tns:goodsMeasForWs"/>
|
||||
</wsdl:message>
|
||||
<wsdl:message name="goodsMeasForWsResponse">
|
||||
<wsdl:part name="parameters" element="tns:goodsMeasForWsResponse"/>
|
||||
</wsdl:message>
|
||||
<wsdl:portType name="GoodsNomenclatureForWs">
|
||||
<wsdl:operation name="goodsDescrForWs">
|
||||
<wsdl:input name="goodsDescrForWs" message="tns:goodsDescrForWs"/>
|
||||
<wsdl:output name="goodsDescrForWsResponse" message="tns:goodsDescrForWsResponse"/>
|
||||
</wsdl:operation>
|
||||
<wsdl:operation name="goodsMeasForWs">
|
||||
<wsdl:input name="goodsMeasForWs" message="tns:goodsMeasForWs"/>
|
||||
<wsdl:output name="goodsMeasForWsResponse" message="tns:goodsMeasForWsResponse"/>
|
||||
</wsdl:operation>
|
||||
</wsdl:portType>
|
||||
<wsdl:binding name="GoodsNomenclatureForWsImplPortBinding" type="tns:GoodsNomenclatureForWs">
|
||||
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
|
||||
<wsdl:operation name="goodsDescrForWs">
|
||||
<soap:operation soapAction="" style="document"/>
|
||||
<wsdl:input>
|
||||
<soap:body use="literal"/>
|
||||
</wsdl:input>
|
||||
<wsdl:output>
|
||||
<soap:body use="literal"/>
|
||||
</wsdl:output>
|
||||
</wsdl:operation>
|
||||
<wsdl:operation name="goodsMeasForWs">
|
||||
<soap:operation soapAction="" style="document"/>
|
||||
<wsdl:input>
|
||||
<soap:body use="literal"/>
|
||||
</wsdl:input>
|
||||
<wsdl:output>
|
||||
<soap:body use="literal"/>
|
||||
</wsdl:output>
|
||||
</wsdl:operation>
|
||||
</wsdl:binding>
|
||||
<wsdl:service name="GoodsNomenclatureForWs">
|
||||
<wsdl:port name="GoodsNomenclatureForWsImplPort" binding="tns:GoodsNomenclatureForWsImplPortBinding">
|
||||
<soap:address location="https://ec.europa.eu/taxation_customs/dds2/taric/services/goods"/>
|
||||
</wsdl:port>
|
||||
</wsdl:service>
|
||||
</wsdl:definitions>
|
||||
Loading…
Add table
Reference in a new issue