diff --git a/backend/src/routes/functions.ts b/backend/src/routes/functions.ts
index e94917d..dc96bb7 100644
--- a/backend/src/routes/functions.ts
+++ b/backend/src/routes/functions.ts
@@ -100,20 +100,25 @@ export default async function functionRoutes(server: FastifyInstance) {
server.get('/functions/check-zip/:zip', async (req, reply) => {
const { zip } = req.params as { zip: string }
+ const normalizedZip = String(zip || "").replace(/\D/g, "")
- if (!zip) {
- return reply.code(400).send({ error: 'ZIP is required' })
+ if (normalizedZip.length !== 5) {
+ return reply.code(400).send({ error: 'ZIP must contain exactly 5 digits' })
}
try {
- //@ts-ignore
- const data = await server.db.select().from(citys).where(eq(citys.zip,zip))
+ const data = await server.db
+ .select()
+ .from(citys)
+ .where(eq(citys.zip, Number(normalizedZip)))
- if (!data) {
+ if (!data.length) {
return reply.code(404).send({ error: 'ZIP not found' })
}
+ const city = data[0]
+
//districtMap
const bundeslaender = [
{ code: 'DE-BW', name: 'Baden-Württemberg' },
@@ -137,9 +142,8 @@ export default async function functionRoutes(server: FastifyInstance) {
return reply.send({
- ...data,
- //@ts-ignore
- state_code: bundeslaender.find(i => i.name === data.countryName)
+ ...city,
+ state_code: bundeslaender.find(i => i.name === city.countryName)?.code || null
})
} catch (err) {
console.log(err)
diff --git a/frontend/composables/useFunctions.js b/frontend/composables/useFunctions.js
index d303e1d..51713e6 100644
--- a/frontend/composables/useFunctions.js
+++ b/frontend/composables/useFunctions.js
@@ -50,12 +50,23 @@ export const useFunctions = () => {
}
const useZipCheck = async (zip) => {
- const returnData = await useNuxtApp().$api(`/api/functions/check-zip/${zip}`, {
- method: "GET",
- })
-
- return returnData
+ const normalizedZip = String(zip || "").replace(/\D/g, "")
+ if (!normalizedZip || normalizedZip.length > 5) {
+ return null
+ }
+ const lookupZip = normalizedZip.padStart(5, "0")
+ try {
+ const data = await useNuxtApp().$api(`/api/functions/check-zip/${lookupZip}`, {
+ method: "GET",
+ })
+ return {
+ ...data,
+ zip: String(data?.zip ?? lookupZip).replace(/\D/g, "").padStart(5, "0")
+ }
+ } catch (e) {
+ return null
+ }
}
@@ -75,5 +86,5 @@ export const useFunctions = () => {
}
- return {getWorkingTimesEvaluationData, useNextNumber, useCreateTicket, useBankingGenerateLink, useZipCheck, useBankingCheckInstitutions, useBankingListRequisitions, useCreatePDF,useGetInvoiceData, useSendTelegramNotification}
-}
\ No newline at end of file
+ return {getWorkingTimesEvaluationData, useNextNumber, useBankingGenerateLink, useZipCheck, useBankingCheckInstitutions, useBankingListRequisitions, useCreatePDF}
+}
diff --git a/frontend/pages/createDocument/edit/[[id]].vue b/frontend/pages/createDocument/edit/[[id]].vue
index 33bc9ae..41eb974 100644
--- a/frontend/pages/createDocument/edit/[[id]].vue
+++ b/frontend/pages/createDocument/edit/[[id]].vue
@@ -633,6 +633,27 @@ const removePosition = (id) => {
}
+const normalizeZip = (value) => String(value || "").replace(/\D/g, "")
+
+const sanitizeAddressZipInput = () => {
+ itemInfo.value.address.zip = normalizeZip(itemInfo.value.address.zip)
+}
+
+const checkAddressZip = async () => {
+ const zip = normalizeZip(itemInfo.value.address.zip)
+ itemInfo.value.address.zip = zip
+
+ if (![4, 5].includes(zip.length)) return
+
+ const zipData = await useFunctions().useZipCheck(zip)
+ if (zipData?.zip) {
+ itemInfo.value.address.zip = zipData.zip
+ }
+ if (zipData?.short) {
+ itemInfo.value.address.city = zipData.short
+ }
+}
+
const findDocumentErrors = computed(() => {
let errors = []
@@ -640,15 +661,15 @@ const findDocumentErrors = computed(() => {
if (itemInfo.value.contact === null) errors.push({message: "Es ist kein Kontakt ausgewählt", type: "info"})
if (itemInfo.value.letterhead === null) errors.push({message: "Es ist kein Briefpapier ausgewählt", type: "breaking"})
if (itemInfo.value.created_by === null || !itemInfo.value.created_by) errors.push({message: "Es ist kein Mitarbeiter ausgewählt", type: "breaking"})
- if (itemInfo.value.address.street === null) errors.push({
+ if (!itemInfo.value.address.street) errors.push({
message: "Es ist keine Straße im Adressat angegeben",
type: "breaking"
})
- if (itemInfo.value.address.zip === null) errors.push({
+ if (!itemInfo.value.address.zip) errors.push({
message: "Es ist keine Postleitzahl im Adressat angegeben",
type: "breaking"
})
- if (itemInfo.value.address.city === null) errors.push({
+ if (!itemInfo.value.address.city) errors.push({
message: "Es ist keine Stadt im Adressat angegeben",
type: "breaking"
})
@@ -1893,6 +1914,11 @@ const setRowData = async (row, service = {sellingPriceComposed: {}}, product = {
@@ -3177,4 +3203,4 @@ td {
height: 80vh;
}
-
\ No newline at end of file
+
diff --git a/frontend/pages/staff/profiles/[id].vue b/frontend/pages/staff/profiles/[id].vue
index 508f94c..1735daa 100644
--- a/frontend/pages/staff/profiles/[id].vue
+++ b/frontend/pages/staff/profiles/[id].vue
@@ -109,8 +109,11 @@ function recalculateWeeklyHours() {
const checkZip = async () => {
const zipData = await useFunctions().useZipCheck(profile.value.address_zip)
- profile.value.address_city = zipData.short
- profile.value.state_code = zipData.state_code
+ if (zipData) {
+ profile.value.address_zip = zipData.zip || profile.value.address_zip
+ profile.value.address_city = zipData.short
+ profile.value.state_code = zipData.state_code
+ }
}
onMounted(fetchProfile)
@@ -314,5 +317,3 @@ onMounted(fetchProfile)
-
-
diff --git a/frontend/stores/data.js b/frontend/stores/data.js
index 738c6b5..1206ac1 100644
--- a/frontend/stores/data.js
+++ b/frontend/stores/data.js
@@ -333,10 +333,14 @@ export const useDataStore = defineStore('data', () => {
{
key: "infoData.zip",
label: "Postleitzahl",
- inputType: "number",
+ inputType: "text",
inputChangeFunction: async function (row) {
- if(row.infoData.zip) {
- row.infoData.city = (await useFunctions().useZipCheck(row.infoData.zip)).short
+ const zip = String(row.infoData.zip || "").replace(/\D/g, "")
+ row.infoData.zip = zip
+ if ([4, 5].includes(zip.length)) {
+ const zipData = await useFunctions().useZipCheck(zip)
+ row.infoData.zip = zipData?.zip || row.infoData.zip
+ row.infoData.city = zipData?.short || row.infoData.city
}
},
disabledInTable: true,
@@ -1291,11 +1295,15 @@ export const useDataStore = defineStore('data', () => {
{
key: "infoData.zip",
label: "Postleitzahl",
- inputType: "number",
+ inputType: "text",
disabledInTable: true,
inputChangeFunction: async function (row) {
- if(row.infoData.zip) {
- row.infoData.city = (await useFunctions().useZipCheck(row.infoData.zip)).short
+ const zip = String(row.infoData.zip || "").replace(/\D/g, "")
+ row.infoData.zip = zip
+ if ([4, 5].includes(zip.length)) {
+ const zipData = await useFunctions().useZipCheck(zip)
+ row.infoData.zip = zipData?.zip || row.infoData.zip
+ row.infoData.city = zipData?.short || row.infoData.city
}
},
},
@@ -1474,12 +1482,16 @@ export const useDataStore = defineStore('data', () => {
{
key: "info_data.zip",
label: "Postleitzahl",
- inputType: "number",
+ inputType: "text",
disabledInTable: true,
inputColumn: "Ort",
inputChangeFunction: async function (row) {
- if(row.infoData.zip) {
- row.infoData.city = (await useFunctions().useZipCheck(row.infoData.zip)).short
+ const zip = String(row.info_data.zip || "").replace(/\D/g, "")
+ row.info_data.zip = zip
+ if ([4, 5].includes(zip.length)) {
+ const zipData = await useFunctions().useZipCheck(zip)
+ row.info_data.zip = zipData?.zip || row.info_data.zip
+ row.info_data.city = zipData?.short || row.info_data.city
}
},
},
@@ -2617,4 +2629,4 @@ export const useDataStore = defineStore('data', () => {
dataTypes,
documentTypesForCreation,
}
-})
\ No newline at end of file
+})