feat: enhance forms with decimal formatting and validation

- Updated CustomersPage.vue to use decimalString for standard discount percent.
- Enhanced IncomingInvoicesPage.vue to format item quantities, unit prices, and tax rates using decimalString.
- Improved ItemsPage.vue with new supplier price management and decimal formatting for prices.
- Modified OrganizationSetupPage.vue to use a dropdown for default tax rates and ensure numeric input for payment days.
- Updated OutgoingInvoicesPage.vue to apply decimal formatting for customer discounts and item details.
- Enhanced PriceImportsPage.vue to include additional fields in the import format.
- Improved PriceRulesPage.vue to use decimal input for markup percentages.
- Updated QuotesPage.vue to apply decimal formatting for customer discounts and item details.
- Enhanced SuppliersPage.vue to use decimal input for standard discount percent.
- Added a new SQL migration to set default unit for items to 'Stck'.
- Introduced format.ts for centralized decimal and currency formatting utilities.
This commit is contained in:
Torsten Schulz (local)
2026-06-03 09:25:10 +02:00
parent 0e539710c0
commit d5b6f39177
22 changed files with 1420 additions and 183 deletions

View File

@@ -3,6 +3,7 @@ import { computed, onMounted, reactive, ref, watch } from "vue";
import { apiDelete, apiGet, apiPost, apiPut } from "../api";
import FormStatus from "../components/FormStatus.vue";
import PageHeader from "../components/PageHeader.vue";
import { decimalString } from "../format";
import { matchesObjectSearch, reserveNextNumber } from "../number-ranges";
import { liveUpdateState } from "../realtime";
import type { CashDiscountTerm, Customer } from "../types";
@@ -73,9 +74,13 @@ function selectCustomer(customer: Customer) {
async function save() {
pending.value = true;
const payload = {
...form,
standard_discount_percent: decimalString(form.standard_discount_percent)
};
const result = selectedId.value
? await apiPut<Customer>(`/api/v1/customers/${encodeURIComponent(selectedId.value)}`, form)
: await apiPost<Customer>("/api/v1/customers", form);
? await apiPut<Customer>(`/api/v1/customers/${encodeURIComponent(selectedId.value)}`, payload)
: await apiPost<Customer>("/api/v1/customers", payload);
pending.value = false;
if (!result.ok) {
status.value = result.message;
@@ -145,7 +150,7 @@ watch(
<option value="blocked">Gesperrt</option>
</select>
</label>
<label class="field"><span>Standardrabatt %</span><input v-model="form.standard_discount_percent" type="number" min="0" max="100" step="0.01" required /></label>
<label class="field"><span>Standardrabatt %</span><input v-model="form.standard_discount_percent" inputmode="decimal" required /></label>
<label class="field">
<span>Skonto-Regel</span>
<select v-model="form.cash_discount_term_id">