diff --git a/.claude/settings.local.json b/.claude/settings.local.json index b290255..e3d71c4 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,8 +1,20 @@ { + "permissions": { + "allow": [ + "mcp__serena__read_file", + "mcp__serena__search_for_pattern", + "mcp__serena__find_file", + "mcp__serena__list_dir", + "mcp__serena__think_about_collected_information", + "Bash(git add:*)", + "Bash(git commit:*)", + "mcp__serena__replace_regex" + ] + }, + "enableAllProjectMcpServers": true, "enabledMcpjsonServers": [ "serena", "context7", "git" - ], - "enableAllProjectMcpServers": true + ] } diff --git a/.mcp.json b/.mcp.json index ad2686c..741d00e 100644 --- a/.mcp.json +++ b/.mcp.json @@ -1,28 +1,33 @@ { "mcpServers": { "serena": { - "command": "uvx", - "args": [ - "--from", - "git+https://github.com/oraios/serena", - "serena", - "start-mcp-server", - "--enable-web-dashboard", - "false" - ] + "command": "docker", + "args": [ + "run", + "--rm", + "-i", + "--network", "host", + "-v", "./:/workspaces/projects", + "ghcr.io/oraios/serena:0.1.4", + "serena", "start-mcp-server", + "--transport", "stdio", + "--project", "/workspaces/projects", + "--enable-web-dashboard", "false" + ], + "autoApprove": { + "commands": [ + "search_for_pattern", + "read_file", + "find_file", + "list_dir", + "think_about_collected_information", + "replace_regex" + ] + } }, "context7": { "type": "http", "url": "https://mcp.context7.com/mcp" - }, - "git": { - "command": "uvx", - "args": [ - "mcp-server-git" - ], - "env": { - "MCP_GIT_ALLOW": "/home/knee-cola/web-pro/evidencija-rezija" - } } } } \ No newline at end of file diff --git a/app/lib/actions/billActions.ts b/app/lib/actions/billActions.ts index 3a5de12..98ae03b 100644 --- a/app/lib/actions/billActions.ts +++ b/app/lib/actions/billActions.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import { getDbClient } from '../dbClient'; -import { Bill, BillAttachment, BillingLocation, YearMonth } from '../db-types'; +import { Bill, BilledTo, BillAttachment, BillingLocation, YearMonth } from '../db-types'; import { ObjectId } from 'mongodb'; import { withUser } from '@/app/lib/auth'; import { AuthenticatedUser } from '../types/next-auth'; @@ -145,6 +145,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI } = validatedFields.data; const billPaid = formData.get('billPaid') === 'on'; + const billedTo = (formData.get('billedTo') as BilledTo) ?? BilledTo.Tenant; const barcodeImage = formData.get('barcodeImage')?.valueOf() as string; // update the bill in the mongodb @@ -159,6 +160,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI const mongoDbSet = billAttachment ? { "bills.$[elem].name": billName, "bills.$[elem].paid": billPaid, + "bills.$[elem].billedTo": billedTo, "bills.$[elem].attachment": billAttachment, "bills.$[elem].notes": billNotes, "bills.$[elem].payedAmount": payedAmount, @@ -167,6 +169,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI }: { "bills.$[elem].name": billName, "bills.$[elem].paid": billPaid, + "bills.$[elem].billedTo": billedTo, "bills.$[elem].notes": billNotes, "bills.$[elem].payedAmount": payedAmount, "bills.$[elem].barcodeImage": barcodeImage, @@ -191,6 +194,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI _id: (new ObjectId()).toHexString(), name: billName, paid: billPaid, + billedTo: billedTo, attachment: billAttachment, notes: billNotes, payedAmount, @@ -254,6 +258,7 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI _id: (new ObjectId()).toHexString(), name: billName, paid: false, // New bills in subsequent months are unpaid + billedTo: BilledTo.Tenant, // Default to tenant for subsequent months attachment: null, // No attachment for subsequent months notes: billNotes, payedAmount: null, diff --git a/app/lib/actions/printActions.ts b/app/lib/actions/printActions.ts index 45616b2..6a3756f 100644 --- a/app/lib/actions/printActions.ts +++ b/app/lib/actions/printActions.ts @@ -1,7 +1,7 @@ 'use server'; import { getDbClient } from '../dbClient'; -import { BillingLocation, Bill } from '../db-types'; +import { BilledTo, BillingLocation, Bill } from '../db-types'; import { AuthenticatedUser } from '../types/next-auth'; import { withUser } from '../auth'; import { unstable_noStore as noStore } from 'next/cache'; @@ -41,7 +41,8 @@ export const fetchBarcodeDataForPrint = withUser(async (user: AuthenticatedUser, for (const location of locations) { for (const bill of location.bills) { - if (bill.barcodeImage && bill.barcodeImage.trim() !== "") { + // Only include bills that are billed to tenant and have barcode images + if (bill.barcodeImage && bill.barcodeImage.trim() !== "" && (bill.billedTo ?? BilledTo.Tenant) === BilledTo.Tenant) { printData.push({ locationName: location.name, billName: bill.name, diff --git a/app/lib/db-types.ts b/app/lib/db-types.ts index d9d6cc8..dc63601 100644 --- a/app/lib/db-types.ts +++ b/app/lib/db-types.ts @@ -31,6 +31,11 @@ export interface BillingLocation { notes: string|null; }; +export enum BilledTo { + Tenant = "tenant", + Landlord = "landlord" +} + /** Bill basic data */ export interface Bill { _id: string; @@ -38,6 +43,8 @@ export interface Bill { name: string; /** is the bill paid */ paid: boolean; + /** who is billed for the bill */ + billedTo?: BilledTo; /** payed amount amount in cents */ payedAmount?: number | null; /** attached document (optional) */ diff --git a/app/ui/BillEditForm.tsx b/app/ui/BillEditForm.tsx index 29a61a1..08343b8 100644 --- a/app/ui/BillEditForm.tsx +++ b/app/ui/BillEditForm.tsx @@ -1,7 +1,7 @@ "use client"; import { DocumentIcon, TrashIcon } from "@heroicons/react/24/outline"; -import { Bill, BillingLocation } from "../lib/db-types"; +import { Bill, BilledTo, BillingLocation } from "../lib/db-types"; import React, { FC } from "react"; import { useFormState } from "react-dom"; import { updateOrAddBill } from "../lib/actions/billActions"; @@ -29,7 +29,7 @@ export const BillEditForm:FC = ({ location, bill }) => { const t = useTranslations("bill-edit-form"); const locale = useLocale(); - const { _id: billID, name, paid, attachment, notes, payedAmount: initialPayedAmount, barcodeImage: initialBarcodeImage } = bill ?? { _id:undefined, name:"", paid:false, notes:"" }; + const { _id: billID, name, paid, billedTo = BilledTo.Tenant, attachment, notes, payedAmount: initialPayedAmount, barcodeImage: initialBarcodeImage } = bill ?? { _id:undefined, name:"", paid:false, notes:"" }; const { yearMonth:{year: billYear, month: billMonth}, _id: locationID } = location; @@ -40,10 +40,16 @@ export const BillEditForm:FC = ({ location, bill }) => { const [ isScanningPDF, setIsScanningPDF ] = React.useState(false); const [ state, dispatch ] = useFormState(handleAction, initialState); const [ isPaid, setIsPaid ] = React.useState(paid); + const [ billedToValue, setBilledToValue ] = React.useState(billedTo); const [ payedAmount, setPayedAmount ] = React.useState(initialPayedAmount ? `${initialPayedAmount/100}` : "" ); const [ barcodeImage, setBarcodeImage ] = React.useState(initialBarcodeImage); const [ barcodeResults, setBarcodeResults ] = React.useState | null>(null); + + const billedTo_handleChange = (event: React.ChangeEvent) => { + setBilledToValue(event.target.value as BilledTo); + } + const billPaid_handleChange = (event: React.ChangeEvent) => { setIsPaid(event.target.checked); } @@ -202,9 +208,37 @@ export const BillEditForm:FC = ({ location, bill }) => { ))} +
+
+ {t("billed-to-label")} + + +
+
+ {/* Show toggle only when adding a new bill (not editing) */} {!bill && ( -
+