Rechnungsdatum und Belegupload ueberarbeiten
All checks were successful
CI / Build (push) Successful in 1m59s
CI / Deploy (push) Successful in 2m2s

This commit is contained in:
jan
2026-05-01 16:51:27 +02:00
parent 549c8f16c6
commit 796e134ea2
14 changed files with 165 additions and 95 deletions

View File

@@ -50,7 +50,7 @@ type BudgetColumnProps = {
onApprove: (expenseId: string, approvalType: "CHAIR_A" | "CHAIR_B" | "FINANCE") => Promise<void>;
onMarkPaid: (expenseId: string) => Promise<void>;
onDocument: (expenseId: string, proofUrl?: string) => Promise<void>;
onUploadProof: (expenseId: string, file: File) => Promise<string>;
onUploadProof: (expenseId: string, file: File, invoiceDate: string) => Promise<string>;
onSaveWorkingGroup: (groupId: string, name: string) => Promise<void>;
onDeleteWorkingGroup: (groupId: string, groupName: string) => Promise<void>;
onSaveBudget: (budgetId: string, name: string, totalBudget: string, colorCode: string) => Promise<void>;
@@ -155,8 +155,8 @@ export function BudgetColumn({
const [editingBudgetId, setEditingBudgetId] = useState<string | null>(null);
const [isEditingGroup, setIsEditingGroup] = useState(false);
const [groupDraftName, setGroupDraftName] = useState(group.name);
const [proofUrlDrafts, setProofUrlDrafts] = useState<Record<string, string>>({});
const [proofFileDrafts, setProofFileDrafts] = useState<Record<string, File | null>>({});
const [invoiceDateDrafts, setInvoiceDateDrafts] = useState<Record<string, string>>({});
const [expandedRecurringExpenses, setExpandedRecurringExpenses] = useState<Record<string, boolean>>({});
const budgetCardWidth = 352;
@@ -756,16 +756,23 @@ export function BudgetColumn({
) : null}
{expense.proofUrl ? (
<Link
href={expense.proofUrl}
target="_blank"
rel="noreferrer"
underline="hover"
variant="body2"
sx={{ overflowWrap: "anywhere" }}
>
{"Beleg \u00f6ffnen"}
</Link>
<Stack spacing={0.4}>
<Link
href={expense.proofUrl}
target="_blank"
rel="noreferrer"
underline="hover"
variant="body2"
sx={{ overflowWrap: "anywhere" }}
>
{"Rechnungsdokument \u00f6ffnen"}
</Link>
{expense.invoiceDate ? (
<Typography variant="caption" color="text.secondary">
Rechnung vom {dateFormatter.format(new Date(expense.invoiceDate))}
</Typography>
) : null}
</Stack>
) : null}
<Stack direction="row" gap={1} useFlexGap flexWrap="wrap">
@@ -791,7 +798,12 @@ export function BudgetColumn({
</Button>
))}
{!expense.paidAt && expense.approvalStatus === "APPROVED" && canMarkPaid(viewer.role) ? (
{!expense.paidAt &&
expense.approvalStatus === "APPROVED" &&
expense.proofUrl &&
expense.invoiceDate &&
expense.documentedAt &&
canMarkPaid(viewer.role) ? (
<Button
size="small"
variant="outlined"
@@ -829,8 +841,25 @@ export function BudgetColumn({
) : null}
</Stack>
{expense.paidAt && !expense.documentedAt && canDocumentExpense(viewer.role) ? (
<Stack direction={{ xs: "column", sm: "row" }} gap={1}>
{!expense.paidAt &&
expense.approvalStatus === "APPROVED" &&
!expense.proofUrl &&
canDocumentExpense(viewer.role) ? (
<Stack direction={{ xs: "column", sm: "row" }} gap={1} alignItems={{ sm: "center" }}>
<TextField
label="Rechnungsdatum"
type="date"
value={invoiceDateDrafts[expense.id] ?? ""}
onChange={(event) =>
setInvoiceDateDrafts((current) => ({
...current,
[expense.id]: event.target.value
}))
}
InputLabelProps={{ shrink: true }}
size="small"
required
/>
<TextField
label="Beleg"
value={proofFileDrafts[expense.id]?.name ?? expense.proofUrl ?? ""}
@@ -874,14 +903,17 @@ export function BudgetColumn({
disabled={busy}
onClick={async () => {
const proofFile = proofFileDrafts[expense.id];
const proofUrl = proofFile
? await onUploadProof(expense.id, proofFile)
: proofUrlDrafts[expense.id] ?? expense.proofUrl ?? undefined;
const invoiceDate = invoiceDateDrafts[expense.id] ?? "";
await onDocument(expense.id, proofUrl);
if (!proofFile || !invoiceDate) {
return;
}
await onUploadProof(expense.id, proofFile, invoiceDate);
await onMarkPaid(expense.id);
}}
>
Dokumentieren
Rechnung abgeben und bezahlt setzen
</Button>
</Stack>
) : null}