@@ -435,7 +200,7 @@
function linkActionChange(link_id) {
//console.log($("#link-" + link_id + "-action-cancel").prop("checked"));
- if($("#link-" + link_id + "-action-cancel").prop("checked")) {
+ if($("#link-" + link_id + "-action-cancel").prop("checked") && $("#finish_date").val()) {
$("#link-" + link_id + "-cancel_date").show();
} else {
$("#link-" + link_id + "-cancel_date").hide();
diff --git a/Layout/default/Contract/View.php b/Layout/default/Contract/View.php
index 357065e4f..a32bf419b 100644
--- a/Layout/default/Contract/View.php
+++ b/Layout/default/Contract/View.php
@@ -231,7 +231,7 @@
diff --git a/Layout/default/Contract/include/productchange-action.php b/Layout/default/Contract/include/productchange-action.php
new file mode 100644
index 000000000..58470eb0d
--- /dev/null
+++ b/Layout/default/Contract/include/productchange-action.php
@@ -0,0 +1,359 @@
+
+
+
+
\ No newline at end of file
diff --git a/Layout/default/Order/Index.php b/Layout/default/Order/Index.php
index 9f947a7d5..95ec4fe67 100644
--- a/Layout/default/Order/Index.php
+++ b/Layout/default/Order/Index.php
@@ -142,7 +142,8 @@
diff --git a/Layout/default/Order/Productchange.php b/Layout/default/Order/Productchange.php
new file mode 100644
index 000000000..73c0ba386
--- /dev/null
+++ b/Layout/default/Order/Productchange.php
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
Produktwechsel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Layout/default/Order/ProductchangeForm.php b/Layout/default/Order/ProductchangeForm.php
new file mode 100644
index 000000000..b3673bebc
--- /dev/null
+++ b/Layout/default/Order/ProductchangeForm.php
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
=$contract->product_name?> (=$contract->id?>)
+
+
+
+ Matchcode:
+ =$contract->matchcode?>
+
+ Vertragsinhaber:
+
+ $contract->owner->id])?>">=$contract->owner->getCompanyOrName()?>
+ (=$contract->owner->customer_number?>)
+
+
+
+ Produkt:
+ =$contract->product_name?> [=$contract->product_id?>
+ ]=($contract->product_name != $contract->product->name) ? " (" . $contract->product->name . ") " : ""?>
+
+ Produkt Info:
+ =$contract->product_info?>
+
+ Preis Netto:
+ ">€ =number_format(($contract->amount != 1) ? $contract->price * $contract->amount : $contract->price, 4, ",", ".")?>
+
+ Preis Brutto:
+ ">€
+ price && $contract->vatrate): ?>
+ amount != 1): ?>
+ =number_format($contract->price + ($contract->price / 100) * $contract->vatrate, 4, ",", ".")?>
+
+ =number_format(($contract->price + ($contract->price / 100) * $contract->vatrate) * $contract->amount, 4, ",", ".")?>
+
+
+
+
+ Fertigstellungsdatum:
+ =date("d.m.Y", $contract->finish_date)?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Layout/default/Preorder/Index.php b/Layout/default/Preorder/Index.php
index 973776820..245bb7e86 100644
--- a/Layout/default/Preorder/Index.php
+++ b/Layout/default/Preorder/Index.php
@@ -437,7 +437,7 @@
});
}
} else {
- preorderMap = L.map('preorder-map').setView([=TT_PLACEHOLDER_GPS_LAT?>, =TT_PLACEHOLDER_GPS_LONG?>], 12);
+ preorderMap = L.map('preorder-map', {fullscreenControl: true}).setView([=TT_PLACEHOLDER_GPS_LAT?>, =TT_PLACEHOLDER_GPS_LONG?>], 12);
}
if(!(currentTileset in tileLayers)) {
diff --git a/Layout/default/header.php b/Layout/default/header.php
index f73c6b3f6..1a1f26627 100644
--- a/Layout/default/header.php
+++ b/Layout/default/header.php
@@ -19,6 +19,7 @@
+
@@ -39,6 +40,7 @@
+
diff --git a/application/Billing/BillingController.php b/application/Billing/BillingController.php
index 3e37c96f1..b6135e4f4 100644
--- a/application/Billing/BillingController.php
+++ b/application/Billing/BillingController.php
@@ -346,6 +346,8 @@ class BillingController extends mfBaseController {
$total_days = $last_of_period->diff($first_of_period)->format("%a") + 1;
$period_days = ($end_date->diff($start_date)->format("%a")) + 1;
+ if($period_days < 0) continue; // don't bill for negative time range
+
$pc = $period_days / $total_days * 100;
$price = round($contract->price / 100 * $pc, 4);
diff --git a/application/Contract/ContractController.php b/application/Contract/ContractController.php
index ec6cf2ebb..bb216f2e8 100644
--- a/application/Contract/ContractController.php
+++ b/application/Contract/ContractController.php
@@ -11,7 +11,7 @@ class ContractController extends mfBaseController
$this->me = $me;
$this->layout()->set("me", $me);
- if (!$me->is(["Admin"])) {
+ if (!$me->is(["Admin", "salespartner", "netowner"])) {
$this->redirect("Dashboard");
}
}
@@ -19,6 +19,10 @@ class ContractController extends mfBaseController
protected function indexAction()
{
+ if(!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
+
$this->layout()->setTemplate("Contract/Index");
if ($this->request->resetFilter) {
@@ -87,6 +91,10 @@ class ContractController extends mfBaseController
protected function viewAction()
{
+ if(!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
+
$this->layout()->setTemplate("Contract/View");
$id = $this->request->contract_id;
@@ -116,6 +124,9 @@ class ContractController extends mfBaseController
}
protected function cancelAction() {
+ if(!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
$this->layout()->setTemplate("Contract/CancelForm");
$id = $this->request->contract_id;
@@ -154,6 +165,9 @@ class ContractController extends mfBaseController
}
protected function saveCancel() {
+ if(!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
$r = $this->request;
$id = $r->contract_id;
@@ -212,6 +226,9 @@ class ContractController extends mfBaseController
}
protected function sendCancelNotification() {
+ if(!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
$contract_id = $this->request->contract_id;
$contract = new Contract($contract_id);
@@ -238,23 +255,65 @@ class ContractController extends mfBaseController
{
$this->layout()->setTemplate("Contract/ProductchangeForm");
+ $f = $this->request->f;
+ if(!$f) {
+ $f = "c"; // from Contract
+ }
+ $this->layout()->set("f", $f);
+
$id = $this->request->contract_id;
if (!$id) {
$id = $this->request->id;
}
if (!is_numeric($id) || !$id) {
$this->layout()->setFlash("Vertrag nicht gefunden", "error");
- $this->redirect("Contract");
+ if($f == "o") {
+ $this->redirect("Order", "addUpgrade");
+ } else {
+ $this->redirect("Contract");
+ }
+
}
$contract = new Contract($id);
if (!$contract->id) {
$this->layout()->setFlash("Vertrag nicht gefunden", "error");
- $this->redirect("Contract");
+ if($f == "o") {
+ $this->redirect("Order", "addUpgrade");
+ } else {
+ $this->redirect("Contract");
+ }
}
+ if($this->me->isAdmin()) {
+ $this->layout()->set("terminations", TerminationModel::getAll());
+ } else {
+ // check permissions
+ // check if correct network
+
+ $my_network_ids = [];
+ foreach($this->me->my_networks as $network) {
+ $my_network_ids[] = $network->id;
+ }
+
+ if($contract->termination_id) {
+ if(!in_array($contract->termination->network_id, $my_network_ids)) {
+ if($f == "o") {
+ // from Order, redirect back to Order
+ $this->layout()->setFlash("Keine Berechtigung", "error");
+ $this->redirect("Order", "addUpgrade", ["owner_id" => $contract->owner_id]);
+ }
+ }
+ }
+
+
+ $terms = TerminationModel::search(["network_id" => $my_network_ids]);
+ $this->layout()->set("terminations", $terms);
+ }
+
+
$this->layout()->set("contract", $contract);
- $this->layout()->set("terminations", TerminationModel::getAll());
+
if ($this->request->filter) {
$this->layout()->set("filter", $this->request->filter);
@@ -266,19 +325,36 @@ class ContractController extends mfBaseController
protected function saveProductchangeAction()
{
+ if(!$this->me->is(["Admin", "salespartner", "netowner"])) {
+ $this->redirect("Dashboard");
+ }
+
$r = $this->request;
//var_dump($r->links);exit;
+ $f = $r->f;
+ if(!$f) {
+ $f = "c"; // from Contract
+ }
+
$id = $r->contract_id;
if (!is_numeric($id) || !$id) {
$this->layout()->setFlash("Vertrag nicht gefunden", "error");
- $this->redirect("Contract");
+ if($f == "o") {
+ $this->redirect("Order", "addUpgrade");
+ } else {
+ $this->redirect("Contract");
+ }
}
$contract = new Contract($id);
if (!$contract->id) {
$this->layout()->setFlash("Vertrag nicht gefunden", "error");
- $this->redirect("Contract");
+ if($f == "o") {
+ $this->redirect("Order", "addUpgrade");
+ } else {
+ $this->redirect("Contract");
+ }
}
$new_contract = clone($contract);
@@ -303,7 +379,12 @@ class ContractController extends mfBaseController
$product = new Product($r->product_id);
if (!$product->id) {
$this->layout()->setFlash("Produkt nicht gefunden", "error");
- $this->redirect("Contract", "productchange", ["contract_id" => $id]);
+ if($f == "o") {
+ $this->redirect("Contract", "productchange", ["contract_id" => $id, "f" => $f]);
+ } else {
+ $this->redirect("Contract", "productchange", ["contract_id" => $id]);
+ }
+
}
$contract_data['product_external'] = $product->external;
@@ -315,7 +396,11 @@ class ContractController extends mfBaseController
$finish_date = DateTime::createFromFormat("d.m.Y", $r->finish_date, new DateTimeZone("Europe/Vienna"));
} catch (Exception $e) {
$this->layout()->setFlash("Ungültiges Kündigungsdateum", "error");
- $this->redirect("Contract", "productchange", ["contract_id" => $id]);
+ if($f == "o") {
+ $this->redirect("Contract", "productchange", ["contract_id" => $id, "f" => $f]);
+ } else {
+ $this->redirect("Contract", "productchange", ["contract_id" => $id]);
+ }
}
$finish_date->setTime(0,0,0);
@@ -334,7 +419,11 @@ class ContractController extends mfBaseController
if (!$contract_data['termination_id'] || !$termination->id) {
$this->layout()->setFlash("Produkt erfordert Anschluss.", "error");
- $this->redirect("Contract", "productchange", ["contract_id" => $id]);
+ if($f == "o") {
+ $this->redirect("Contract", "productchange", ["contract_id" => $id, "f" => $f]);
+ } else {
+ $this->redirect("Contract", "productchange", ["contract_id" => $id]);
+ }
}
} else {
$contract_data['termination_id'] = null;
@@ -371,7 +460,11 @@ class ContractController extends mfBaseController
$cancel_date = DateTime::createFromFormat("d.m.Y", $link_data["cancel_date"], new DateTimeZone("Europe/Vienna"));
} catch (Exception $e) {
$this->layout()->setFlash("Ungültiges Kündigungsdateum", "error");
- $this->redirect("Contract", "productchange", ["contract_id" => $id]);
+ if($f == "o") {
+ $this->redirect("Contract", "productchange", ["contract_id" => $id, "f" => $f]);
+ } else {
+ $this->redirect("Contract", "productchange", ["contract_id" => $id]);
+ }
}
}
@@ -408,7 +501,7 @@ class ContractController extends mfBaseController
}
if ($action == "cancel") {
- if($cancel_date) {
+ if($cancel_date && $contract_cancel_date) {
// insert cancel_date in old contract
$lc = new Contract($origin_id);
$lc->cancel_date = $cancel_date->getTimestamp();
@@ -497,13 +590,21 @@ class ContractController extends mfBaseController
}
$this->layout()->setFlash("Neuer Contract erfolgreich erstellt", "success");
- $this->redirect("Contract", "view", ["contract_id" => $new_contract_id]);
+ if($f == "o") {
+ $this->redirect("Order");
+ } else {
+ $this->redirect("Contract", "view", ["contract_id" => $new_contract_id]);
+ }
+
}
protected function finishContractAction()
{
+ if(!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
$r = $this->request;
$id = $r->contract_id;
@@ -550,6 +651,9 @@ class ContractController extends mfBaseController
protected function addAction()
{
+ if(!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
$this->layout()->setTemplate("Contract/Form");
$this->layout()->set("terminations", TerminationModel::getAll());
@@ -569,6 +673,9 @@ class ContractController extends mfBaseController
protected function editAction()
{
+ if(!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
$id = $this->request->contract_id;
if (!$id) {
$id = $this->request->id;
@@ -602,6 +709,9 @@ class ContractController extends mfBaseController
protected function saveAction()
{
+ if(!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
$r = $this->request;
//var_dump($r);
@@ -787,7 +897,7 @@ class ContractController extends mfBaseController
protected function apiAction()
{
- if (!$this->me->is(["Admin"])) {
+ if (!$this->me->is(["Admin", "salespartner", "netowner"])) {
$this->redirect("Dashboard");
}
$do = $this->request->do;
@@ -797,8 +907,15 @@ class ContractController extends mfBaseController
case "getContract":
$return = $this->getContractApi();
break;
+ case "findContracts":
+ $return = $this->getContractsApi();
+ break;
case "findContract":
$return = $this->findContractApi();
+ break;
+ case "":
+ $return = "";
+ break;
default:
$return = false;
}
@@ -814,6 +931,10 @@ class ContractController extends mfBaseController
private function getContractApi()
{
+ if (!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
+
$contract_id = $this->request->contract_id;
if (!is_numeric($contract_id) || $contract_id < 1) {
return false;
@@ -834,8 +955,58 @@ class ContractController extends mfBaseController
return ["contract" => $data, "form_id" => $form_id];
}
+ private function getContractsApi() {
+ $owner_id = $this->request->owner_id;
+ if(!$owner_id) return false;
+
+ $return = [];
+
+ $contracts = ContractModel::search(["owner_id" => $owner_id]);
+ if(!$contracts) {
+ header("Content-type: application/json");
+ echo json_encode([]);
+ exit;
+ }
+ $is_valid_owner = false;
+
+ if(!$this->me->is("Admin")) {
+ foreach($contracts as $contract) {
+ foreach(ContractLinkModel::includesContractId($contract->id) as $link) {
+ if($link->type != "credit") continue;
+ $link_contract = $link->contract;
+ if($link->contract_id == $contract->id) $link_contract = $link->origin;
+ if($link_contract->owner_id == $this->me->address_id) {
+ $is_valid_owner = true;
+ break;
+ }
+ }
+ }
+
+ if(!$is_valid_owner) {
+ header("Content-type: application/json");
+ echo json_encode([]);
+ exit;
+ }
+ }
+
+
+
+ foreach($contracts as $contract) {
+ $c = get_object_vars($contract->data);
+ $c["id"] = $contract->id;
+ $return[] = $c;
+ }
+
+ header("Content-type: application/json");
+ echo json_encode($return);
+ exit;
+ }
+
private function findContractApi()
{
+ if (!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
$search = trim($this->request->q);
$autocomplete = $this->request->autocomplete;
diff --git a/application/Contract/trigger/Finished.php b/application/Contract/trigger/Finished.php
index bc81bc6ce..7c257414a 100644
--- a/application/Contract/trigger/Finished.php
+++ b/application/Contract/trigger/Finished.php
@@ -48,6 +48,7 @@ class ContractTrigger_Finished {
$now->setTime(2,0,0);
$cancel_date = clone($now);
+ $cancel_date->modify("-1 day");
$cancel_date->setTime(23,59,59);
$origin = $link->origin;
@@ -74,7 +75,7 @@ class ContractTrigger_Finished {
// verlinkten Contract kündigen (wenn nicht schon gekündigt)
if ($old_link->change_action == "cancel" && !$old_link->origin->cancel_date) {
$old_link->origin->update([
- 'cancel_date' => $now->getTimestamp(),
+ 'cancel_date' => $cancel_date->getTimestamp(),
'cancel_date_by' => $this->me->id,
'edit_by' => $this->me->id
]);
@@ -100,7 +101,7 @@ class ContractTrigger_Finished {
// verlinkten Contract kündigen (wenn nicht schon gekündigt)
if ($old_link->change_action == "cancel" && !$old_link->contract->cancel_date) {
$old_link->contract->update([
- 'cancel_date' => $now->getTimestamp(),
+ 'cancel_date' => $cancel_date->getTimestamp(),
'cancel_date_by' => $this->me->id,
'edit_by' => $this->me->id
]);
@@ -126,7 +127,7 @@ class ContractTrigger_Finished {
// Alte Gutschrift kündigen und neue anlegen
//var_dump($old_credit->contract);
$old_credit->contract->update([
- 'cancel_date' => $now->getTimestamp(),
+ 'cancel_date' => $cancel_date->getTimestamp(),
'cancel_date_by' => $this->me->id,
'edit_by' => $this->me->id
]);
diff --git a/application/Order/OrderController.php b/application/Order/OrderController.php
index 2e8e1e52e..2c7cd1697 100644
--- a/application/Order/OrderController.php
+++ b/application/Order/OrderController.php
@@ -150,18 +150,11 @@ class OrderController extends mfBaseController {
}
}
- //if(!$showLonelies) {
- //var_dump($order_search);exit;
- $pagination['maxItems'] = OrderModel::count($order_search);
- foreach(OrderModel::search($order_search, $pagination) as $order) {
- if(!array_key_exists($order->id, $orders)) {
- $orders[$order->id] = $order;
- }
- }
- //}
-
+ $pagination['maxItems'] = OrderModel::count($order_search);
+ $orders = OrderModel::search($order_search, $pagination, true);
+
$showLoneliesCount = false;
- foreach(["owner", "owner_address", "partner_number"] as $key) {
+ foreach(["owner", "owner_address", "partner_number"] as $key) {
if(array_key_exists($key, $filter) && $filter[$key]) {
$showLoneliesCount = true;
break;
@@ -192,7 +185,6 @@ class OrderController extends mfBaseController {
if($this->me->isAdmin()) {
if(!$this->request->filter['network_id']) {
$lonelies = OrderModel::search($order_search);
-
}
} else {
$order_search['create_by'] = $userIds;
@@ -225,7 +217,7 @@ class OrderController extends mfBaseController {
foreach($lonelies as $order) {
// check for voice or special products only
- $this->log->debug("Order id ".$order->id);
+ //$this->log->debug("Order id ".$order->id);
/*if($order->id == 38) {
var_dump($order);
exit;
@@ -379,18 +371,7 @@ class OrderController extends mfBaseController {
$users = [];
foreach($this->me->my_networks as $network) {
$network_ids[] = $network->id;
- /*$tmp_users = $network->getAddressUsersByAddresstype("salespartner");
- foreach($tmp_users as $user) {
- if(!in_array($user->id, $users)) {
- $users[] = $user->id;
- }
- }*/
}
- /*
- // get addresses from salespartner address' user ids
- $addresses = AddressModel::search(["create_by" => $users]);
- $this->layout()->set("addresses", $addresses);
- */
// get terminations in my networks
$terms = TerminationModel::search(["network_id" => $network_ids]);
$this->layout()->set("terminations", $terms);
@@ -445,6 +426,10 @@ class OrderController extends mfBaseController {
return $this->addAction();
}
+
+ protected function upgradesAction() {
+
+ }
protected function setwaitingAction() {
$order_id = $this->request->id;
@@ -476,7 +461,73 @@ class OrderController extends mfBaseController {
$this->layout()->setFlash("Wartestatus erfolgreich gespeichert", "success");
$this->redirect("Order","Index", $qs);
}
-
+
+ protected function addUpgrade() {
+ //$this->layout()->setTemplate("Order/Productchange");
+ Helper::renderVue($this, "OrderProductchange", "Neuer Produktwechsel", ["CONTRACT_API_URL" => $this->getUrl("Contract", "api"),
+ "ADDRESS_API_URL" => $this->getUrl("Address", "api"),
+ "ORDER_PRODUCTCHANGE_URL" => $this->getUrl("Order", "productchange")]);
+
+ }
+
+ protected function productchangeAction() {
+ $this->layout()->setTemplate("Order/ProductchangeForm");
+
+ $f = $this->request->f;
+ if(!$f) {
+ $f = "c"; // from Contract
+ }
+ $this->layout()->set("f", $f);
+
+ $id = $this->request->contract_id;
+ if (!$id) {
+ $id = $this->request->id;
+ }
+ if (!is_numeric($id) || !$id) {
+ $this->layout()->setFlash("Vertrag nicht gefunden", "error");
+ $this->redirect("Order", "addUpgrade");
+ }
+
+ $contract = new Contract($id);
+ if (!$contract->id) {
+ $this->layout()->setFlash("Vertrag nicht gefunden", "error");
+ $this->redirect("Order", "addUpgrade");
+ }
+
+ if($this->me->isAdmin()) {
+ $this->layout()->set("terminations", TerminationModel::getAll());
+ } else {
+ // check permissions
+ // check if correct network
+
+ $my_network_ids = [];
+ foreach($this->me->my_networks as $network) {
+ $my_network_ids[] = $network->id;
+ }
+
+ if($contract->termination_id) {
+ if(!in_array($contract->termination->network_id, $my_network_ids)) {
+ $this->layout()->setFlash("Keine Berechtigung", "error");
+ $this->redirect("Order", "addUpgrade", ["owner_id" => $contract->owner_id]);
+ }
+ }
+
+ $terms = TerminationModel::search(["network_id" => $my_network_ids]);
+ $this->layout()->set("terminations", $terms);
+ }
+
+
+ $this->layout()->set("contract", $contract);
+
+
+ if ($this->request->filter) {
+ $this->layout()->set("filter", $this->request->filter);
+ }
+ if ($this->request->s) {
+ $this->layout()->set("filter", $this->request->s);
+ }
+ }
+
protected function saveAction() {
$r = $this->request;
//var_dump($r->products);
diff --git a/application/Order/OrderModel.php b/application/Order/OrderModel.php
index db4a8ca51..48527d8f2 100644
--- a/application/Order/OrderModel.php
+++ b/application/Order/OrderModel.php
@@ -180,7 +180,7 @@ class OrderModel {
return 0;
}
- public static function search($filter, $limit=false) {
+ public static function search($filter, $limit=false, $withId = false) {
$items = [];
$db = FronkDB::singleton();
@@ -210,7 +210,7 @@ class OrderModel {
if(is_array($limit) && count($limit)) {
if(is_numeric($limit['start']) && is_numeric($limit['count'])) {
$sql .= " LIMIT ".$limit['start'].", ".$limit['count'];
- } elseif(is_numeric($count)) {
+ } elseif(is_numeric($limit['count'])) {
$sql .= " LIMIT ".$limit['count'];
}
}
@@ -218,7 +218,11 @@ class OrderModel {
$res = $db->query($sql);
if($db->num_rows($res)) {
while($data = $db->fetch_object($res)) {
- $items[] = new Order($data);
+ if($withId) {
+ $items[$data->id] = new Order($data);
+ } else {
+ $items[] = new Order($data);
+ }
}
}
diff --git a/application/Product/ProductController.php b/application/Product/ProductController.php
index ef758bd55..5578dd379 100644
--- a/application/Product/ProductController.php
+++ b/application/Product/ProductController.php
@@ -421,9 +421,32 @@ class ProductController extends mfBaseController {
}
$results = [];
-
+
+
+
+ if(!$this->me->isAdmin()) {
+ $my_product_ids = [];
+ $my_network_ids = [];
+ foreach($this->me->my_networks as $network) {
+ $my_network_ids[] = $network->id;
+ }
+
+ foreach(ProductNetworkModel::search(["network_id" => $my_network_ids]) as $pn) {
+ if(!$pn->product->active) continue;
+ if(!array_key_exists($pn->product_id, $my_product_ids)) {
+ $my_product_ids[] = $pn->product_id;
+ }
+ }
+ }
+
// return bootstrap-autocomplete format
foreach($products as $product) {
+ if(!$this->me->isAdmin()) {
+ if(!in_array($product->id, $my_product_ids)) continue;
+ }
+
+
+
$result = ['value' => $product->id, 'text' => str_replace("'", "\\'", str_replace(["\n", "\r"], " ",$product->name))];
$results[] = $result;
if(count($results) > 15) {
diff --git a/public/assets/css/fullscreen.png b/public/assets/css/fullscreen.png
new file mode 100644
index 000000000..7384960ae
Binary files /dev/null and b/public/assets/css/fullscreen.png differ
diff --git a/public/assets/css/fullscreen@2x.png b/public/assets/css/fullscreen@2x.png
new file mode 100644
index 000000000..9fca7f875
Binary files /dev/null and b/public/assets/css/fullscreen@2x.png differ
diff --git a/public/assets/css/leaflet.fullscreen.css b/public/assets/css/leaflet.fullscreen.css
new file mode 100644
index 000000000..f4892578e
--- /dev/null
+++ b/public/assets/css/leaflet.fullscreen.css
@@ -0,0 +1,40 @@
+.leaflet-control-fullscreen a {
+ background:#fff url(fullscreen.png) no-repeat 0 0;
+ background-size:26px 52px;
+ }
+ .leaflet-touch .leaflet-control-fullscreen a {
+ background-position: 2px 2px;
+ }
+ .leaflet-fullscreen-on .leaflet-control-fullscreen a {
+ background-position:0 -26px;
+ }
+ .leaflet-touch.leaflet-fullscreen-on .leaflet-control-fullscreen a {
+ background-position: 2px -24px;
+ }
+
+/* Do not combine these two rules; IE will break. */
+.leaflet-container:-webkit-full-screen {
+ width:100%!important;
+ height:100%!important;
+ }
+.leaflet-container.leaflet-fullscreen-on {
+ width:100%!important;
+ height:100%!important;
+ }
+
+.leaflet-pseudo-fullscreen {
+ position:fixed!important;
+ width:100%!important;
+ height:100%!important;
+ top:0!important;
+ left:0!important;
+ z-index:99999;
+ }
+
+@media
+ (-webkit-min-device-pixel-ratio:2),
+ (min-resolution:192dpi) {
+ .leaflet-control-fullscreen a {
+ background-image:url(fullscreen@2x.png);
+ }
+ }
diff --git a/public/assets/js/Leaflet.fullscreen.min.js b/public/assets/js/Leaflet.fullscreen.min.js
new file mode 100644
index 000000000..fc2eb24a3
--- /dev/null
+++ b/public/assets/js/Leaflet.fullscreen.min.js
@@ -0,0 +1 @@
+(function(factory){var L;if(typeof define==="function"&&define.amd){define(["leaflet"],factory)}else if(typeof module!=="undefined"){L=require("leaflet");module.exports=factory(L)}else{if(typeof window.L==="undefined"){throw new Error("Leaflet must be loaded first")}factory(window.L)}})(function(L){L.Control.Fullscreen=L.Control.extend({options:{position:"topleft",title:{"false":"View Fullscreen","true":"Exit Fullscreen"}},onAdd:function(map){var container=L.DomUtil.create("div","leaflet-control-fullscreen leaflet-bar leaflet-control");this.link=L.DomUtil.create("a","leaflet-control-fullscreen-button leaflet-bar-part",container);this.link.href="#";this._map=map;this._map.on("fullscreenchange",this._toggleTitle,this);this._toggleTitle();L.DomEvent.on(this.link,"click",this._click,this);return container},_click:function(e){L.DomEvent.stopPropagation(e);L.DomEvent.preventDefault(e);this._map.toggleFullscreen(this.options)},_toggleTitle:function(){this.link.title=this.options.title[this._map.isFullscreen()]}});L.Map.include({isFullscreen:function(){return this._isFullscreen||false},toggleFullscreen:function(options){var container=this.getContainer();if(this.isFullscreen()){if(options&&options.pseudoFullscreen){this._disablePseudoFullscreen(container)}else if(document.exitFullscreen){document.exitFullscreen()}else if(document.mozCancelFullScreen){document.mozCancelFullScreen()}else if(document.webkitCancelFullScreen){document.webkitCancelFullScreen()}else if(document.msExitFullscreen){document.msExitFullscreen()}else{this._disablePseudoFullscreen(container)}}else{if(options&&options.pseudoFullscreen){this._enablePseudoFullscreen(container)}else if(container.requestFullscreen){container.requestFullscreen()}else if(container.mozRequestFullScreen){container.mozRequestFullScreen()}else if(container.webkitRequestFullscreen){container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}else if(container.msRequestFullscreen){container.msRequestFullscreen()}else{this._enablePseudoFullscreen(container)}}},_enablePseudoFullscreen:function(container){L.DomUtil.addClass(container,"leaflet-pseudo-fullscreen");this._setFullscreen(true);this.fire("fullscreenchange")},_disablePseudoFullscreen:function(container){L.DomUtil.removeClass(container,"leaflet-pseudo-fullscreen");this._setFullscreen(false);this.fire("fullscreenchange")},_setFullscreen:function(fullscreen){this._isFullscreen=fullscreen;var container=this.getContainer();if(fullscreen){L.DomUtil.addClass(container,"leaflet-fullscreen-on")}else{L.DomUtil.removeClass(container,"leaflet-fullscreen-on")}this.invalidateSize()},_onFullscreenChange:function(e){var fullscreenElement=document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement;if(fullscreenElement===this.getContainer()&&!this._isFullscreen){this._setFullscreen(true);this.fire("fullscreenchange")}else if(fullscreenElement!==this.getContainer()&&this._isFullscreen){this._setFullscreen(false);this.fire("fullscreenchange")}}});L.Map.mergeOptions({fullscreenControl:false});L.Map.addInitHook(function(){if(this.options.fullscreenControl){this.fullscreenControl=new L.Control.Fullscreen(this.options.fullscreenControl);this.addControl(this.fullscreenControl)}var fullscreenchange;if("onfullscreenchange"in document){fullscreenchange="fullscreenchange"}else if("onmozfullscreenchange"in document){fullscreenchange="mozfullscreenchange"}else if("onwebkitfullscreenchange"in document){fullscreenchange="webkitfullscreenchange"}else if("onmsfullscreenchange"in document){fullscreenchange="MSFullscreenChange"}if(fullscreenchange){var onFullscreenChange=L.bind(this._onFullscreenChange,this);this.whenReady(function(){L.DomEvent.on(document,fullscreenchange,onFullscreenChange)});this.on("unload",function(){L.DomEvent.off(document,fullscreenchange,onFullscreenChange)})}});L.control.fullscreen=function(options){return new L.Control.Fullscreen(options)}});
\ No newline at end of file
diff --git a/public/js/pages/OrderProductchange/OrderProductchange.js b/public/js/pages/OrderProductchange/OrderProductchange.js
new file mode 100644
index 000000000..8854eec28
--- /dev/null
+++ b/public/js/pages/OrderProductchange/OrderProductchange.js
@@ -0,0 +1,94 @@
+Vue.component('OrderProductchange', {
+ //language=Vue
+ template: `
+
+
+
+
+
+
Wählen Sie den Vertragsinhaber aus, um die aktiven Produkte anzuzeigen.
+ Produktwechsel sollten immer mit dem Hauptprodukt durchgeführt werden. Dies ist fast immer das Internetzugangsprodukt.
+
+
+
+
+
+ {{owner.name}}
+ {{owner.street}}
+ {{owner.zip}} {{owner.city}}
+
+
+
+
+
+ Produktwechsel erstellen
+
+
+ Monatlich
+ Jährlich
+ Einmalig
+ {{row.billing_period}}
+
+
+ {{window.moment.unix(row.finish_date).isValid() ? window.moment.unix(row.finish_date).format('DD.MM.YYYY') : ''}}
+
+
+ {{window.moment.unix(row.cancel_date).isValid() ? window.moment.unix(row.cancel_date).format('DD.MM.YYYY') : ''}}
+
+
+ € {{row.price | formatPrice}}
+
+
+ € {{row.price_setup | formatPrice}}
+
+
+
+
+
+
+
+
+
+
+ `, data() {
+ return {
+ window: window,
+ OrderProductchangeTableConfig: {
+ headers: [
+ {text: "", key: "actions", class: "text-right", headerClass: "text-right"},
+ {text: "Contract ID", key: "id", class: "text-right", headerClass: "text-right"},
+ {text: "Produkt", key: "product_name", headerClass: "text-left"},
+ {text: "Matchcode", key: "matchcode", headerClass: "text-left"},
+ {text: "Preis", key: "price", headerClass: "text-left"},
+ {text: "Periode", key: "billing_period", headerClass: "text-left"},
+ {text: "Herstellungskosten", key: "price_setup", headerClass: "text-left"},
+ {text: "Fertigstellung", key: "finish_date", filter: "date", headerClass: "text-left"},
+ {text: "Kündigung", key: "cancel_date", filter: "date", headerClass: "text-left"}
+ ],
+ tableHeader: 'Zu änderndes Produkt wählen',
+ key: 'OrderProductchange',
+ },
+ owner_id: "",
+ owner: false
+ }
+ },
+ filters: {
+ formatPrice(price) {
+ roundedPrice = Math.round((parseFloat(price) + Number.EPSILON) * 100) / 100;
+ return roundedPrice.toFixed(4);
+ }
+ },
+ beforeMount() {
+ const urlSearchParams = new URLSearchParams(window.location.search);
+ if (urlSearchParams.has("owner_id")) {
+ this.owner_id = urlSearchParams.get("owner_id");
+ }
+ }
+
+})
+