initial commit

This commit is contained in:
2024-08-15 21:55:12 +02:00
commit 7e89db7500
20 changed files with 4283 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};
+12
View File
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.
+227
View File
@@ -0,0 +1,227 @@
<script>
let invoiceData = null;
const handleFileUpload = async (event) => {
const file = event.target.files[0];
if (!file) return;
// FileReader to read the XML file
const reader = new FileReader();
reader.onload = (e) => {
const xmlText = e.target.result;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlText, 'application/xml');
// Namespace Resolver
const nsResolver = (prefix) => {
const ns = {
'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'
};
return ns[prefix] || null;
};
// Extract Invoice details
const invoiceID = xmlDoc.evaluate('//cbc:ID', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const issueDate = xmlDoc.evaluate('//cbc:IssueDate', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const dueDate = xmlDoc.evaluate('//cbc:DueDate', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const currency = xmlDoc.evaluate('//cbc:DocumentCurrencyCode', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
// Extract Supplier details
const supplierName = xmlDoc.evaluate('//cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const supplierStreet = xmlDoc.evaluate('//cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cbc:StreetName', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const supplierCity = xmlDoc.evaluate('//cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cbc:CityName', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const supplierCountry = xmlDoc.evaluate('//cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cac:Country/cbc:IdentificationCode', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
// Extract Customer details
const customerName = xmlDoc.evaluate('//cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc:Name', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const customerStreet = xmlDoc.evaluate('//cac:AccountingCustomerParty/cac:Party/cac:PostalAddress/cbc:StreetName', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const customerCity = xmlDoc.evaluate('//cac:AccountingCustomerParty/cac:Party/cac:PostalAddress/cbc:CityName', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const customerCountry = xmlDoc.evaluate('//cac:AccountingCustomerParty/cac:Party/cac:PostalAddress/cac:Country/cbc:IdentificationCode', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
// Extract Line Items
const lineItems = xmlDoc.evaluate('//cac:InvoiceLine', xmlDoc, nsResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
let items = [];
for (let i = 0; i < lineItems.snapshotLength; i++) {
const itemNode = lineItems.snapshotItem(i);
const itemDescription = xmlDoc.evaluate('cac:Item/cbc:Description', itemNode, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const itemQuantity = xmlDoc.evaluate('cbc:InvoicedQuantity', itemNode, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const itemUnitCode = xmlDoc.evaluate('cbc:InvoicedQuantity/@unitCode', itemNode, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const itemPrice = xmlDoc.evaluate('cac:Price/cbc:PriceAmount', itemNode, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const itemLineExtensionAmount = xmlDoc.evaluate('cbc:LineExtensionAmount', itemNode, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
items.push({
description: itemDescription,
quantity: itemQuantity,
unitCode: itemUnitCode,
price: itemPrice,
lineExtensionAmount: itemLineExtensionAmount
});
}
// Extract Totals
const lineExtensionAmountTotal = xmlDoc.evaluate('//cac:LegalMonetaryTotal/cbc:LineExtensionAmount', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const taxExclusiveAmount = xmlDoc.evaluate('//cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const taxInclusiveAmount = xmlDoc.evaluate('//cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
const payableAmount = xmlDoc.evaluate('//cac:LegalMonetaryTotal/cbc:PayableAmount', xmlDoc, nsResolver, XPathResult.STRING_TYPE, null).stringValue;
// Set invoiceData
invoiceData = {
invoiceID,
issueDate,
dueDate,
currency,
supplier: {
name: supplierName,
street: supplierStreet,
city: supplierCity,
country: supplierCountry
},
customer: {
name: customerName,
street: customerStreet,
city: customerCity,
country: customerCountry
},
items,
totals: {
lineExtensionAmountTotal,
taxExclusiveAmount,
taxInclusiveAmount,
payableAmount
}
};
};
reader.readAsText(file); // Read the file
};
</script>
<input type="file" accept=".xml" on:change={handleFileUpload} />
{#if invoiceData}
<div class="invoice-container">
<div class="header">
<h1>Invoice</h1>
</div>
<div class="details">
<div class="section-title">Invoice Details</div>
<div><span class="label">Invoice ID:</span> <span class="value">{invoiceData.invoiceID}</span></div>
<div><span class="label">Issue Date:</span> <span class="value">{invoiceData.issueDate}</span></div>
<div><span class="label">Due Date:</span> <span class="value">{invoiceData.dueDate}</span></div>
<div><span class="label">Currency:</span> <span class="value">{invoiceData.currency}</span></div>
</div>
<div class="details">
<div class="section-title">Supplier Details</div>
<div><span class="label">Name:</span> <span class="value">{invoiceData.supplier.name}</span></div>
<div><span class="label">Street:</span> <span class="value">{invoiceData.supplier.street}</span></div>
<div><span class="label">City:</span> <span class="value">{invoiceData.supplier.city}</span></div>
<div><span class="label">Country:</span> <span class="value">{invoiceData.supplier.country}</span></div>
</div>
<div class="details">
<div class="section-title">Customer Details</div>
<div><span class="label">Name:</span> <span class="value">{invoiceData.customer.name}</span></div>
<div><span class="label">Street:</span> <span class="value">{invoiceData.customer.street}</span></div>
<div><span class="label">City:</span> <span class="value">{invoiceData.customer.city}</span></div>
<div><span class="label">Country:</span> <span class="value">{invoiceData.customer.country}</span></div>
</div>
<div class="items">
<div class="section-title">Invoice Items</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Code</th>
<th>Price (EUR)</th>
<th>Line Extension Amount (EUR)</th>
</tr>
</thead>
<tbody>
{#each invoiceData.items as item}
<tr>
<td>{item.description}</td>
<td>{item.quantity} {item.unitCode}</td>
<td>{item.unitCode}</td>
<td>{item.price}</td>
<td>{item.lineExtensionAmount}</td>
</tr>
{/each}
</tbody>
</table>
</div>
<div class="totals">
<div><span class="label">Line Extension Amount Total:</span> <span class="value">{invoiceData.totals.lineExtensionAmountTotal}</span></div>
<div><span class="label">Tax Exclusive Amount:</span> <span class="value">{invoiceData.totals.taxExclusiveAmount}</span></div>
<div><span class="label">Tax Inclusive Amount:</span> <span class="value">{invoiceData.totals.taxInclusiveAmount}</span></div>
<div><span class="label">Payable Amount:</span> <span class="value">{invoiceData.totals.payableAmount}</span></div>
</div>
</div>
{/if}
<style>
.invoice-container {
width: 70%;
margin: 50px auto;
background-color: #fff;
padding: 20px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}
.header {
text-align: center;
margin-bottom: 20px;
}
.header h1 {
margin: 0;
font-size: 24px;
color: #333;
}
.section-title {
font-size: 18px;
color: #555;
margin-bottom: 10px;
border-bottom: 2px solid #e7e7e7;
padding-bottom: 5px;
}
.details, .items, .totals {
margin-bottom: 20px;
}
.details .label, .totals .label {
width: 30%;
display: inline-block;
color: #888;
}
.details .value, .totals .value {
width: 70%;
display: inline-block;
color: #333;
}
.items table {
width: 100%;
border-collapse: collapse;
}
.items table, .items th, .items td {
border: 1px solid #e7e7e7;
}
.items th, .items td {
padding: 10px;
text-align: left;
}
.items th {
background-color: #f8f8f8;
color: #555;
}
.totals {
text-align: right;
}
.totals .label {
font-weight: bold;
}
</style>
+195
View File
@@ -0,0 +1,195 @@
<script>
import { onMount } from 'svelte';
// Variables for storing extracted invoice data
let invoiceData = {
invoiceID: '',
issueDate: '',
dueDate: '',
currency: '',
supplier: {
name: '',
street: '',
city: '',
country: ''
},
customer: {
name: '',
street: '',
city: '',
country: ''
},
items: [],
totals: {
lineExtensionAmountTotal: '',
taxExclusiveAmount: '',
taxInclusiveAmount: '',
payableAmount: ''
}
};
// Simulating data extraction (normally from an API or file)
async function extractInvoiceData() {
// Simulating a delay as if we're fetching from an external source
await new Promise(resolve => setTimeout(resolve, 1000));
// Here you would normally extract or fetch data.
// For demonstration, we use hardcoded data.
invoiceData = {
invoiceID: "INV-12345",
issueDate: "2023-08-01",
dueDate: "2023-08-31",
currency: "EUR",
supplier: {
name: "ACME Corporation",
street: "123 Main St",
city: "Berlin",
country: "DE"
},
customer: {
name: "XYZ Ltd",
street: "456 Elm St",
city: "Munich",
country: "DE"
},
items: [
{ description: "Widget A", quantity: "10", unitCode: "EA", price: "50.00", lineExtensionAmount: "500.00" },
{ description: "Widget B", quantity: "5", unitCode: "EA", price: "30.00", lineExtensionAmount: "150.00" }
],
totals: {
lineExtensionAmountTotal: "650.00",
taxExclusiveAmount: "650.00",
taxInclusiveAmount: "773.50",
payableAmount: "773.50"
}
};
}
// On component mount, extract the data
onMount(() => {
extractInvoiceData();
});
</script>
<style>
.invoice-container {
width: 70%;
margin: 50px auto;
background-color: #fff;
padding: 20px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}
.header {
text-align: center;
margin-bottom: 20px;
}
.header h1 {
margin: 0;
font-size: 24px;
color: #333;
}
.section-title {
font-size: 18px;
color: #555;
margin-bottom: 10px;
border-bottom: 2px solid #e7e7e7;
padding-bottom: 5px;
}
.details, .items, .totals {
margin-bottom: 20px;
}
.details .label, .totals .label {
width: 30%;
display: inline-block;
color: #888;
}
.details .value, .totals .value {
width: 70%;
display: inline-block;
color: #333;
}
.items table {
width: 100%;
border-collapse: collapse;
}
.items table, .items th, .items td {
border: 1px solid #e7e7e7;
}
.items th, .items td {
padding: 10px;
text-align: left;
}
.items th {
background-color: #f8f8f8;
color: #555;
}
.totals {
text-align: right;
}
.totals .label {
font-weight: bold;
}
</style>
<div class="invoice-container">
<div class="header">
<h1>Invoice</h1>
</div>
<div class="details">
<div class="section-title">Invoice Details</div>
<div><span class="label">Invoice ID:</span> <span class="value">{invoiceData.invoiceID}</span></div>
<div><span class="label">Issue Date:</span> <span class="value">{invoiceData.issueDate}</span></div>
<div><span class="label">Due Date:</span> <span class="value">{invoiceData.dueDate}</span></div>
<div><span class="label">Currency:</span> <span class="value">{invoiceData.currency}</span></div>
</div>
<div class="details">
<div class="section-title">Supplier Details</div>
<div><span class="label">Name:</span> <span class="value">{invoiceData.supplier.name}</span></div>
<div><span class="label">Street:</span> <span class="value">{invoiceData.supplier.street}</span></div>
<div><span class="label">City:</span> <span class="value">{invoiceData.supplier.city}</span></div>
<div><span class="label">Country:</span> <span class="value">{invoiceData.supplier.country}</span></div>
</div>
<div class="details">
<div class="section-title">Customer Details</div>
<div><span class="label">Name:</span> <span class="value">{invoiceData.customer.name}</span></div>
<div><span class="label">Street:</span> <span class="value">{invoiceData.customer.street}</span></div>
<div><span class="label">City:</span> <span class="value">{invoiceData.customer.city}</span></div>
<div><span class="label">Country:</span> <span class="value">{invoiceData.customer.country}</span></div>
</div>
<div class="items">
<div class="section-title">Invoice Items</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Code</th>
<th>Price (EUR)</th>
<th>Line Extension Amount (EUR)</th>
</tr>
</thead>
<tbody>
{#each invoiceData.items as item}
<tr>
<td>{item.description}</td>
<td>{item.quantity}</td>
<td>{item.unitCode}</td>
<td>{item.price}</td>
<td>{item.lineExtensionAmount}</td>
</tr>
{/each}
</tbody>
</table>
</div>
<div class="totals">
<div><span class="label">Line Extension Amount Total:</span> <span class="value">{invoiceData.totals.lineExtensionAmountTotal}</span></div>
<div><span class="label">Tax Exclusive Amount:</span> <span class="value">{invoiceData.totals.taxExclusiveAmount}</span></div>
<div><span class="label">Tax Inclusive Amount:</span> <span class="value">{invoiceData.totals.taxInclusiveAmount}</span></div>
<div><span class="label">Payable Amount:</span> <span class="value">{invoiceData.totals.payableAmount}</span></div>
</div>
</div>