seperate delivery and billig adresses in contract added

This commit is contained in:
dufyfduck 2026-02-04 08:48:25 +01:00
parent fdef6d1d3b
commit 312e879221
15 changed files with 922 additions and 216 deletions

File diff suppressed because one or more lines are too long

View File

@ -405,6 +405,7 @@ exports.Prisma.ContractScalarFieldEnum = {
status: 'status', status: 'status',
contractCategoryId: 'contractCategoryId', contractCategoryId: 'contractCategoryId',
addressId: 'addressId', addressId: 'addressId',
billingAddressId: 'billingAddressId',
bankCardId: 'bankCardId', bankCardId: 'bankCardId',
identityDocumentId: 'identityDocumentId', identityDocumentId: 'identityDocumentId',
salesPlatformId: 'salesPlatformId', salesPlatformId: 'salesPlatformId',

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
{ {
"name": "prisma-client-3c4bb688688ba372393d0bf86523c07e8b4de3ff0d9ad23a89f905f15047a1a5", "name": "prisma-client-5918fcf1a24d6a26f6b4fad7137d1ae3a684231bfa7340820c473996737deea6",
"main": "index.js", "main": "index.js",
"types": "index.d.ts", "types": "index.d.ts",
"browser": "index-browser.js", "browser": "index-browser.js",

View File

@ -148,19 +148,20 @@ enum AddressType {
} }
model Address { model Address {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
customerId Int customerId Int
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade) customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
type AddressType @default(DELIVERY_RESIDENCE) type AddressType @default(DELIVERY_RESIDENCE)
street String street String
houseNumber String houseNumber String
postalCode String postalCode String
city String city String
country String @default("Deutschland") country String @default("Deutschland")
isDefault Boolean @default(false) isDefault Boolean @default(false)
contracts Contract[] contractsAsDelivery Contract[] @relation("DeliveryAddress")
createdAt DateTime @default(now()) contractsAsBilling Contract[] @relation("BillingAddress")
updatedAt DateTime @updatedAt createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
} }
// ==================== BANK CARDS ==================== // ==================== BANK CARDS ====================
@ -481,8 +482,13 @@ model Contract {
contractCategoryId Int? contractCategoryId Int?
contractCategory ContractCategory? @relation(fields: [contractCategoryId], references: [id]) contractCategory ContractCategory? @relation(fields: [contractCategoryId], references: [id])
// Lieferadresse
addressId Int? addressId Int?
address Address? @relation(fields: [addressId], references: [id]) address Address? @relation("DeliveryAddress", fields: [addressId], references: [id])
// Rechnungsadresse (falls leer, wird Lieferadresse verwendet)
billingAddressId Int?
billingAddress Address? @relation("BillingAddress", fields: [billingAddressId], references: [id])
bankCardId Int? bankCardId Int?
bankCard BankCard? @relation(fields: [bankCardId], references: [id]) bankCard BankCard? @relation(fields: [bankCardId], references: [id])

View File

@ -405,6 +405,7 @@ exports.Prisma.ContractScalarFieldEnum = {
status: 'status', status: 'status',
contractCategoryId: 'contractCategoryId', contractCategoryId: 'contractCategoryId',
addressId: 'addressId', addressId: 'addressId',
billingAddressId: 'billingAddressId',
bankCardId: 'bankCardId', bankCardId: 'bankCardId',
identityDocumentId: 'identityDocumentId', identityDocumentId: 'identityDocumentId',
salesPlatformId: 'salesPlatformId', salesPlatformId: 'salesPlatformId',

View File

@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE `Contract` ADD COLUMN `billingAddressId` INTEGER NULL;
-- AddForeignKey
ALTER TABLE `Contract` ADD CONSTRAINT `Contract_billingAddressId_fkey` FOREIGN KEY (`billingAddressId`) REFERENCES `Address`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -158,7 +158,8 @@ model Address {
city String city String
country String @default("Deutschland") country String @default("Deutschland")
isDefault Boolean @default(false) isDefault Boolean @default(false)
contracts Contract[] contractsAsDelivery Contract[] @relation("DeliveryAddress")
contractsAsBilling Contract[] @relation("BillingAddress")
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
} }
@ -481,8 +482,13 @@ model Contract {
contractCategoryId Int? contractCategoryId Int?
contractCategory ContractCategory? @relation(fields: [contractCategoryId], references: [id]) contractCategory ContractCategory? @relation(fields: [contractCategoryId], references: [id])
// Lieferadresse
addressId Int? addressId Int?
address Address? @relation(fields: [addressId], references: [id]) address Address? @relation("DeliveryAddress", fields: [addressId], references: [id])
// Rechnungsadresse (falls leer, wird Lieferadresse verwendet)
billingAddressId Int?
billingAddress Address? @relation("BillingAddress", fields: [billingAddressId], references: [id])
bankCardId Int? bankCardId Int?
bankCard BankCard? @relation(fields: [bankCardId], references: [id]) bankCard BankCard? @relation(fields: [bankCardId], references: [id])

View File

@ -89,6 +89,7 @@ export async function getAllContracts(filters: ContractFilters) {
}, },
}, },
address: true, address: true,
billingAddress: true,
salesPlatform: true, salesPlatform: true,
cancellationPeriod: true, cancellationPeriod: true,
contractDuration: true, contractDuration: true,
@ -112,6 +113,7 @@ export async function getContractById(id: number, decryptPassword = false) {
include: { include: {
customer: true, customer: true,
address: true, address: true,
billingAddress: true,
bankCard: true, bankCard: true,
identityDocument: true, identityDocument: true,
salesPlatform: true, salesPlatform: true,
@ -163,6 +165,7 @@ interface ContractCreateData {
contractCategoryId?: number; contractCategoryId?: number;
status?: ContractStatus; status?: ContractStatus;
addressId?: number; addressId?: number;
billingAddressId?: number;
bankCardId?: number; bankCardId?: number;
identityDocumentId?: number; identityDocumentId?: number;
salesPlatformId?: number; salesPlatformId?: number;
@ -356,6 +359,7 @@ export async function createContract(data: ContractCreateData) {
include: { include: {
customer: true, customer: true,
address: true, address: true,
billingAddress: true,
salesPlatform: true, salesPlatform: true,
energyDetails: true, energyDetails: true,
internetDetails: { include: { phoneNumbers: true } }, internetDetails: { include: { phoneNumbers: true } },

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>OpenCRM</title> <title>OpenCRM</title>
<script type="module" crossorigin src="/assets/index-H1r24hX1.js"></script> <script type="module" crossorigin src="/assets/index-DCSrWwxa.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DWDTTlpk.css"> <link rel="stylesheet" crossorigin href="/assets/index-DWDTTlpk.css">
</head> </head>
<body> <body>

View File

@ -1833,9 +1833,9 @@ export default function ContractDetail() {
)} )}
{/* Linked Data */} {/* Linked Data */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6"> <div className="grid grid-cols-1 lg:grid-cols-4 gap-6 mb-6">
{c.address && ( {c.address && (
<Card title="Adresse"> <Card title="Lieferadresse">
<CopyableBlock <CopyableBlock
values={[ values={[
`${c.address.street} ${c.address.houseNumber}`, `${c.address.street} ${c.address.houseNumber}`,
@ -1853,6 +1853,35 @@ export default function ContractDetail() {
</CopyableBlock> </CopyableBlock>
</Card> </Card>
)} )}
{/* Rechnungsadresse: Falls nicht gesetzt, Lieferadresse anzeigen */}
{(c.billingAddress || c.address) && (
<Card title="Rechnungsadresse">
{(() => {
const addr = c.billingAddress || c.address;
if (!addr) return null;
return (
<CopyableBlock
values={[
`${addr.street} ${addr.houseNumber}`,
`${addr.postalCode} ${addr.city}`,
addr.country
]}
>
<p>
{addr.street} {addr.houseNumber}
</p>
<p>
{addr.postalCode} {addr.city}
</p>
<p className="text-gray-500">{addr.country}</p>
{!c.billingAddress && c.address && (
<p className="text-xs text-gray-400 mt-1">(wie Lieferadresse)</p>
)}
</CopyableBlock>
);
})()}
</Card>
)}
{c.bankCard && ( {c.bankCard && (
<Card title="Bankkarte"> <Card title="Bankkarte">
<p className="font-medium">{c.bankCard.accountHolder}</p> <p className="font-medium">{c.bankCard.accountHolder}</p>

View File

@ -207,6 +207,7 @@ export default function ContractForm() {
type: c.type, type: c.type,
status: c.status, status: c.status,
addressId: c.addressId?.toString() || '', addressId: c.addressId?.toString() || '',
billingAddressId: c.billingAddressId?.toString() || '',
bankCardId: c.bankCardId?.toString() || '', bankCardId: c.bankCardId?.toString() || '',
identityDocumentId: c.identityDocumentId?.toString() || '', identityDocumentId: c.identityDocumentId?.toString() || '',
salesPlatformId: c.salesPlatformId?.toString() || '', salesPlatformId: c.salesPlatformId?.toString() || '',
@ -422,6 +423,7 @@ export default function ContractForm() {
contractCategoryId: selectedCategory.id, contractCategoryId: selectedCategory.id,
status: data.status, status: data.status,
addressId: safeParseInt(data.addressId) ?? null, addressId: safeParseInt(data.addressId) ?? null,
billingAddressId: safeParseInt(data.billingAddressId) ?? null,
bankCardId: safeParseInt(data.bankCardId) ?? null, bankCardId: safeParseInt(data.bankCardId) ?? null,
identityDocumentId: safeParseInt(data.identityDocumentId) ?? null, identityDocumentId: safeParseInt(data.identityDocumentId) ?? null,
salesPlatformId: safeParseInt(data.salesPlatformId) ?? null, salesPlatformId: safeParseInt(data.salesPlatformId) ?? null,
@ -658,16 +660,31 @@ export default function ContractForm() {
{customerId && ( {customerId && (
<Card className="mb-6" title="Kundendaten verknüpfen"> <Card className="mb-6" title="Kundendaten verknüpfen">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<Select <Select
label="Adresse" label="Lieferadresse"
{...register('addressId')} {...register('addressId')}
options={addresses.map((a) => ({ options={addresses
value: a.id, .filter((a) => a.type === 'DELIVERY_RESIDENCE')
label: `${a.street} ${a.houseNumber}, ${a.postalCode} ${a.city} (${a.type === 'BILLING' ? 'Rechnung' : 'Liefer'})`, .map((a) => ({
}))} value: a.id,
label: `${a.street} ${a.houseNumber}, ${a.postalCode} ${a.city}`,
}))}
/> />
<Select
label="Rechnungsadresse"
{...register('billingAddressId')}
options={addresses
.filter((a) => a.type === 'BILLING')
.map((a) => ({
value: a.id,
label: `${a.street} ${a.houseNumber}, ${a.postalCode} ${a.city}`,
}))}
placeholder="Wie Lieferadresse"
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<Select <Select
label="Bankkarte" label="Bankkarte"
{...register('bankCardId')} {...register('bankCardId')}

View File

@ -274,6 +274,8 @@ export interface Contract {
status: ContractStatus; status: ContractStatus;
addressId?: number; addressId?: number;
address?: Address; address?: Address;
billingAddressId?: number;
billingAddress?: Address;
bankCardId?: number; bankCardId?: number;
bankCard?: BankCard; bankCard?: BankCard;
identityDocumentId?: number; identityDocumentId?: number;