u
This commit is contained in:
@@ -196,7 +196,7 @@ class KreditorTable extends Component {
|
|||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.authService.apiCall(`/admin/kreditoren/${kreditor.id}`, {
|
const response = await this.authService.apiCall(`/admin/kreditoren/${itemToDelete.id}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -350,7 +350,15 @@ const DocumentRenderer = (params) => {
|
|||||||
aria-describedby="document-dialog-content"
|
aria-describedby="document-dialog-content"
|
||||||
>
|
>
|
||||||
<DialogTitle id="document-dialog-title">
|
<DialogTitle id="document-dialog-title">
|
||||||
{hasDocuments ? `Dokumente (${totalCount})` : 'Dokumentinformationen'}
|
{(() => {
|
||||||
|
const beschreibung = params?.data?.description || '';
|
||||||
|
const beschreibungTrimmed = beschreibung ? String(beschreibung).slice(0, 120) : '';
|
||||||
|
if (hasDocuments) {
|
||||||
|
return `Dokumente (${totalCount})${beschreibungTrimmed ? ' — ' + beschreibungTrimmed : ''}`;
|
||||||
|
}
|
||||||
|
// No documents: still include description next to "Dokumentinformationen"
|
||||||
|
return `Dokumentinformationen${beschreibungTrimmed ? ' — ' + beschreibungTrimmed : ''}`;
|
||||||
|
})()}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent sx={{ p: 0 }} id="document-dialog-content">
|
<DialogContent sx={{ p: 0 }} id="document-dialog-content">
|
||||||
{error && (
|
{error && (
|
||||||
@@ -367,13 +375,13 @@ const DocumentRenderer = (params) => {
|
|||||||
sx={{
|
sx={{
|
||||||
color: !params.data['Kontonummer/IBAN']
|
color: !params.data['Kontonummer/IBAN']
|
||||||
? 'text.secondary'
|
? 'text.secondary'
|
||||||
: params.data.hasKreditor
|
: (params.data.hasKreditor && params.data.kreditor && !params.data.kreditor.is_banking)
|
||||||
? 'success.main'
|
? 'success.main'
|
||||||
: 'warning.main',
|
: 'warning.main',
|
||||||
'&.Mui-selected': {
|
'&.Mui-selected': {
|
||||||
color: !params.data['Kontonummer/IBAN']
|
color: !params.data['Kontonummer/IBAN']
|
||||||
? 'text.secondary'
|
? 'text.secondary'
|
||||||
: params.data.hasKreditor
|
: (params.data.hasKreditor && params.data.kreditor && !params.data.kreditor.is_banking)
|
||||||
? 'success.main'
|
? 'success.main'
|
||||||
: 'warning.main',
|
: 'warning.main',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
class KreditorService {
|
class KreditorService {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
// API is mounted under /api (see src/index.js). Keep consistent with AuthService.
|
||||||
this.baseURL = '/api';
|
this.baseURL = '/api';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +46,8 @@ class KreditorService {
|
|||||||
|
|
||||||
async getAllKreditors() {
|
async getAllKreditors() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${this.baseURL}/data/kreditors`, {
|
const url = `${this.baseURL}/data/kreditors`;
|
||||||
|
const response = await fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: await this.getAuthHeaders(),
|
headers: await this.getAuthHeaders(),
|
||||||
});
|
});
|
||||||
@@ -53,19 +55,23 @@ class KreditorService {
|
|||||||
return await this.handleResponse(response);
|
return await this.handleResponse(response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching kreditors:', error);
|
console.error('Error fetching kreditors:', error);
|
||||||
|
|
||||||
// Handle network errors
|
|
||||||
if (error instanceof TypeError && error.message.includes('fetch')) {
|
if (error instanceof TypeError && error.message.includes('fetch')) {
|
||||||
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convenience: find kreditor by kreditorId (string compare)
|
||||||
|
async findKreditorByCode(kreditorId) {
|
||||||
|
const all = await this.getAllKreditors();
|
||||||
|
return (all || []).find(k => String(k.kreditorId).trim() === String(kreditorId).trim());
|
||||||
|
}
|
||||||
|
|
||||||
async getKreditorById(id) {
|
async getKreditorById(id) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${this.baseURL}/data/kreditors/${id}`, {
|
const url = `${this.baseURL}/data/kreditors/${id}`;
|
||||||
|
const response = await fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: await this.getAuthHeaders(),
|
headers: await this.getAuthHeaders(),
|
||||||
});
|
});
|
||||||
@@ -73,19 +79,18 @@ class KreditorService {
|
|||||||
return await this.handleResponse(response);
|
return await this.handleResponse(response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching kreditor:', error);
|
console.error('Error fetching kreditor:', error);
|
||||||
|
|
||||||
// Handle network errors
|
|
||||||
if (error instanceof TypeError && error.message.includes('fetch')) {
|
if (error instanceof TypeError && error.message.includes('fetch')) {
|
||||||
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async createKreditor(kreditorData) {
|
async createKreditor(kreditorData) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${this.baseURL}/data/kreditors`, {
|
const url = `${this.baseURL}/data/kreditors`;
|
||||||
|
console.debug('[KreditorService] POST', url, kreditorData);
|
||||||
|
const response = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: await this.getAuthHeaders(),
|
headers: await this.getAuthHeaders(),
|
||||||
body: JSON.stringify(kreditorData),
|
body: JSON.stringify(kreditorData),
|
||||||
@@ -93,20 +98,23 @@ class KreditorService {
|
|||||||
|
|
||||||
return await this.handleResponse(response);
|
return await this.handleResponse(response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Map unique constraint errors to a clearer duplicate message when possible
|
||||||
|
const msg = (error && error.message) || '';
|
||||||
|
if (/unique|bereits vorhanden|already exists|kreditor/i.test(msg)) {
|
||||||
|
throw new Error('Kreditor bereits vorhanden');
|
||||||
|
}
|
||||||
console.error('Error creating kreditor:', error);
|
console.error('Error creating kreditor:', error);
|
||||||
|
|
||||||
// Handle network errors
|
|
||||||
if (error instanceof TypeError && error.message.includes('fetch')) {
|
if (error instanceof TypeError && error.message.includes('fetch')) {
|
||||||
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateKreditor(id, kreditorData) {
|
async updateKreditor(id, kreditorData) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${this.baseURL}/data/kreditors/${id}`, {
|
const url = `${this.baseURL}/data/kreditors/${id}`;
|
||||||
|
const response = await fetch(url, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: await this.getAuthHeaders(),
|
headers: await this.getAuthHeaders(),
|
||||||
body: JSON.stringify(kreditorData),
|
body: JSON.stringify(kreditorData),
|
||||||
@@ -115,19 +123,17 @@ class KreditorService {
|
|||||||
return await this.handleResponse(response);
|
return await this.handleResponse(response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating kreditor:', error);
|
console.error('Error updating kreditor:', error);
|
||||||
|
|
||||||
// Handle network errors
|
|
||||||
if (error instanceof TypeError && error.message.includes('fetch')) {
|
if (error instanceof TypeError && error.message.includes('fetch')) {
|
||||||
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteKreditor(id) {
|
async deleteKreditor(id) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${this.baseURL}/data/kreditors/${id}`, {
|
const url = `${this.baseURL}/data/kreditors/${id}`;
|
||||||
|
const response = await fetch(url, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: await this.getAuthHeaders(),
|
headers: await this.getAuthHeaders(),
|
||||||
});
|
});
|
||||||
@@ -135,12 +141,9 @@ class KreditorService {
|
|||||||
return await this.handleResponse(response);
|
return await this.handleResponse(response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting kreditor:', error);
|
console.error('Error deleting kreditor:', error);
|
||||||
|
|
||||||
// Handle network errors
|
|
||||||
if (error instanceof TypeError && error.message.includes('fetch')) {
|
if (error instanceof TypeError && error.message.includes('fetch')) {
|
||||||
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut');
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,4 +270,4 @@ router.delete('/buchungsschluessel/:id', authenticateToken, async (req, res) =>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@@ -143,8 +143,8 @@ router.get('/assignable-kreditors', authenticateToken, async (req, res) => {
|
|||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
SELECT id, name, kreditorId
|
SELECT id, name, kreditorId
|
||||||
FROM fibdash.Kreditor
|
FROM fibdash.Kreditor
|
||||||
WHERE is_banking = 0
|
WHERE (is_banking = 0 OR is_banking IS NULL)
|
||||||
ORDER BY name
|
ORDER BY name
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -58,8 +58,9 @@ router.post('/kreditors', authenticateToken, async (req, res) => {
|
|||||||
return res.status(400).json({ error: 'Name and kreditorId are required' });
|
return res.status(400).json({ error: 'Name and kreditorId are required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isBanking && (!iban || iban.trim() === '')) {
|
// Business rule: IBAN is required for banking kreditors (proxies), not required for real kreditors
|
||||||
return res.status(400).json({ error: 'IBAN is required (except for banking accounts)' });
|
if (isBanking && (!iban || iban.trim() === '')) {
|
||||||
|
return res.status(400).json({ error: 'IBAN is required for banking kreditors' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iban && iban.trim() !== '') {
|
if (iban && iban.trim() !== '') {
|
||||||
@@ -108,8 +109,9 @@ router.put('/kreditors/:id', authenticateToken, async (req, res) => {
|
|||||||
return res.status(400).json({ error: 'Name and kreditorId are required' });
|
return res.status(400).json({ error: 'Name and kreditorId are required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isBanking && (!iban || iban.trim() === '')) {
|
// Business rule: IBAN is required for banking kreditors (proxies), not required for real kreditors
|
||||||
return res.status(400).json({ error: 'IBAN is required (except for banking accounts)' });
|
if (isBanking && (!iban || iban.trim() === '')) {
|
||||||
|
return res.status(400).json({ error: 'IBAN is required for banking kreditors' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkQuery = `SELECT id FROM fibdash.Kreditor WHERE id = @id`;
|
const checkQuery = `SELECT id FROM fibdash.Kreditor WHERE id = @id`;
|
||||||
|
|||||||
Reference in New Issue
Block a user