srtu
This commit is contained in:
parent
0edd84923c
commit
a6151c6da8
@ -204,7 +204,8 @@ router.post('/members/:id/update', requireAdmin, async (req, res) => {
|
||||
const {
|
||||
salutation, title, first_name, last_name, birth_date,
|
||||
email, phone, street, address_addition, zip, city,
|
||||
bank_name, account_holder, iban, tariff_id, status
|
||||
bank_name, account_holder, iban, tariff_id, status,
|
||||
agreed_price, agreed_duration
|
||||
} = req.body;
|
||||
try {
|
||||
await db.query(`
|
||||
|
||||
@ -127,15 +127,17 @@ router.post('/submit-membership', async (req, res) => {
|
||||
INSERT INTO memberships
|
||||
(tariff_id, salutation, title, first_name, last_name, birth_date, email, phone,
|
||||
street, address_addition, zip, city, bank_name, account_holder, iban,
|
||||
sepa_accepted, agb_accepted, datenschutz_accepted, data_correct, guardian_consent, is_minor, access_token)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
sepa_accepted, agb_accepted, datenschutz_accepted, data_correct, guardian_consent, is_minor, access_token,
|
||||
agreed_price, agreed_duration)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, [
|
||||
tariff_id, salutation, title || '', first_name, last_name, birth_date,
|
||||
email, phone || '', street, address_addition || '', zip, city,
|
||||
bank_name || '', account_holder || '', iban || '',
|
||||
sepa_accepted ? 1 : 0, agb_accepted ? 1 : 0,
|
||||
datenschutz_accepted ? 1 : 0, data_correct ? 1 : 0,
|
||||
guardian_consent ? 1 : 0, is_minor, access_token
|
||||
guardian_consent ? 1 : 0, is_minor, access_token,
|
||||
tariffs[0].price_monthly, tariffs[0].duration_months
|
||||
]);
|
||||
|
||||
res.json({ success: true });
|
||||
|
||||
@ -13,6 +13,9 @@ function calcInvoiceAmount(member, period) {
|
||||
// Pausiert → 0€
|
||||
if (member.status === 'paused') return 0;
|
||||
|
||||
// Vereinbarten Preis verwenden (nicht den aktuellen Tarif-Preis!)
|
||||
const price = parseFloat(member.agreed_price || member.price_monthly);
|
||||
|
||||
// Erster Monat (anteilig)?
|
||||
const firstPeriod = member.first_payment_date
|
||||
? member.first_payment_date.toISOString().substring(0, 7)
|
||||
@ -22,7 +25,7 @@ function calcInvoiceAmount(member, period) {
|
||||
return parseFloat(member.first_payment_amt);
|
||||
}
|
||||
|
||||
return parseFloat(member.price_monthly);
|
||||
return price;
|
||||
}
|
||||
|
||||
// Periode als lesbarer Text: "2026-04" → "April 2026"
|
||||
@ -74,7 +77,8 @@ router.get('/', requireAdmin, async (req, res) => {
|
||||
|
||||
// Vorschau: Mitglieder die noch keine Rechnung für diese Periode haben
|
||||
const [eligible] = await db.query(`
|
||||
SELECT m.*, t.price_monthly, t.name as tariff_name
|
||||
SELECT m.*, t.price_monthly, t.name as tariff_name,
|
||||
COALESCE(m.agreed_price, t.price_monthly) as agreed_price
|
||||
FROM memberships m
|
||||
JOIN tariffs t ON m.tariff_id = t.id
|
||||
WHERE m.status IN ('active','paused')
|
||||
@ -119,7 +123,8 @@ router.post('/run', requireAdmin, async (req, res) => {
|
||||
|
||||
// Alle aktiven/pausierten Mitglieder im Vertragszeitraum
|
||||
const [members] = await db.query(`
|
||||
SELECT m.*, t.price_monthly, t.name as tariff_name
|
||||
SELECT m.*, t.price_monthly, t.name as tariff_name,
|
||||
COALESCE(m.agreed_price, t.price_monthly) as agreed_price
|
||||
FROM memberships m
|
||||
JOIN tariffs t ON m.tariff_id = t.id
|
||||
WHERE m.status IN ('active','paused')
|
||||
|
||||
@ -200,7 +200,12 @@
|
||||
<tr>
|
||||
<td><%= m.last_name %>, <%= m.first_name %></td>
|
||||
<td><%= m.tariff_name %></td>
|
||||
<td><strong><%= Number(m.price_monthly).toFixed(2).replace('.', ',') %> €</strong></td>
|
||||
<td>
|
||||
<strong><%= Number(m.agreed_price || m.price_monthly).toFixed(2).replace('.', ',') %> €</strong>
|
||||
<% if (m.agreed_price && Number(m.agreed_price) !== Number(m.price_monthly)) { %>
|
||||
<br><small class="text-muted" title="Aktueller Tarif-Preis">Tarif: <%= Number(m.price_monthly).toFixed(2).replace('.', ',') %> €</small>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
|
||||
@ -146,6 +146,23 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="karte-row">
|
||||
<div class="karte-field">
|
||||
<label>Vereinbarter Preis/Monat <small>(vertraglich)</small></label>
|
||||
<div class="input-wrap" style="border-radius:6px">
|
||||
<input type="number" name="agreed_price" step="0.01" min="0"
|
||||
value="<%= member.agreed_price ? Number(member.agreed_price).toFixed(2) : '' %>"
|
||||
disabled class="karte-input" style="border:none;padding:5px 0">
|
||||
<span style="font-size:0.8rem;color:var(--text-muted);padding-right:8px">€</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="karte-field">
|
||||
<label>Vereinbarte Laufzeit <small>(Monate)</small></label>
|
||||
<input type="number" name="agreed_duration" min="1"
|
||||
value="<%= member.agreed_duration || '' %>"
|
||||
disabled class="karte-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="karte-row">
|
||||
<div class="karte-field">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user