Files
thetool/Layout/default/PreorderBillingInvoice/Index.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" style="font-size: 125%;" 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" style="font-size: 125%;" 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">&times;</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">&times;</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>&nbsp;</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, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
+ "<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"); ?>