@@ -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/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/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/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 26f6bccda..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;
@@ -821,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;
@@ -847,7 +961,37 @@ class ContractController extends mfBaseController
$return = [];
- foreach(ContractModel::search(["owner_id" => $owner_id]) as $contract) {
+ $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;
@@ -860,6 +1004,9 @@ class ContractController extends mfBaseController
private function findContractApi()
{
+ if (!$this->me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
$search = trim($this->request->q);
$autocomplete = $this->request->autocomplete;
diff --git a/application/Order/OrderController.php b/application/Order/OrderController.php
index f7d086513..2c7cd1697 100644
--- a/application/Order/OrderController.php
+++ b/application/Order/OrderController.php
@@ -371,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);
@@ -437,6 +426,10 @@ class OrderController extends mfBaseController {
return $this->addAction();
}
+
+ protected function upgradesAction() {
+
+ }
protected function setwaitingAction() {
$order_id = $this->request->id;
@@ -471,12 +464,70 @@ class OrderController extends mfBaseController {
protected function addUpgrade() {
//$this->layout()->setTemplate("Order/Productchange");
- Helper::renderVue($this, "OrderProductchange", $this->mod, ["CONTRACT_API_URL" => $this->getUrl("Contract", "api"),
+ Helper::renderVue($this, "OrderProductchange", "Neuer Produktwechsel", ["CONTRACT_API_URL" => $this->getUrl("Contract", "api"),
"ADDRESS_API_URL" => $this->getUrl("Address", "api"),
- "CONTRACT_PRODUCTCHANGE_URL" => $this->getUrl("Contract", "productchange")]);
+ "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/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/js/pages/OrderProductchange/OrderProductchange.js b/public/js/pages/OrderProductchange/OrderProductchange.js
index 4dfb315ca..8854eec28 100644
--- a/public/js/pages/OrderProductchange/OrderProductchange.js
+++ b/public/js/pages/OrderProductchange/OrderProductchange.js
@@ -1,55 +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
-
-
-
-
+ :config="OrderProductchangeTableConfig" :small="false" class="sm"
+ disable-filtering ref="contractTable">
+
+
+ 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: "Contract ID", key: "id", filter: false, order: false},
- {text: "Produkt", key: "product_id", filter: false, order: false},
- {text: "Matchcode", key: "matchcode", filter: false, order: false},
- {text: "Preis p.P.", key: "price", filter: false, order: false},
- {text: "Herstellungskosten", key: "price_setup", filter: false, order: false},
- {text: "Fertigstellung", key: "finish_date", filter: false, order: false},
- {text: "Kündigung", key: "cancel_date", filter: false, order: false},
- {text: "Aktion", key: "actions", filter: false, order: false}
+ {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: 'Aktive Produkte',
+ tableHeader: 'Zu änderndes Produkt wählen',
key: 'OrderProductchange',
},
owner_id: "",
+ owner: false
}
},
- methods: {
-
+ filters: {
+ formatPrice(price) {
+ roundedPrice = Math.round((parseFloat(price) + Number.EPSILON) * 100) / 100;
+ return roundedPrice.toFixed(4);
+ }
},
- watch: {
- owner_id: {
- async handler() {
- console.log(this.owner_id);
- //this.$refs.contractTable.$set(this.$refs.contractTable.fetchUrl, `${this.window['TT_CONFIG']['CONTRACT_API_URL']}?do=findContracts&owner_id=${this.owner_id}`);
- //this.$refs.contractTable.$set(this.$refs.contractTable.filters, 'owner_id', this.owner_id);
- //await this.$refs.contractTable.fetchData();
- }
+ beforeMount() {
+ const urlSearchParams = new URLSearchParams(window.location.search);
+ if (urlSearchParams.has("owner_id")) {
+ this.owner_id = urlSearchParams.get("owner_id");
}
}
+
})