Added discounts to invoices
Some checks failed
Docker Deploy / build-and-push (push) Has been cancelled
Some checks failed
Docker Deploy / build-and-push (push) Has been cancelled
This commit is contained in:
@@ -4,12 +4,7 @@ import { invoices, members } from "../../../../db/schema";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { recalculateInvoiceTotals } from "../../../../utils/invoice";
|
||||
|
||||
export const POST: APIRoute = async ({
|
||||
request,
|
||||
redirect,
|
||||
locals,
|
||||
params,
|
||||
}) => {
|
||||
export const POST: APIRoute = async ({ request, redirect, locals, params }) => {
|
||||
const user = locals.user;
|
||||
if (!user) {
|
||||
return redirect("/login");
|
||||
@@ -38,8 +33,8 @@ export const POST: APIRoute = async ({
|
||||
.where(
|
||||
and(
|
||||
eq(members.userId, user.id),
|
||||
eq(members.organizationId, invoice.organizationId)
|
||||
)
|
||||
eq(members.organizationId, invoice.organizationId),
|
||||
),
|
||||
)
|
||||
.get();
|
||||
|
||||
@@ -53,6 +48,8 @@ export const POST: APIRoute = async ({
|
||||
const issueDateStr = formData.get("issueDate") as string;
|
||||
const dueDateStr = formData.get("dueDate") as string;
|
||||
const taxRateStr = formData.get("taxRate") as string;
|
||||
const discountType = (formData.get("discountType") as string) || "percentage";
|
||||
const discountValueStr = formData.get("discountValue") as string;
|
||||
const notes = formData.get("notes") as string;
|
||||
|
||||
if (!number || !currency || !issueDateStr || !dueDateStr) {
|
||||
@@ -64,6 +61,11 @@ export const POST: APIRoute = async ({
|
||||
const dueDate = new Date(dueDateStr);
|
||||
const taxRate = taxRateStr ? parseFloat(taxRateStr) : 0;
|
||||
|
||||
let discountValue = discountValueStr ? parseFloat(discountValueStr) : 0;
|
||||
if (discountType === "fixed") {
|
||||
discountValue = Math.round(discountValue * 100);
|
||||
}
|
||||
|
||||
await db
|
||||
.update(invoices)
|
||||
.set({
|
||||
@@ -72,6 +74,8 @@ export const POST: APIRoute = async ({
|
||||
issueDate,
|
||||
dueDate,
|
||||
taxRate,
|
||||
discountType: discountType as "percentage" | "fixed",
|
||||
discountValue,
|
||||
notes: notes || null,
|
||||
})
|
||||
.where(eq(invoices.id, invoiceId));
|
||||
|
||||
@@ -294,6 +294,15 @@ const isDraft = invoice.status === 'draft';
|
||||
<span class="text-base-content/60">Subtotal</span>
|
||||
<span class="font-medium">{formatCurrency(invoice.subtotal)}</span>
|
||||
</div>
|
||||
{(invoice.discountAmount > 0) && (
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-base-content/60">
|
||||
Discount
|
||||
{invoice.discountType === 'percentage' && ` (${invoice.discountValue}%)`}
|
||||
</span>
|
||||
<span class="font-medium text-success">-{formatCurrency(invoice.discountAmount)}</span>
|
||||
</div>
|
||||
)}
|
||||
{((invoice.taxRate ?? 0) > 0 || isDraft) && (
|
||||
<div class="flex justify-between text-sm items-center group">
|
||||
<span class="text-base-content/60 flex items-center gap-2">
|
||||
|
||||
@@ -38,6 +38,10 @@ if (!membership) {
|
||||
// Format dates for input[type="date"]
|
||||
const issueDateStr = invoice.issueDate.toISOString().split('T')[0];
|
||||
const dueDateStr = invoice.dueDate.toISOString().split('T')[0];
|
||||
|
||||
const discountValueDisplay = invoice.discountType === 'fixed'
|
||||
? (invoice.discountValue || 0) / 100
|
||||
: (invoice.discountValue || 0);
|
||||
---
|
||||
|
||||
<DashboardLayout title={`Edit ${invoice.number} - Chronus`}>
|
||||
@@ -112,6 +116,27 @@ const dueDateStr = invoice.dueDate.toISOString().split('T')[0];
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Discount -->
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-semibold">Discount</span>
|
||||
</label>
|
||||
<div class="join w-full">
|
||||
<select name="discountType" class="select select-bordered join-item">
|
||||
<option value="percentage" selected={!invoice.discountType || invoice.discountType === 'percentage'}>%</option>
|
||||
<option value="fixed" selected={invoice.discountType === 'fixed'}>Fixed</option>
|
||||
</select>
|
||||
<input
|
||||
type="number"
|
||||
name="discountValue"
|
||||
step="0.01"
|
||||
min="0"
|
||||
class="input input-bordered join-item w-full"
|
||||
value={discountValueDisplay}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tax Rate -->
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
|
||||
Reference in New Issue
Block a user