|
|
|
|
@@ -1,5 +1,8 @@
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use PHPMailer\PHPMailer\PHPMailer;
|
|
|
|
|
use PHPMailer\PHPMailer\Exception;
|
|
|
|
|
|
|
|
|
|
class ManualInvoiceController extends TTCrud
|
|
|
|
|
{
|
|
|
|
|
protected string $headerTitle = 'Manuelle Rechnungen';
|
|
|
|
|
@@ -19,9 +22,9 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
['key' => 'total', 'text' => 'Netto', 'table' => ['sortable' => true, 'formatter' => 'formatPrice']],
|
|
|
|
|
['key' => 'total_gross', 'text' => 'Brutto', 'table' => ['sortable' => true, 'formatter' => 'formatPrice']],
|
|
|
|
|
['key' => 'status', 'text' => 'Status', 'table' => ['filter' => 'select', 'filterOptions' => [
|
|
|
|
|
['value' => 'draft', 'text' => 'Entwurf'],
|
|
|
|
|
['value' => 'finalized', 'text' => 'Finalisiert'],
|
|
|
|
|
['value' => 'exported', 'text' => 'Exportiert'],
|
|
|
|
|
['value' => 'erstellt', 'text' => 'Erstellt'],
|
|
|
|
|
['value' => 'gesendet', 'text' => 'Gesendet'],
|
|
|
|
|
['value' => 'exportiert', 'text' => 'Exportiert'],
|
|
|
|
|
]]],
|
|
|
|
|
['key' => 'billing_type', 'text' => 'Zahlungsart', 'table' => ['filter' => 'select', 'filterOptions' => [
|
|
|
|
|
['value' => 'invoice', 'text' => 'Rechnung'],
|
|
|
|
|
@@ -31,7 +34,9 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
protected array $additionalActions = [
|
|
|
|
|
['key' => 'createGutschrift', 'title' => 'Gutschrift erstellen', 'class' => 'fas fa-file-invoice text-warning']
|
|
|
|
|
['key' => 'createGutschrift', 'title' => 'Gutschrift erstellen', 'class' => 'fas fa-file-invoice text-warning'],
|
|
|
|
|
['key' => 'pdfPreview', 'title' => 'PDF Vorschau', 'class' => 'fas fa-file-pdf text-danger'],
|
|
|
|
|
['key' => 'sendInvoice', 'title' => 'Rechnung aussenden', 'class' => 'fas fa-paper-plane text-success']
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
protected function createPDFAction($returnFilename = false) {
|
|
|
|
|
@@ -46,9 +51,23 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
'company' => '', 'firstname' => '', 'lastname' => '',
|
|
|
|
|
'street' => '', 'zip' => '', 'city' => '', 'country' => 'Österreich',
|
|
|
|
|
'email' => '', 'uid' => '', 'tax_text' => '', 'billing_type' => 'invoice',
|
|
|
|
|
'leistungszeitraum' => '', 'einleitender_text' => '', 'externe_referenz' => '', 'gesamtrabatt' => 0,
|
|
|
|
|
'total' => 0, 'total_gross' => 0
|
|
|
|
|
], $post);
|
|
|
|
|
$positions = array_map(fn($p) => (object)$p, $post['positions'] ?? []);
|
|
|
|
|
|
|
|
|
|
// Convert invoice_date from string to timestamp if needed
|
|
|
|
|
if (isset($invoice->invoice_date) && is_string($invoice->invoice_date)) {
|
|
|
|
|
$invoice->invoice_date = strtotime($invoice->invoice_date);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$positions = array_map(function($p) {
|
|
|
|
|
$obj = (object)$p;
|
|
|
|
|
// Map _group to position_group for preview
|
|
|
|
|
if (isset($p['_group'])) {
|
|
|
|
|
$obj->position_group = $p['_group'];
|
|
|
|
|
}
|
|
|
|
|
return $obj;
|
|
|
|
|
}, $post['positions'] ?? []);
|
|
|
|
|
} else {
|
|
|
|
|
$id = $this->request->id ?? $post['id'] ?? null;
|
|
|
|
|
if (!$id || !($invoice = ManualInvoiceModel::get($id))) {
|
|
|
|
|
@@ -86,6 +105,8 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
"{{ billingAccount }}" => $invoice->fibu_account_number ?? '',
|
|
|
|
|
"{{ invoiceNumber }}" => $invoice->invoice_number ?? "VORSCHAU",
|
|
|
|
|
"{{ invoiceDate }}" => date("d.m.Y", $invoice->invoice_date ?? time()),
|
|
|
|
|
"{{ leistungszeitraumHtml }}" => ($invoice->leistungszeitraum ?? '') ? "<tr><td>Leistungszeitraum:</td><td>" . htmlspecialchars($invoice->leistungszeitraum) . "</td></tr>" : "",
|
|
|
|
|
"{{ externeReferenzHtml }}" => ($invoice->externe_referenz ?? '') ? "<tr><td>Externe Referenz:</td><td>" . htmlspecialchars($invoice->externe_referenz) . "</td></tr>" : "",
|
|
|
|
|
"{{ vatHtml }}" => ($invoice->uid ?? '') ? "<tr><td>Ihre UID:</td><td>" . $invoice->uid . "</td></tr>" : "",
|
|
|
|
|
"{{ qrCodeSrc }}" => $this->generateSepaQRCode($invoice->invoice_number ?? "VORSCHAU", round($invoice->total_gross ?? 0, 2))
|
|
|
|
|
];
|
|
|
|
|
@@ -134,6 +155,186 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function pdfPreviewAction() {
|
|
|
|
|
$post = json_decode(file_get_contents('php://input'), true);
|
|
|
|
|
$id = $post['id'] ?? null;
|
|
|
|
|
|
|
|
|
|
if (!$id || !($invoice = ManualInvoiceModel::get($id))) {
|
|
|
|
|
self::returnJson(['success' => false, 'message' => 'Rechnung nicht gefunden']);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Log PDF preview in journal
|
|
|
|
|
$me = new User();
|
|
|
|
|
$me->loadMe();
|
|
|
|
|
ManualInvoiceJournalModel::create([
|
|
|
|
|
'manualinvoiceId' => $id,
|
|
|
|
|
'text' => 'PDF Vorschau geöffnet',
|
|
|
|
|
'createBy' => $me->id,
|
|
|
|
|
'create' => time()
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
// Return URL to open in new tab
|
|
|
|
|
$url = "?action=ManualInvoice_createPDF&id=" . $id;
|
|
|
|
|
self::returnJson(['success' => true, 'url' => $url]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function getInvoiceEmailAction() {
|
|
|
|
|
$post = json_decode(file_get_contents('php://input'), true);
|
|
|
|
|
$id = $post['id'] ?? null;
|
|
|
|
|
|
|
|
|
|
if (!$id || !($invoice = ManualInvoiceModel::get($id))) {
|
|
|
|
|
self::returnJson(['success' => false, 'message' => 'Rechnung nicht gefunden']);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self::returnJson([
|
|
|
|
|
'success' => true,
|
|
|
|
|
'invoice' => [
|
|
|
|
|
'id' => $invoice->id,
|
|
|
|
|
'invoice_number' => $invoice->invoice_number,
|
|
|
|
|
'email' => $invoice->email,
|
|
|
|
|
'customerName' => trim(($invoice->company ?: '') . ' ' . $invoice->firstname . ' ' . $invoice->lastname)
|
|
|
|
|
]
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function sendInvoiceEmailAction() {
|
|
|
|
|
// Enable error reporting for debugging
|
|
|
|
|
error_reporting(E_ALL);
|
|
|
|
|
ini_set('display_errors', 1);
|
|
|
|
|
ini_set('display_startup_errors', 1);
|
|
|
|
|
|
|
|
|
|
$post = json_decode(file_get_contents('php://input'), true);
|
|
|
|
|
$id = $post['id'] ?? null;
|
|
|
|
|
$recipientEmail = $post['email'] ?? null;
|
|
|
|
|
$subject = $post['subject'] ?? 'Ihre Rechnung von XINON GmbH';
|
|
|
|
|
$bodyText = $post['body'] ?? 'Sehr geehrte Damen und Herren,\n\nanbei erhalten Sie Ihre Rechnung.\n\nMit freundlichen Grüßen\nIhr Xinon Team';
|
|
|
|
|
|
|
|
|
|
if (!$id || !$recipientEmail) {
|
|
|
|
|
self::returnJson(['success' => false, 'message' => 'ID oder E-Mail-Adresse fehlt']);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$invoice = ManualInvoiceModel::get($id);
|
|
|
|
|
if (!$invoice) {
|
|
|
|
|
self::returnJson(['success' => false, 'message' => 'Rechnung nicht gefunden']);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate PDF
|
|
|
|
|
$pdf_filename = $this->createPDFAction(true);
|
|
|
|
|
if (!$pdf_filename || !file_exists($pdf_filename)) {
|
|
|
|
|
self::returnJson(['success' => false, 'message' => 'PDF konnte nicht erstellt werden']);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$pdfContent = file_get_contents($pdf_filename);
|
|
|
|
|
|
|
|
|
|
// --- HTML Email Generation ---
|
|
|
|
|
$logoToolPath = BASEDIR . '/public/assets/images/the-tool-logo.png';
|
|
|
|
|
$logoXinonPath = BASEDIR . '/public/assets/images/xinon-full.png';
|
|
|
|
|
$logoToolExists = file_exists($logoToolPath);
|
|
|
|
|
$logoXinonExists = file_exists($logoXinonPath);
|
|
|
|
|
|
|
|
|
|
// Construct HTML Body
|
|
|
|
|
$html = '<!DOCTYPE html><html lang="de"><head><meta charset="UTF-8"><title>Rechnung</title><style>body { font-family: Arial, sans-serif; color: #333; }</style></head><body style="margin:0;padding:20px;background-color:#f3f4f6;">';
|
|
|
|
|
$html .= '<div style="background-color:#fff;padding:20px;border-radius:8px;max-width:600px;margin:0 auto;box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);">';
|
|
|
|
|
|
|
|
|
|
// Logos
|
|
|
|
|
$html .= '<div style="text-align:center;margin-bottom:20px;border-bottom: 1px solid #e5e7eb;padding-bottom: 15px;">';
|
|
|
|
|
if ($logoToolExists) $html .= '<img src="cid:logo_thetool" alt="The Tool" style="height:40px;margin-right:15px;vertical-align:middle;">';
|
|
|
|
|
if ($logoXinonExists) $html .= '<img src="cid:logo_xinon" alt="Xinon" style="height:40px;vertical-align:middle;">';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<h2 style="color:#00558c;text-align:center;font-size:20px;margin-bottom:20px;">' . htmlspecialchars($subject) . '</h2>';
|
|
|
|
|
$html .= '<div style="font-size:14px;line-height:1.6;color:#333;">';
|
|
|
|
|
$html .= nl2br(htmlspecialchars($bodyText));
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<br><div style="border-top:1px solid #eee;padding-top:20px;font-size:12px;color:#999;text-align:center;">';
|
|
|
|
|
$html .= 'XINON GmbH | <a href="https://www.xinon.at" style="color:#00558c;text-decoration:none;">www.xinon.at</a>';
|
|
|
|
|
$html .= '</div></div></body></html>';
|
|
|
|
|
|
|
|
|
|
$mail = new PHPMailer(true);
|
|
|
|
|
try {
|
|
|
|
|
// Server settings
|
|
|
|
|
$mail->isSMTP();
|
|
|
|
|
$mail->Host = TT_PIPEWORK_SMTP_HOST;
|
|
|
|
|
$mail->SMTPAuth = true;
|
|
|
|
|
$mail->Username = TT_PIPEWORK_SMTP_USER;
|
|
|
|
|
$mail->Password = TT_PIPEWORK_SMTP_PASS;
|
|
|
|
|
$mail->CharSet = PHPMailer::CHARSET_UTF8;
|
|
|
|
|
$mail->Encoding = 'base64';
|
|
|
|
|
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
|
|
|
|
$mail->Port = 587;
|
|
|
|
|
|
|
|
|
|
// Logos
|
|
|
|
|
if ($logoToolExists) $mail->addEmbeddedImage($logoToolPath, 'logo_thetool');
|
|
|
|
|
if ($logoXinonExists) $mail->addEmbeddedImage($logoXinonPath, 'logo_xinon');
|
|
|
|
|
|
|
|
|
|
$mail->addReplyTo('backoffice@xinon.at', 'XINON Backoffice');
|
|
|
|
|
$mail->setFrom('thetool@xinon.at', 'XINON TheTool');
|
|
|
|
|
|
|
|
|
|
$customerName = trim(($invoice->company ?: '') . ' ' . $invoice->firstname . ' ' . $invoice->lastname);
|
|
|
|
|
$mail->addAddress($recipientEmail, $customerName);
|
|
|
|
|
$mail->Subject = $subject;
|
|
|
|
|
$mail->isHTML(true);
|
|
|
|
|
$mail->Body = $html;
|
|
|
|
|
$mail->AltBody = strip_tags($bodyText);
|
|
|
|
|
|
|
|
|
|
$mail->addStringAttachment($pdfContent, $invoice->invoice_number . '_Rechnung.pdf', 'base64', 'application/pdf');
|
|
|
|
|
|
|
|
|
|
$mail->send();
|
|
|
|
|
|
|
|
|
|
// Update invoice status
|
|
|
|
|
$invoice->status = 'gesendet';
|
|
|
|
|
$invoice->save();
|
|
|
|
|
|
|
|
|
|
// Add Journal Entry
|
|
|
|
|
$me = new User();
|
|
|
|
|
$me->loadMe();
|
|
|
|
|
ManualInvoiceJournalModel::create([
|
|
|
|
|
'manualinvoiceId' => $id,
|
|
|
|
|
'text' => "Rechnung per E-Mail an $recipientEmail gesendet.",
|
|
|
|
|
'statusChange' => 'gesendet',
|
|
|
|
|
'createBy' => $me->id,
|
|
|
|
|
'create' => time()
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
self::returnJson(['success' => true, 'message' => 'E-Mail erfolgreich versendet an ' . $recipientEmail]);
|
|
|
|
|
} catch (Exception $e) {
|
|
|
|
|
self::returnJson(['success' => false, 'message' => 'E-Mail konnte nicht gesendet werden. Fehler: ' . $mail->ErrorInfo]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function downloadInvoiceAction() {
|
|
|
|
|
$post = json_decode(file_get_contents('php://input'), true);
|
|
|
|
|
$id = $post['id'] ?? null;
|
|
|
|
|
|
|
|
|
|
if (!$id || !($invoice = ManualInvoiceModel::get($id))) {
|
|
|
|
|
self::returnJson(['success' => false, 'message' => 'Rechnung nicht gefunden']);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$me = new User();
|
|
|
|
|
$me->loadMe();
|
|
|
|
|
|
|
|
|
|
// Log download in journal
|
|
|
|
|
ManualInvoiceJournalModel::create([
|
|
|
|
|
'manualinvoiceId' => $id,
|
|
|
|
|
'text' => 'Rechnung heruntergeladen',
|
|
|
|
|
'createBy' => $me->id,
|
|
|
|
|
'create' => time()
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$downloadUrl = "?action=ManualInvoice_downloadInvoicePdf&id=" . $id;
|
|
|
|
|
self::returnJson([
|
|
|
|
|
'success' => true,
|
|
|
|
|
'url' => $downloadUrl
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function beforeCreate(&$data): bool {
|
|
|
|
|
if (isset($data['positions']) && is_array($data['positions'])) {
|
|
|
|
|
$this->tempPositions = $data['positions'];
|
|
|
|
|
@@ -143,12 +344,18 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
$me = new User();
|
|
|
|
|
$me->loadMe();
|
|
|
|
|
|
|
|
|
|
// Convert invoice_date from string to timestamp if needed
|
|
|
|
|
if (isset($data['invoice_date']) && is_string($data['invoice_date'])) {
|
|
|
|
|
$data['invoice_date'] = strtotime($data['invoice_date']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$data = array_merge([
|
|
|
|
|
'invoice_number' => ManualInvoiceModel::getNextInvoiceNumber(),
|
|
|
|
|
'invoice_date' => time(),
|
|
|
|
|
'status' => 'draft',
|
|
|
|
|
'invoice_date' => $data['invoice_date'] ?? time(),
|
|
|
|
|
'status' => 'erstellt',
|
|
|
|
|
'fibu_payment_skonto' => 0,
|
|
|
|
|
'fibu_payment_skonto_rate' => 0,
|
|
|
|
|
'gesamtrabatt' => 0,
|
|
|
|
|
'total' => 0,
|
|
|
|
|
'total_gross' => 0,
|
|
|
|
|
'create_by' => $me->id,
|
|
|
|
|
@@ -163,6 +370,17 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
protected function afterCreate($data) {
|
|
|
|
|
$this->savePositions($data['id']);
|
|
|
|
|
$this->recalculateTotals($data['id']);
|
|
|
|
|
|
|
|
|
|
// Log creation in journal
|
|
|
|
|
$me = new User();
|
|
|
|
|
$me->loadMe();
|
|
|
|
|
ManualInvoiceJournalModel::create([
|
|
|
|
|
'manualinvoiceId' => $data['id'],
|
|
|
|
|
'text' => 'Rechnung erstellt',
|
|
|
|
|
'statusChange' => 'erstellt',
|
|
|
|
|
'createBy' => $me->id,
|
|
|
|
|
'create' => time()
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function beforeUpdate(&$data): bool {
|
|
|
|
|
@@ -171,11 +389,16 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
unset($data['positions']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset($data['id']) && ($invoice = ManualInvoiceModel::get($data['id'])) && $invoice->status === 'exported') {
|
|
|
|
|
if (isset($data['id']) && ($invoice = ManualInvoiceModel::get($data['id'])) && $invoice->status === 'exportiert') {
|
|
|
|
|
$this->infoMessages['update'] = 'Rechnung wurde bereits exportiert und kann nicht mehr bearbeitet werden';
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert invoice_date from string to timestamp if needed
|
|
|
|
|
if (isset($data['invoice_date']) && is_string($data['invoice_date'])) {
|
|
|
|
|
$data['invoice_date'] = strtotime($data['invoice_date']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$me = new User();
|
|
|
|
|
$me->loadMe();
|
|
|
|
|
$data['edit_by'] = $me->id;
|
|
|
|
|
@@ -190,6 +413,16 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
|
|
|
|
|
$this->savePositions($data['id']);
|
|
|
|
|
$this->recalculateTotals($data['id']);
|
|
|
|
|
|
|
|
|
|
// Log update in journal
|
|
|
|
|
$me = new User();
|
|
|
|
|
$me->loadMe();
|
|
|
|
|
ManualInvoiceJournalModel::create([
|
|
|
|
|
'manualinvoiceId' => $data['id'],
|
|
|
|
|
'text' => 'Rechnung aktualisiert',
|
|
|
|
|
'createBy' => $me->id,
|
|
|
|
|
'create' => time()
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function savePositions($invoiceId) {
|
|
|
|
|
@@ -199,9 +432,18 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
$me->loadMe();
|
|
|
|
|
|
|
|
|
|
foreach ($this->tempPositions as $position) {
|
|
|
|
|
// Skip empty positions
|
|
|
|
|
if (empty($position['product_name']) || ($position['amount'] ?? 0) == 0) continue;
|
|
|
|
|
|
|
|
|
|
// Map _group to position_group
|
|
|
|
|
$groupName = $position['_group'] ?? null;
|
|
|
|
|
unset($position['_group']);
|
|
|
|
|
|
|
|
|
|
ManualInvoicepositionModel::create(array_merge([
|
|
|
|
|
'manualinvoice_id' => $invoiceId,
|
|
|
|
|
'start_date' => date('Y-m-d'),
|
|
|
|
|
'position_group' => $groupName,
|
|
|
|
|
'unit' => 'Stk.',
|
|
|
|
|
'discount' => 0,
|
|
|
|
|
'create_by' => $me->id,
|
|
|
|
|
'edit_by' => $me->id,
|
|
|
|
|
'create' => time(),
|
|
|
|
|
@@ -215,8 +457,23 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
if (!($invoice = ManualInvoiceModel::get($invoiceId))) return;
|
|
|
|
|
|
|
|
|
|
$positions = ManualInvoicepositionModel::search(['manualinvoice_id' => $invoiceId]);
|
|
|
|
|
$invoice->total = array_sum(array_column($positions, 'price_total'));
|
|
|
|
|
$invoice->total_gross = array_sum(array_column($positions, 'price_gross'));
|
|
|
|
|
$subtotal = array_sum(array_column($positions, 'price_total'));
|
|
|
|
|
|
|
|
|
|
// Apply gesamtrabatt (total discount) if exists
|
|
|
|
|
$gesamtrabatt = $invoice->gesamtrabatt ?? 0;
|
|
|
|
|
$discountAmount = $subtotal * ($gesamtrabatt / 100);
|
|
|
|
|
$netTotal = $subtotal - $discountAmount;
|
|
|
|
|
|
|
|
|
|
// Calculate gross total with VAT applied after discount
|
|
|
|
|
$grossTotal = 0;
|
|
|
|
|
foreach ($positions as $pos) {
|
|
|
|
|
$positionNet = $pos->price_total;
|
|
|
|
|
$positionAfterDiscount = $positionNet * (1 - $gesamtrabatt / 100);
|
|
|
|
|
$grossTotal += $positionAfterDiscount * (1 + $pos->vatrate / 100);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$invoice->total = $netTotal;
|
|
|
|
|
$invoice->total_gross = $grossTotal;
|
|
|
|
|
$invoice->save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -272,23 +529,23 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
return [
|
|
|
|
|
'id' => $pos->id,
|
|
|
|
|
'manualinvoice_id' => $pos->manualinvoice_id,
|
|
|
|
|
'_group' => $pos->position_group ?? '',
|
|
|
|
|
'billing_id' => $pos->billing_id,
|
|
|
|
|
'contract_id' => $pos->contract_id,
|
|
|
|
|
'start_date' => $pos->start_date,
|
|
|
|
|
'end_date' => $pos->end_date,
|
|
|
|
|
'matchcode' => $pos->matchcode,
|
|
|
|
|
'product_id' => $pos->product_id,
|
|
|
|
|
'product_name' => $pos->product_name,
|
|
|
|
|
'product_info' => $pos->product_info,
|
|
|
|
|
'amount' => $pos->amount,
|
|
|
|
|
'unit' => $pos->unit ?? 'Stk.',
|
|
|
|
|
'price' => $pos->price,
|
|
|
|
|
'discount' => $pos->discount ?? 0,
|
|
|
|
|
'price_total' => $pos->price_total,
|
|
|
|
|
'price_gross' => $pos->price_gross,
|
|
|
|
|
'vatrate' => $pos->vatrate,
|
|
|
|
|
'fibu_cost_account' => $pos->fibu_cost_account,
|
|
|
|
|
'fibu_cost_account_legacy' => $pos->fibu_cost_account_legacy,
|
|
|
|
|
'fibu_taxcode' => $pos->fibu_taxcode,
|
|
|
|
|
'billing_period' => $pos->billing_period,
|
|
|
|
|
'options' => $pos->options
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
@@ -340,6 +597,7 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
'original_amount' => $pos->amount,
|
|
|
|
|
'credited_amount' => $creditedAmounts[$key] ?? 0,
|
|
|
|
|
'available_amount' => $availableAmount,
|
|
|
|
|
'unit' => $pos->unit ?? 'Stk.',
|
|
|
|
|
'price' => $pos->price,
|
|
|
|
|
'vatrate' => $pos->vatrate,
|
|
|
|
|
'product_id' => $pos->product_id,
|
|
|
|
|
@@ -376,6 +634,10 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
$invoiceData = [
|
|
|
|
|
'invoice_number' => ManualInvoiceModel::getNextInvoiceNumber(),
|
|
|
|
|
'invoice_date' => time(),
|
|
|
|
|
'leistungszeitraum' => $originalInvoice->leistungszeitraum ?? null,
|
|
|
|
|
'einleitender_text' => 'Gutschrift zur Rechnung ' . $originalInvoice->invoice_number,
|
|
|
|
|
'externe_referenz' => $originalInvoice->externe_referenz ?? null,
|
|
|
|
|
'gesamtrabatt' => 0,
|
|
|
|
|
'owner_id' => $originalInvoice->owner_id,
|
|
|
|
|
'billingaddress_id' => $originalInvoice->billingaddress_id,
|
|
|
|
|
'customer_number' => $originalInvoice->customer_number,
|
|
|
|
|
@@ -410,7 +672,7 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
'total_gross' => 0,
|
|
|
|
|
'vatgroup_id' => $originalInvoice->vatgroup_id,
|
|
|
|
|
'credit_for_invoice_id' => $originalInvoiceId,
|
|
|
|
|
'status' => 'finalized',
|
|
|
|
|
'status' => 'erstellt',
|
|
|
|
|
'create' => time(),
|
|
|
|
|
'edit' => time(),
|
|
|
|
|
'create_by' => $me->id,
|
|
|
|
|
@@ -425,11 +687,14 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
$priceTotal = (-abs($pos['amount'])) * $pos['price'];
|
|
|
|
|
ManualInvoicepositionModel::create([
|
|
|
|
|
'manualinvoice_id' => $creditInvoiceId,
|
|
|
|
|
'position_group' => null,
|
|
|
|
|
'product_id' => $pos['product_id'],
|
|
|
|
|
'product_name' => $pos['product_name'],
|
|
|
|
|
'product_info' => $pos['product_info'] ?? '',
|
|
|
|
|
'amount' => -abs($pos['amount']),
|
|
|
|
|
'unit' => $pos['unit'] ?? 'Stk.',
|
|
|
|
|
'price' => $pos['price'],
|
|
|
|
|
'discount' => 0,
|
|
|
|
|
'vatrate' => $pos['vatrate'],
|
|
|
|
|
'price_total' => $priceTotal,
|
|
|
|
|
'price_gross' => $priceTotal * (1 + $pos['vatrate'] / 100),
|
|
|
|
|
@@ -437,8 +702,7 @@ class ManualInvoiceController extends TTCrud
|
|
|
|
|
'fibu_cost_account' => $pos['fibu_cost_account'] ?? null,
|
|
|
|
|
'fibu_taxcode' => $pos['fibu_taxcode'] ?? null,
|
|
|
|
|
'contract_id' => 0,
|
|
|
|
|
'start_date' => date('Y-m-d'),
|
|
|
|
|
'billing_period' => 0,
|
|
|
|
|
'billing_id' => null,
|
|
|
|
|
'create_by' => $me->id,
|
|
|
|
|
'edit_by' => $me->id,
|
|
|
|
|
'create' => time(),
|
|
|
|
|
|