508 lines
28 KiB
PHP
508 lines
28 KiB
PHP
<?php
|
|
$pagination_baseurl = $this->getUrl($Mod, "Index");
|
|
$pagination_baseurl_params = ["filter" => $filter];
|
|
$pagination_entity_name = "Rechnungen";
|
|
?>
|
|
<?php include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/header.php"); ?>
|
|
|
|
<!-- start page title -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="page-title-box">
|
|
<div class="page-title-right">
|
|
<ol class="breadcrumb m-0">
|
|
<li class="breadcrumb-item"><a href="<?=self::getUrl("Dashboard")?>"><?=MFAPPNAME_SLUG?></a></li>
|
|
<li class="breadcrumb-item"><a href="<?=self::getUrl("Preordercampaign")?>">Vorbestellkampagnen</a></li>
|
|
<li class="breadcrumb-item active">Rechnungen</li>
|
|
</ol>
|
|
</div>
|
|
<h4 class="page-title">Rechnungen</h4>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- end page title -->
|
|
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
|
|
<div class="card">
|
|
<div class="card-body mb-3">
|
|
<h4 class="header-title mb-3">Filter</h4>
|
|
|
|
<form method="get" action="<?=self::getUrl("PreorderBillingInvoice")?>">
|
|
<div class="row">
|
|
|
|
<div class="col-2">
|
|
<label class="form-label" for="filter_owner_id">Netzbetreiber</label>
|
|
<select class="form-control" name="filter[owner_id]" id="filter_owner_id">
|
|
<option></option>
|
|
<?php foreach($netoperators as $netop): ?>
|
|
<option value="<?=$netop->id?>" <?=(is_array($filter) && $filter["owner_id"] == $netop->id) ? "selected='selected'" : ""?>><?=$netop->getCompanyOrName()?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-1">
|
|
<label class="form-label" for="filter_fibu_account_number">Kundennummer</label>
|
|
<input type="text" class="form-control" name="filter[fibu_account_number]" id="filter_fibu_account_number" value="<?=(array_key_exists("fibu_account_number", $filter)) ? $filter['fibu_account_number'] : ""?>"/>
|
|
</div>
|
|
|
|
<div class="col-2">
|
|
<label class="form-label" for="filter_name">Rechungsempfänger</label>
|
|
<input type="text" class="form-control" name="filter[name]" id="filter_name" value="<?=(array_key_exists("name", $filter)) ? $filter['name'] : ""?>"/>
|
|
</div>
|
|
|
|
<div class="col-2">
|
|
<label class="form-label" for="filter_product">Produkt</label>
|
|
<select class="form-control" name="filter[product_id]" id="filter_product_id">
|
|
<option></option>
|
|
<?php foreach(PreorderProduct::getWithTypes() as $product): ?>
|
|
<option value="<?=$product->id?>" <?=(is_array($filter) && $filter["product_id"] == $product->id) ? "selected='selected'" : ""?>><?=$product->name?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-1">
|
|
<label class="form-label" for="filter_start_date_from">Rech.nummer von</label>
|
|
<input type="text" class="form-control" name="filter[start_date_from]" id="filter_start_date_from" value="<?=(array_key_exists("start_date_from", $filter)) ? $filter['start_date_from'] : ""?>"/>
|
|
</div>
|
|
<div class="col-1">
|
|
<label class="form-label" for="filter_start_date_to">Rech.nummer bis</label>
|
|
<input type="text" class="form-control" name="filter[start_date_to]" id="filter_start_date_to" value="<?=(array_key_exists("start_date_to", $filter)) ? $filter['start_date_to'] : ""?>"/>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="row mt-2">
|
|
<div class="col">
|
|
<button type="submit" class="btn btn-primary">Filter anwenden</button>
|
|
<a class="btn btn-secondary" href="<?=self::getUrl("PreorderBillingInvoice")?>?resetFilter=1">Filter zurücksetzen</a>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body mb-3">
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-6">
|
|
<h4>Rechungsemails versenden</h4>
|
|
<form method="post" action="<?=self::getUrl("PreorderBillingInvoice", "createJob")?>">
|
|
<input type="hidden" name="task" value="send-preorder-invoice-email" />
|
|
<div class="row">
|
|
<div class="col-4">
|
|
<label class="form-label" for="from_date">Job Startdatum:</label>
|
|
<input type="text" class="form-control datepicker" name="from_date" value="" />
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary mt-1"><i class="fas fa-fw fa-circle-plus"></i> Versandjob erstellen</button>
|
|
|
|
<?php if(is_array($email_jobs) && count($email_jobs)): ?>
|
|
<h5>Aktuelle Email Jobs</h5>
|
|
<table class="table table-sm table-striped">
|
|
<tr>
|
|
<th>Start ab</th>
|
|
<th>Gestartet</th>
|
|
<th>Beendet</th>
|
|
<th>Status</th>
|
|
</tr>
|
|
<?php foreach($email_jobs as $job): ?>
|
|
<tr id="job-<?=$job->id?>">
|
|
<td><?=$job->from_date?></td>
|
|
<td><?=$job->started?></td>
|
|
<td class="finished"><?=$job->finished?></td>
|
|
<td>
|
|
<strong class="status text-monospace <?=(($job->status == "finished") ? "text-success" : ($job->status == "timeout" ? "text-danger" : "text-info"))?>"><?=($job->status) ? $job->status : "neu"?></strong><br />
|
|
<span class="status-text"><?=$job->getResult("sent") ? $job->getResult("sent")." Emails versendet" : ""?></span>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</table>
|
|
<?php endif; ?>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="col-6 border-left">
|
|
<h4>BMD-Export</h4>
|
|
|
|
<h5>Personenkonten</h5>
|
|
<div class="row col">
|
|
<a class="btn btn-purple" href="<?=self::getUrl("PreorderBillingInvoice", "bmdExport", ["type" => "addresses"])?>"><i class="fas fa-fw fa-users"></i> Personenexport erstellen</a>
|
|
</div>
|
|
<div class="row col">
|
|
<small>Letzter Export: <?=($bmd_export["person"]) ? date("d.m.Y H:i:s", $bmd_export["person"]) : ""?> </small>
|
|
</div>
|
|
|
|
<h5>Rechnungsdaten</h5>
|
|
<div class="row col">
|
|
<a class="btn btn-purple" href="<?=self::getUrl("PreorderBillingInvoice", "bmdExport", ["type" => "invoice"])?>"><i class="fas fa-fw fa-file-invoice"></i> Rechnungsexport erstellen</a>
|
|
</div>
|
|
<div class="row col">
|
|
<small>Letzter Export: <?=($bmd_export["invoice"]) ? date("d.m.Y H:i:s", $bmd_export["invoice"]) : ""?></small>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<h4 class="header-title">Rechnungen</h4>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<?php include(realpath(dirname(__FILE__)."/../")."/tpl/pagination.php"); ?>
|
|
<?php include(realpath(dirname(__FILE__)."/../")."/tpl/pagination-summary.php"); ?>
|
|
|
|
<table class="table table-sm table-striped table-hover">
|
|
<tr>
|
|
<th>Rechnungsnummer</th>
|
|
<th>Rechnungsdatum</th>
|
|
<th>Kundennummer</th>
|
|
<th>Rechnungsadresse</th>
|
|
<th>Rechnungstext</th>
|
|
<th>Netto</th>
|
|
<th>Ust.</th>
|
|
<th>Brutto</th>
|
|
<th>Versendet</th>
|
|
<th>Erstellt</th>
|
|
<th></th>
|
|
</tr>
|
|
<?php foreach($invoices as $invoice): ?>
|
|
<tr>
|
|
<td>
|
|
<a href="<?=self::getUrl("PreorderBillingInvoice", "downloadInvoice", ["id" => $invoice->id])?>"><i class="fas fa-download fa-fw"></i> <?=$invoice->invoice_number?></a>
|
|
<?php if($invoice->date_delivered): ?>
|
|
<i class="fas fa-fw fa-mail" title="per Email versendet am <?=date("d.m.Y H:i", $invoice->date_delivered)?>"></i>
|
|
<?php endif; ?>
|
|
<?php if($invoice->csv): ?>
|
|
<a class="ml-2" href="<?=self::getUrl("PreorderBillingInvoice", "downloadDetailCsv", ["id" => $invoice->id])?>">
|
|
<i class="far fa-fw fa-file-csv" title="Rechnungsgetails als CSV-Datei herunterladen"></i>
|
|
</a>
|
|
<a class="ml-1" href="<?=self::getUrl("PreorderBillingInvoice", "downloadDetailPdf", ["id" => $invoice->id])?>">
|
|
<i class="far fa-fw fa-file-pdf text-danger" title="Rechnungsgetails als PDF-Datei herunterladen"></i>
|
|
</a>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?=($invoice->invoice_date) ? (new DateTime($invoice->invoice_date))->format("d.m.Y") : ""?></td>
|
|
<td><?=$invoice->fibu_account_number?></td>
|
|
<td>
|
|
<?=($invoice->company) ? $invoice->company."<br />" : ""?>
|
|
<?=($invoice->firstname || $invoice->lastname) ? $invoice->firstname." ".$invoice->lastname."<br />" : ""?>
|
|
<?=$invoice->street?><br />
|
|
<?=$invoice->zip?> <?=$invoice->city?>
|
|
<?=($invoice->country != "Österreich") ? "<br >".$invoice->country : ""?>
|
|
</td>
|
|
<td><?=nl2br(htmlentities($invoice->head_text))?></td>
|
|
<td>€ <?=number_format($invoice->total, 2, ",", ".")?></td>
|
|
<td>€ <?=number_format($invoice->total_gross - $invoice->total, 2, ",", ".")?></td>
|
|
<td>€ <?=number_format($invoice->total_gross, 2, ",", ".")?></td>
|
|
<td class="text-monospace text-success">
|
|
<?php if($invoice->date_delivered): ?>
|
|
<?php if($invoice->emailLog): ?>
|
|
<a href="#" onclick="displayEmailLogEmail(<?=$invoice->id?>, <?=$invoice->emailLog->id?>); return false;"><i class='far fa-envelope-circle-check'></i></a>
|
|
<?php else: ?>
|
|
<i class='far fa-envelope-circle-check'></i>
|
|
<?php endif ?>
|
|
<?=date("d.m.Y H:i", $invoice->date_delivered)?>
|
|
<?php endif; ?>
|
|
|
|
</td>
|
|
<td>
|
|
<?=$invoice->creator->name?><br />
|
|
<?=date("d.m.Y H:i", $invoice->create)?>
|
|
</td>
|
|
<td>
|
|
<a href="#" onclick="openSendCopyModal(<?=$invoice->id?>); return false;" title="Rechungskopie versenden"><i class="fas fa-fw fa-paper-plane"></i></a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</table>
|
|
|
|
<?php include(realpath(dirname(__FILE__)."/../")."/tpl/pagination-summary.php"); ?>
|
|
<?php include(realpath(dirname(__FILE__)."/../")."/tpl/pagination.php"); ?>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="modal" tabindex="-1" id="email-log-modal" style="max-height: 100vh;">
|
|
<div class="modal-dialog modal-dialog-centered modal-xl">
|
|
<div class="modal-content" style="overflow: auto;">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Emailansicht</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col">
|
|
<table class="table">
|
|
<tr>
|
|
<th>Von:</th>
|
|
<td id="email-log-from-value" class="text-monospace"></td>
|
|
</tr><tr>
|
|
<th>An:</th>
|
|
<td id="email-log-to-value" class="text-monospace"></td>
|
|
</tr><tr>
|
|
<th>Gesendet:</th>
|
|
<td id="email-log-sent-value" class="text-monospace"></td>
|
|
</tr><tr>
|
|
<th>Betreff:</th>
|
|
<td id="email-log-subject-value" class="text-monospace"></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3" id="email-log-header-section">
|
|
<div class="col">
|
|
<a href="#" onclick="displayEmailLogHeaders(); return false;"><i class="fas fa-chevron-right fa-fw"></i> Alle Header anzeigen</a>
|
|
<div id="email-log-header-view" class="mt-2 text-monospace hidden" style="min-height: 48px; width:100%; border: 1px solid #ccc; padding: 8px; font-family: sans-serif;"></div>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-2" id="email-log-body-section">
|
|
<div class="col">
|
|
<iframe id="email-log-body-view" style="height: 50vh; width:100%; border: 1px solid #000; padding: 8px; font-family: sans-serif; overflow-y: auto;"></iframe>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3 hidden" id="email-log-attachments-section">
|
|
<div class="col-6">
|
|
<h5>Dateianhänge</h5>
|
|
<ul id="email-log-attachment-list" class="list-group"></ul>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal fade" id="sendCopyModal" tabindex="-1" aria-labelledby="sendCopyModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<form method="post" action="<?=self::getUrl("PreorderBillingInvoice", "sendCopy")?>">
|
|
<input type="hidden" name="id" value="" />
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="sendCopyModalLabel">Rechungskopie versenden</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label for="recipient-name" class="col-form-label">Empfänger Emailadresse:</label>
|
|
<input type="text" class="form-control email_to" name="email_to">
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Abbrechen</button>
|
|
<button type="submit" class="btn btn-primary">Rechnungskopie versenden</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
$("#filter_start_date_from").datepicker({
|
|
orientation: "bottom",
|
|
language: 'de',
|
|
format: "dd.mm.yyyy",
|
|
showWeekDays: true,
|
|
todayBtn: 'linked',
|
|
autoclose: true
|
|
});
|
|
$("#filter_start_date_to").datepicker({
|
|
orientation: "bottom",
|
|
language: 'de',
|
|
format: "dd.mm.yyyy",
|
|
showWeekDays: true,
|
|
todayBtn: 'linked',
|
|
autoclose: true
|
|
});
|
|
$('.datepicker').datepicker({
|
|
orientation: "bottom",
|
|
language: 'de',
|
|
format: "dd.mm.yyyy",
|
|
showWeekDays: true,
|
|
todayBtn: 'linked',
|
|
autoclose: true
|
|
});
|
|
|
|
function openSendCopyModal(id) {
|
|
$('#sendCopyModal input[name="id"]').val(id);
|
|
$('#sendCopyModal input[name="email_to"]').val("");
|
|
$('#sendCopyModal').modal();
|
|
}
|
|
|
|
var status_update;
|
|
|
|
function updateStatus() {
|
|
$.post(
|
|
"<?=self::getUrl("PreorderBillingInvoice", "api")?>",
|
|
{
|
|
do: "getActiveJobs",
|
|
type: "send-preorder-invoice-email"
|
|
},
|
|
function(success) {
|
|
if(success.status != "OK") return;
|
|
|
|
jobs = success.result.jobs;
|
|
jobs.forEach((job) => {
|
|
let status = JSON.parse(job.result);
|
|
if(!status) return;
|
|
|
|
let status_text = "";
|
|
let count = 0;
|
|
|
|
if(job.task == "send-preorder-invoice-email") {
|
|
status_text = status.sent + " Emails versendet";
|
|
count = status.sent;
|
|
}
|
|
|
|
let old_count = 0;
|
|
let m = $("#job-" + job.id + " .status-text").text().match(/^(\d+)/);
|
|
if(m) {
|
|
old_count = m[1];
|
|
}
|
|
if(old_count != count) {
|
|
$("#job-" + job.id + " .status-text").fadeOut();
|
|
$("#job-" + job.id + " .status-text").promise().done(() => {$("#job-" + job.id + " .status-text").text(status_text).fadeIn()});
|
|
}
|
|
|
|
$("#job-" + job.id + " .status").text(job.status ? job.status : "neu");
|
|
if(job.status == "timeout") {
|
|
$("#job-" + job.id + " .status").removeClass("text-info text-success").addClass("text-danger");
|
|
} else if(job.status == "finished") {
|
|
$("#job-" + job.id + " .status").removeClass("text-info text-danger").addClass("text-success");
|
|
} else {
|
|
$("#job-" + job.id + " .status").removeClass("text-danger text-success").addClass("text-info");
|
|
}
|
|
|
|
if(job.finished) {
|
|
$("#job-" + job.id + " .finished").text(job.finished);
|
|
} else {
|
|
$("#job-" + job.id + " .finished").text("");
|
|
}
|
|
});
|
|
|
|
status_update = setTimeout(updateStatus, 2000);
|
|
},
|
|
"json"
|
|
);
|
|
}
|
|
|
|
$(document).ready(() => {
|
|
<?php if(is_array($email_jobs) && count($email_jobs)): ?>
|
|
status_update = setTimeout(updateStatus, 1000);
|
|
<?php endif; ?>
|
|
});
|
|
|
|
async function displayEmailLogEmail(invoice_id, email_id) {
|
|
$("#email-log-from-value").text("");
|
|
$("#email-log-to-value").text("");
|
|
$("#email-log-log-sent-value").text("");
|
|
$("#email-log-subject-value").text("");
|
|
document.getElementById("email-log-body-view").contentWindow.document.open();
|
|
document.getElementById("email-log-body-view").contentWindow.document.write("<html><body> </body></html>");
|
|
document.getElementById("email-log-body-view").contentWindow.document.close();
|
|
$("#email-log-attachments-section").hide();
|
|
$("#email-log-attachment-list").empty();
|
|
hideEmailLogHeaders();
|
|
|
|
if(!email_id) return false;
|
|
|
|
var resp = await fetch("<?=self::getUrl("PreorderBillingInvoice", "api", ["do" => "getLoggedEmail"])?>&oid=" + invoice_id + "&eid=" + email_id);
|
|
console.log(resp);
|
|
if(!resp.ok) {
|
|
notify("error", "Email konnte nicht geladen werden");
|
|
return false;
|
|
}
|
|
|
|
var response = await resp.json();
|
|
|
|
if(!("result" in response) || typeof response.result !== "object") {
|
|
notify("error", "Email konnte nicht geladen werden");
|
|
return false;
|
|
}
|
|
|
|
var email = response.result;
|
|
$("#email-log-from-value").text(email.from);
|
|
$("#email-log-to-value").text(email.to);
|
|
$("#email-log-sent-value").text(email.sent);
|
|
$("#email-log-subject-value").text(email.subject);
|
|
|
|
if("headers" in email && typeof email.headers === "object" && Object.keys(email.headers).length > 0) {
|
|
for (const [key, value] of Object.entries(email.headers)) {
|
|
$("#email-log-header-view").append(
|
|
"<strong>" + key + "</strong>: "
|
|
+ value.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>')
|
|
+ "<br/>");
|
|
if(key == "From") {
|
|
$("#email-log-from-value").text(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
if("attachments" in email && typeof email.attachments === "object" && Object.keys(email.attachments).length > 0) {
|
|
email.attachments.forEach( (item, index) => {
|
|
$("#email-log-attachment-list").append('<li class="list-group-item flex-fill p-1" style="border-radius: 0;"><a href="<?=self::getUrl("EmailLog", "downloadContent")?>?aid=' + item.id + '&hash=' + item.hash + '"><span class="filename text-monospace"><i class="far fa-file"></i> ' + item.filename + '</span></a> (' + Math.round((item.filesize/1024/1024)*100)/100 + ' MB)</li>');
|
|
});
|
|
$("#email-log-attachments-section").show();
|
|
}
|
|
|
|
document.getElementById("email-log-body-view").contentWindow.document.open();
|
|
if(email.bodyIsHtml) {
|
|
document.getElementById("email-log-body-view").contentWindow.document.write(email.body);
|
|
} else {
|
|
var html_body = '<html lang="de"><head><meta charset="utf-8" /></head><body><p>';
|
|
html_body += email.body.replaceAll("\r", "").replaceAll("\n", "<br />");
|
|
html_body += '</p></body></html>';
|
|
document.getElementById("email-log-body-view").contentWindow.document.write(html_body);
|
|
}
|
|
document.getElementById("email-log-body-view").contentWindow.document.close();
|
|
|
|
|
|
$("#email-log-modal").modal("show");
|
|
}
|
|
|
|
function displayEmailLogHeaders() {
|
|
$("#email-log-header-view").toggleClass("hidden");
|
|
if($("#email-log-header-view").hasClass("hidden")) {
|
|
$("#email-log-header-section").find("i").addClass("fa-chevron-right").removeClass("fa-chevron-down");
|
|
} else {
|
|
$("#email-log-header-section").find("i").addClass("fa-chevron-down").removeClass("fa-chevron-right");
|
|
}
|
|
|
|
}
|
|
|
|
function hideEmailLogHeaders() {
|
|
$("#email-log-header-view").empty();
|
|
if(!$("#email-log-header-view").hasClass("hidden")) {
|
|
$("#email-log-header-view").addClass("hidden");
|
|
$("#email-log-header-section").find("i").addClass("fa-chevron-down").removeClass("fa-chevron-right");
|
|
}
|
|
}
|
|
</script>
|
|
<?php include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/footer.php"); ?>
|