Merge branch 'master' into fronkdev
This commit is contained in:
@@ -484,7 +484,7 @@
|
||||
<th>Neuer Status</th>
|
||||
</tr>
|
||||
<?php foreach($preorder->history as $history): ?>
|
||||
<?php if($history->key != "preorderstatus_id") continue; ?>
|
||||
<?php if($history->key != "status_id") continue; ?>
|
||||
<tr>
|
||||
<td><?=date("d.m.Y H:i:s", $history->create)?></td>
|
||||
<td><?=$history->creator->name?></td>
|
||||
|
||||
@@ -225,6 +225,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="card-title mb-3 mt-3">Lager</h4>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" class="form-check-input" name="can[WarehouseAdmin]" id="can_warehouse_admin" value="1" <?=($user && $user->can("WarehouseAdmin")) ? "checked='checked'" : ""?> />
|
||||
<label for="can_warehouse_admin" class="form-check-label">Lager-Admin</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" class="form-check-input" name="can[WarehouseUser]" id="can_warehouse_user" value="1" <?=($user && $user->can("WarehouseUser")) ? "checked='checked'" : ""?> />
|
||||
<label for="can_warehouse_user" class="form-check-label">Lager-User</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" class="form-check-input" name="can[WarehouseEShop]" id="can_warehouse_e_shop" value="1" <?=($user && $user->can("WarehouseEShop")) ? "checked='checked'" : ""?> />
|
||||
<label for="can_warehouse_e_shop" class="form-check-label">Energie Steiermark Shop</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="card-title mb-3 mt-3">Zusatzberechtigungen</h4>
|
||||
|
||||
|
||||
@@ -130,23 +130,28 @@
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if($me->is(["Admin"])&& isset($_GET['warehouse'])): ?>
|
||||
<?php if($me->can(["WarehouseAdmin", "WarehouseUser", "WarehouseEShop"])): ?>
|
||||
<li class="has-submenu">
|
||||
<a href="#">
|
||||
<i class="fa-solid fa-warehouse"></i>Lager <div class="arrow-down"></div>
|
||||
<?php if ($me->can("WarehouseEShop") && !($me->can("WarehouseAdmin") || $me->can("WarehouseUser"))): ?>
|
||||
<i class="fas fa-fw fa-shopping-cart"></i>E-Shop<div class="arrow-down"></div>
|
||||
<?php elseif ($me->can("WarehouseAdmin") || $me->can("WarehouseUser")): ?>
|
||||
<i class="fas fa-fw fa-warehouse"></i>Lager<div class="arrow-down"></div>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<ul class="submenu">
|
||||
<!-- create links for WarehouseArticle, WarehouseDistributor, WarehouseLocation, WarehouseItem, WarehouseOrderRecommendation -->
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseArticle")): ?><li><a href="<?=self::getUrl("WarehouseArticle")?>?warehouse"><i class="far fa-fw fa-box text-info"></i> Artikel</a></li><?php endif; ?>
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseDistributor")): ?><li><a href="<?=self::getUrl("WarehouseDistributor")?>?warehouse"><i class="far fa-fw fa-truck text-info"></i> Lieferanten</a></li><?php endif; ?>
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseArticlePriceType")): ?><li><a href="<?=self::getUrl("WarehouseArticlePriceType")?>?warehouse"><i class="far fa-fw fa-money-bill-wave text-info"></i> Preis Typen</a></li><?php endif; ?>
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseLocation")): ?><li><a href="<?=self::getUrl("WarehouseLocation")?>?warehouse"><i class="far fa-fw fa-map-marker-alt text-info"></i> Lagerorte</a></li><?php endif; ?>
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseItem")): ?><li><a href="<?=self::getUrl("WarehouseItem")?>?warehouse"><i class="far fa-fw fa-boxes text-info"></i> Lagerbestand</a></li><?php endif; ?>
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseOrderRecommendation")): ?><li><a href="<?=self::getUrl("WarehouseOrderRecommendation")?>?warehouse"><i class="far fa-fw fa-box-full text-info"></i> Bestellvorschläge</a></li><?php endif; ?>
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseEShop")): ?><li><a href="<?=self::getUrl("WarehouseEShop")?>?warehouse"><i class="far fa-fw fa-shopping-cart text-info"></i> E-Shop</a></li><?php endif; ?>
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseEShopOrder")): ?><li><a href="<?=self::getUrl("WarehouseEShopOrder")?>?warehouse"><i class="far fa-fw fa-shopping-basket text-info"></i> E-Shop Bestellungen</a></li><?php endif; ?>
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseOrder")): ?><li><a href="<?=self::getUrl("WarehouseOrder")?>?warehouse"><i class="far fa-fw fa-shopping-bag text-info"></i> Bestellungen</a></li><?php endif; ?>
|
||||
<?php if($me->isAdmin() || $me->can("WarehouseShippingNote")): ?><li><a href="<?=self::getUrl("WarehouseShippingNote")?>?warehouse"><i class="far fa-fw fa-shipping-fast text-info"></i> Lieferscheine</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmin")): ?><li><a href="<?=self::getUrl("WarehouseArticle")?>"><i class="far fa-fw fa-box text-info"></i> Artikel</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmin")): ?><li><a href="<?=self::getUrl("WarehouseArticlePacket")?>"><i class="far fa-fw fa-box text-info"></i> Artikel-Pakete (EStmk)</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmin")): ?><li><a href="<?=self::getUrl("WarehouseDistributor")?>"><i class="far fa-fw fa-truck text-info"></i> Lieferanten</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmin")): ?><li><a href="<?=self::getUrl("WarehouseArticlePriceType")?>"><i class="far fa-fw fa-money-bill-wave text-info"></i> Preis Typen</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmin")): ?><li><a href="<?=self::getUrl("WarehouseLocation")?>"><i class="far fa-fw fa-map-marker-alt text-info"></i> Lagerorte</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmin")): ?><li><a href="<?=self::getUrl("WarehouseItem")?>"><i class="far fa-fw fa-boxes text-info"></i> Lagerbestand</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmin")): ?><li><a href="<?=self::getUrl("WarehouseOrderRecommendation")?>"><i class="far fa-fw fa-box-full text-info"></i> Bestellvorschläge</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseEShop")): ?><li><a href="<?=self::getUrl("WarehouseEShop")?>"><i class="far fa-fw fa-shopping-cart text-info"></i> E-Shop</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmin")): ?><li><a href="<?=self::getUrl("WarehouseEShopOrder")?>"><i class="far fa-fw fa-shopping-basket text-info"></i> E-Shop Bestellungen</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmins")): ?><li><a href="<?=self::getUrl("WarehouseOrder")?>"><i class="far fa-fw fa-shopping-bag text-info"></i> Bestellungen</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmins")): ?><li><a href="<?=self::getUrl("WarehouseShippingNote")?>"><i class="far fa-fw fa-shipping-fast text-info"></i> Lieferscheine</a></li><?php endif; ?>
|
||||
<?php if($me->can("WarehouseAdmin")): ?><li><a href="<?=self::getUrl("WarehouseRevenueAccount")?>"><i class="far fa-fw fa-money-bill-wave text-info"></i> Erlöskontos</a></li><?php endif; ?>
|
||||
</ul>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -16,9 +16,47 @@ class ADBHausnummer extends mfBaseModel {
|
||||
}
|
||||
|
||||
public function afterSave() {
|
||||
if($this->netzgebiet_id && !$this->gps_long && !$this->gps_lat) {
|
||||
$this->getGpsCoords();
|
||||
}
|
||||
// prevent potential infinite loop
|
||||
$nesting_level = mfValuecache::singleton()->get("adbhausnummer-save-nesting-level-".$this->id);
|
||||
if(!$nesting_level) {
|
||||
$nesting_level = 1;
|
||||
} else {
|
||||
$nesting_level++;
|
||||
}
|
||||
mfValuecache::singleton()->set("adbhausnummer-save-nesting-level-".$this->id, $nesting_level);
|
||||
|
||||
if($nesting_level > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if($this->netzgebiet_id && !$this->gps_long && !$this->gps_lat) {
|
||||
$this->getGpsCoords();
|
||||
}
|
||||
|
||||
|
||||
// Statuschange from Rimo statuschange for all units
|
||||
foreach(ADBWohneinheitModel::search(["hausnummer_id" => $this->id]) as $wohneinheit) {
|
||||
AddressDB::handleRimoStatusUpdate($wohneinheit->id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function setNewStatusCode($new_status_code) {
|
||||
if(!$new_status_code) return false;
|
||||
|
||||
$this->log->debug(__METHOD__.": Want new Hausnummer (".$this->id.") Status ".$new_status_code);
|
||||
|
||||
$new_status = ADBStatusModel::getFirst(["code" => $new_status_code]);
|
||||
if(!$new_status) return false;
|
||||
|
||||
$old_status = $this->getProperty("status");
|
||||
if($old_status->code < $new_status->code) {
|
||||
$this->log->debug(__METHOD__.": Setting Hausnummer (".$this->id.") Status from ".$old_status->code." to ".$new_status->code);
|
||||
$this->status_id = $new_status->id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getGpsCoords() {
|
||||
|
||||
@@ -14,7 +14,23 @@ class ADBWohneinheit extends mfBaseModel {
|
||||
protected function afterSave() {
|
||||
if(!$this->id) return true;
|
||||
if(!$this->hausnummer_id) return true;
|
||||
|
||||
|
||||
// prevent potential infinite loop
|
||||
$nesting_level = mfValuecache::singleton()->get("adbwohneinheit-save-nesting-level-".$this->id);
|
||||
if(!$nesting_level) {
|
||||
$nesting_level = 1;
|
||||
} else {
|
||||
$nesting_level++;
|
||||
}
|
||||
mfValuecache::singleton()->set("adbwohneinheit-save-nesting-level-".$this->id, $nesting_level);
|
||||
|
||||
if($nesting_level > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Statuschange from Rimo statuschange
|
||||
AddressDB::handleRimoStatusUpdate($this->id);
|
||||
|
||||
// ADBWohneinheit_onSave_noAutoUnitCount can be defined if doing bulk
|
||||
// operations where unit count is calculated seperately
|
||||
if(!defined("ADBWohneinheit_onSave_noAutoUnitCount") || !ADBWohneinheit_onSave_noAutoUnitCount) {
|
||||
@@ -36,6 +52,20 @@ class ADBWohneinheit extends mfBaseModel {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function setNewStatusCode($new_status_code) {
|
||||
if(!$new_status_code) return false;
|
||||
|
||||
$new_status = ADBStatusModel::getFirst(["code" => $new_status_code]);
|
||||
if(!$new_status) return false;
|
||||
|
||||
$old_status = $this->getProperty("status");
|
||||
if($old_status->code < $new_status->code) {
|
||||
$this->status_id = $new_status->id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function parseHausnummerZusatz($text) {
|
||||
|
||||
|
||||
@@ -70,7 +70,83 @@ class AddressDB {
|
||||
$this->db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
|
||||
$this->log = mfLoghandler::singleton();
|
||||
}
|
||||
|
||||
|
||||
public static function handleRimoStatusUpdate($wohneinheit_id) {
|
||||
if(!$wohneinheit_id) return true;
|
||||
|
||||
$log = mfLoghandler::singleton();
|
||||
//echo "in handleRimoStatusUpdate\n";
|
||||
|
||||
$wohneinheit = new ADBWohneinheit($wohneinheit_id);
|
||||
if(!$wohneinheit->id) return false;
|
||||
|
||||
$hausnummer = $wohneinheit->hausnummer;
|
||||
if(!$hausnummer->netzgebiet->getOption("statuschange")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$preorder = PreorderModel::getFirstActive(["adb_wohneinheit_id" => $wohneinheit->id]);
|
||||
if(!$preorder) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$b_ex_state = strtolower($hausnummer->rimo_ex_state);
|
||||
$b_op_state = strtolower($hausnummer->rimo_op_state);
|
||||
|
||||
$h_ex_state = strtolower($wohneinheit->rimo_ex_state);
|
||||
$h_op_state = strtolower($wohneinheit->rimo_op_state);
|
||||
|
||||
$wo_state = false;
|
||||
$workorder = $wohneinheit->rimo_workorder;
|
||||
if($workorder) {
|
||||
$wo_state = strtolower($workorder->rimo_status);
|
||||
}
|
||||
|
||||
|
||||
$order_type = $preorder->type;
|
||||
|
||||
foreach(TT_PREORDER_RIMO_STATUS_MATRIX as $matrix) {
|
||||
//echo "wohneinheit ".$wohneinheit->id."\n";
|
||||
//var_dump($matrix);
|
||||
if($matrix["rbop"] && $matrix["rbop"] != $b_op_state) continue;
|
||||
if($matrix["rbex"] && $matrix["rbex"] != $b_ex_state) continue;
|
||||
|
||||
if($matrix["rhop"] && $matrix["rhop"] != $h_op_state) continue;
|
||||
if($matrix["rhex"] && $matrix["rhex"] != $h_ex_state) continue;
|
||||
|
||||
if($matrix["rwo"] && (!$workorder || $matrix["rwo"] != $wo_state)) continue;
|
||||
|
||||
if($matrix["pt"] && $matrix["pt"] != $order_type) continue;
|
||||
// seems all criteria match => set new status
|
||||
|
||||
$log->debug(__METHOD__.": new Preorder Status: ".$matrix["p"]);
|
||||
|
||||
$preorderstatus = $matrix["p"];
|
||||
if(!$preorderstatus) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$preorder->setNewStatusCode($preorderstatus);
|
||||
$preorder->save();
|
||||
|
||||
$hausnummer_status = $matrix["h"];
|
||||
if($hausnummer_status) {
|
||||
$log->debug(__METHOD__.": new Hausnummer (".$hausnummer->id.") status: ".$matrix["h"]);
|
||||
$hausnummer->setNewStatusCode($hausnummer_status);
|
||||
$hausnummer->save();
|
||||
}
|
||||
|
||||
$wohneinheit_status = $matrix["w"];
|
||||
if($wohneinheit_status) {
|
||||
$wohneinheit->setNewStatusCode($wohneinheit_status);
|
||||
$wohneinheit->save();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function import($input) {
|
||||
$path = __DIR__."/Importer/";
|
||||
$dir = opendir($path);
|
||||
|
||||
@@ -180,5 +180,39 @@ class IpNetworkController extends mfBaseController {
|
||||
}
|
||||
}
|
||||
|
||||
private function update(): array {
|
||||
$json = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
try {
|
||||
IpNetworkModel::updateIpNetwork($json);
|
||||
return [
|
||||
"status" => "success",
|
||||
"message" => "IP Network updated."
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
return [
|
||||
"status" => "error",
|
||||
"message" => $e->getMessage()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private function delete(): array {
|
||||
$json = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
try {
|
||||
IpNetworkModel::deleteIpNetwork($json['id']);
|
||||
return [
|
||||
"status" => "success",
|
||||
"message" => "IP Network deleted."
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
return [
|
||||
"status" => "error",
|
||||
"message" => $e->getMessage()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -200,6 +200,24 @@ class IpNetworkModel {
|
||||
}
|
||||
}
|
||||
|
||||
public static function updateIpNetwork($data): void {
|
||||
$db = FronkDB::singleton();
|
||||
|
||||
$sqlSetStr = "";
|
||||
$sqlSetStr .= isset($data['status']) ? "`status` = '" . $data['status'] . "', " : "";
|
||||
$sqlSetStr .= isset($data['name']) ? "`name` = '" . $data['name'] . "', " : "";
|
||||
$sqlSetStr .= isset($data['description']) ? "`description` = '" . $data['description'] . "', " : "";
|
||||
$sqlSetStr .= isset($data['location']) ? "`location` = '" . $data['location'] . "', " : "";
|
||||
$sqlSetStr .= "`edit` = UNIX_TIMESTAMP()";
|
||||
|
||||
$sql = "UPDATE `IpNetwork` SET $sqlSetStr WHERE `id` = " . $data['id'];
|
||||
$result = $db->query($sql);
|
||||
|
||||
if (!$result) {
|
||||
throw new Exception("Failed to update network");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function getById($id) {
|
||||
$db = FronkDB::singleton();
|
||||
@@ -209,4 +227,22 @@ class IpNetworkModel {
|
||||
return $row ? new IpNetworkModel($row) : null;
|
||||
}
|
||||
|
||||
public static function deleteIpNetwork($id) {
|
||||
// delete this id and all children and children of children until no more children
|
||||
$db = FronkDB::singleton();
|
||||
$sql = "SELECT `id` FROM `IpNetwork` WHERE `parent_network_id` = $id";
|
||||
$result = $db->query($sql);
|
||||
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
self::deleteIpNetwork($row['id']);
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM `IpNetwork` WHERE `id` = $id";
|
||||
$result = $db->query($sql);
|
||||
if (!$result) {
|
||||
throw new Exception("Failed to delete network");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -235,7 +235,7 @@ class Preorder extends mfBaseModel {
|
||||
|
||||
}
|
||||
|
||||
private function cascadeStatusToPreorders() {
|
||||
public function cascadeStatusToPreorders() {
|
||||
$status = new Preorderstatus($this->status_id);
|
||||
if(!$status->id) {
|
||||
return false;
|
||||
@@ -427,6 +427,18 @@ class Preorder extends mfBaseModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setNewStatusCode($new_status_code) {
|
||||
if(!$new_status_code) return false;
|
||||
|
||||
$new_status = PreorderstatusModel::getFirst(["code" => $new_status_code]);
|
||||
if(!$new_status) return false;
|
||||
|
||||
$status = $this->getProperty("status");
|
||||
if($status->code < $new_status->code) {
|
||||
$this->status_id = $new_status->id;
|
||||
}
|
||||
}
|
||||
|
||||
public function createUcode() {
|
||||
$ucode = $this->generateNewUcode();
|
||||
|
||||
@@ -3,7 +3,27 @@
|
||||
class RimoWorkorder extends mfBaseModel {
|
||||
private $adb_wohneinheit;
|
||||
private $termination;
|
||||
|
||||
|
||||
public function afterSave() {
|
||||
// prevent potential infinite loop
|
||||
$nesting_level = mfValuecache::singleton()->get("rimoworkorder-save-nesting-level-".$this->id);
|
||||
if(!$nesting_level) {
|
||||
$nesting_level = 1;
|
||||
} else {
|
||||
$nesting_level++;
|
||||
}
|
||||
mfValuecache::singleton()->set("rimoworkorder-save-nesting-level-".$this->id, $nesting_level);
|
||||
|
||||
if($nesting_level > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Statuschange from Rimo statuschange for all units
|
||||
$wohneinheit = $this->getProperty("adb_wohneinheit");
|
||||
if($wohneinheit) {
|
||||
AddressDB::handleRimoStatusUpdate($wohneinheit->id);
|
||||
}
|
||||
}
|
||||
|
||||
public function getProperty($name) {
|
||||
if($this->$name == null) {
|
||||
|
||||
@@ -261,10 +261,9 @@ class User extends mfBaseModel {
|
||||
if(!is_array($what)) {
|
||||
$what = [$what];
|
||||
}
|
||||
|
||||
//ob_end_clean();var_dump($what, $this->permissions);exit;
|
||||
|
||||
foreach($what as $w) {
|
||||
$perm = ucfirst(strtolower($w));
|
||||
$perm = ucfirst(($w));
|
||||
if(is_object($this->permissions) && property_exists($this->permissions->data, "can$perm")) {
|
||||
if($this->permissions->{"can$perm"} === "true") {
|
||||
return true;
|
||||
|
||||
@@ -235,6 +235,9 @@ class UserController extends mfBaseController
|
||||
$user->permissions->canBilling = "false";
|
||||
$user->permissions->canFibu = "false";
|
||||
$user->permissions->canStatistics = "false";
|
||||
$user->permissions->canWarehouseAdmin = "false";
|
||||
$user->permissions->canWarehouseEShop = "false";
|
||||
$user->permissions->canWarehouseUser = "false";
|
||||
|
||||
if($r->get("can") && is_array($r->can)) {
|
||||
foreach($r->can as $key => $can) {
|
||||
|
||||
@@ -9,11 +9,16 @@ class WarehouseArticleController extends TTCrud {
|
||||
['key' => 'title', 'text' => 'Titel', 'required' => true, 'table' => ['priority' => 9]],
|
||||
['key' => 'description', 'text' => 'Beschreibung', 'required' => true, 'table' => false],
|
||||
['key' => 'category', 'text' => 'Kategorie', 'required' => true],
|
||||
['key' => 'unit', 'text' => 'Einheit', 'required' => true,'table' => false], // Boolean value
|
||||
['key' => 'defaultSellMultiplier', 'text' => 'Standard Multiplikator','regex' => '/^[0-9]*$/' , 'required' => true,'modal' => ['type' => 'number'], 'table' => false], // Boolean value
|
||||
['key' => 'revenueAccount', 'text' => 'Erlöskonto', 'required' => true,'modal' => ['type' => 'select'], 'table' => false], // Boolean value
|
||||
['key' => 'cheapestPurchasePrice', 'text' => 'Einkauf', 'modal' => false, 'table' => ['class' => 'text-center', 'suffix' => ' €']],
|
||||
['key' => 'cheapestSellPrice', 'text' => 'Verkauf', 'modal' => false, 'table' => ['class' => 'text-center', 'suffix' => ' €']],
|
||||
['key' => 'warningAmount', 'text' => 'Warnmenge', 'modal' => ['type' => 'number'], 'table' => ['class' => 'text-center']], // Stock/inventory related
|
||||
['key' => 'criticalAmount', 'text' => 'Kritische Menge', 'modal' => ['type' => 'number'], 'table' => ['class' => 'text-center']], // Stock/inventory related
|
||||
['key' => 'isEShop', 'text' => 'Ist E-Shop', 'modal' => ['type' => 'checkbox'], 'table' => false], // Boolean value
|
||||
['key' => 'warningAmount', 'text' => 'Warnmenge', 'required' => true,'modal' => ['type' => 'number'], 'table' => ['class' => 'text-center']], // Stock/inventory related
|
||||
['key' => 'criticalAmount', 'text' => 'Kritische Menge', 'required' => true,'modal' => ['type' => 'number'], 'table' => ['class' => 'text-center']], // Stock/inventory related
|
||||
['key' => 'isSerialDocumentation', 'text' => 'Seriennummern', 'required' => true,'modal' => ['type' => 'checkbox'], 'table' => false], // Boolean value
|
||||
['key' => 'isEShop', 'text' => 'Ist E-Shop', 'required' => true,'modal' => ['type' => 'checkbox'], 'table' => false], // Boolean value
|
||||
['key' => 'isEShopHide', 'text' => 'E-Shop Versteckt', 'required' => true,'modal' => ['type' => 'checkbox'], 'table' => false], // Boolean value
|
||||
['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center', 'priority' => 8]]
|
||||
];
|
||||
|
||||
@@ -30,6 +35,15 @@ class WarehouseArticleController extends TTCrud {
|
||||
'delete' => 'Artikel wurde gelöscht',
|
||||
'noChanges' => 'Keine Änderungen',];
|
||||
|
||||
public function prepareCrudConfig() {
|
||||
$revenueAccounts = WarehouseRevenueAccountModel::getAll();
|
||||
$revenueAccounts = array_map(function ($revenueAccount) {
|
||||
return ['value' => $revenueAccount->id, 'text' => $revenueAccount->title];
|
||||
}, $revenueAccounts);
|
||||
|
||||
$this->columns[5]['modal']['items'] = $revenueAccounts;
|
||||
}
|
||||
|
||||
protected function beforeUpdate($postData): bool {
|
||||
(new WarehouseHistoryController)->create($postData, $this->mod);
|
||||
return true;
|
||||
@@ -39,33 +53,75 @@ class WarehouseArticleController extends TTCrud {
|
||||
self::updateCheapestPurchasePrice($postData['id']);
|
||||
}
|
||||
|
||||
public static function updateCheapestPurchasePrice($articleId) {
|
||||
$cheapestPurchasePrice = WarehouseArticleDistributorModel::getAll(['articleId' => $articleId], 1, 0,
|
||||
['key' => 'purchasePrice', 'order' => 'ASC'])[0]->purchasePrice;
|
||||
|
||||
/**
|
||||
* Updates the cheapest purchase price for a given article from WarehouseArticleDistributorModel prices.
|
||||
*
|
||||
* @param int $articleId The ID of the article to update.
|
||||
* @return void
|
||||
* @throws Exception If the article is not an instance of WarehouseArticleModel.
|
||||
*/
|
||||
public static function updateCheapestPurchasePrice(int $articleId): void {
|
||||
$article = WarehouseArticleModel::get($articleId);
|
||||
|
||||
if (!$article instanceof WarehouseArticleModel) {
|
||||
throw new Exception("Article is not an instance of WarehouseArticleModel");
|
||||
}
|
||||
|
||||
//TODO: think of a new way as we have multiple sell prices now and article sellPriceOverride and sellPriceMultiplier do not exist anymore
|
||||
// $cheapestSellPrice = $article->sellPriceOverride ?? $article->sellPriceMultiplier * $cheapestPurchasePrice;
|
||||
$order = ['key' => 'purchasePrice', 'order' => 'ASC'];
|
||||
$cheapestDistributorEntry = WarehouseArticleDistributorModel::getAll(['articleId' => $articleId], 1, 0, $order);
|
||||
|
||||
if ($article->cheapestPurchasePrice != $cheapestPurchasePrice) {
|
||||
WarehouseArticleModel::update([...get_object_vars($article), // Unpack properties into an array
|
||||
'cheapestPurchasePrice' => $cheapestPurchasePrice]);
|
||||
}
|
||||
if (empty($cheapestDistributorEntry)) return;
|
||||
|
||||
$cheapestPurchasePrice = $cheapestDistributorEntry[0]->purchasePrice;
|
||||
if ($article->cheapestPurchasePrice == $cheapestPurchasePrice) return;
|
||||
WarehouseArticleModel::update(array_merge(get_object_vars($article), ['cheapestPurchasePrice' => $cheapestPurchasePrice]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sell prices for a given article.
|
||||
*
|
||||
* @param int $articleId The ID of the article to update.
|
||||
* @return void
|
||||
* @throws Exception If the article is not an instance of WarehouseArticleModel.
|
||||
*/
|
||||
public static function updateSellPrices(int $articleId) {
|
||||
$article = WarehouseArticleModel::get($articleId);
|
||||
if (!$article instanceof WarehouseArticleModel) {
|
||||
throw new Exception("Article is not an instance of WarehouseArticleModel");
|
||||
}
|
||||
|
||||
$priceTypes = WarehouseArticlePriceTypeModel::getAll();
|
||||
$articlePriceTypes = WarehouseArticlePriceModel::getAll(['articleId' => $articleId]);
|
||||
|
||||
$cheapestSellPrices = [];
|
||||
// Calculate sell prices for each price type, use default sell multiplier if no specific price is set
|
||||
foreach ($priceTypes as $priceType) {
|
||||
$articlePriceType = array_filter($articlePriceTypes, function ($apt) use ($priceType) {
|
||||
return $apt->articlePriceTypeId == $priceType->id;
|
||||
});
|
||||
|
||||
$sellPrice = $article->defaultSellMultiplier * $article->cheapestPurchasePrice;
|
||||
if (!empty($articlePriceType)) {
|
||||
$articlePriceType = $articlePriceType[0];
|
||||
$sellPrice = $articlePriceType->priceOverride ?: $articlePriceType->priceMultiplier * $article->cheapestPurchasePrice;
|
||||
}
|
||||
$cheapestSellPrices[$priceType->id] = ['title' => $priceType->title, 'price' => $sellPrice];
|
||||
}
|
||||
|
||||
$article->cheapestSellPrice = json_encode($cheapestSellPrices);
|
||||
WarehouseArticleModel::update(get_object_vars($article));
|
||||
}
|
||||
|
||||
|
||||
protected function afterCreate($postData) {
|
||||
self::updateCheapestPurchasePrice($postData['id']);
|
||||
self::updateSellPrices($postData['id']);
|
||||
}
|
||||
|
||||
protected function updateAllCheapestPurchasePricesAction() {
|
||||
$articles = WarehouseArticleModel::getAll();
|
||||
foreach ($articles as $article) {
|
||||
protected function updatePricesAction() {
|
||||
foreach (WarehouseArticleModel::getAll() as $article) {
|
||||
self::updateCheapestPurchasePrice($article->id);
|
||||
self::updateSellPrices($article->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,12 +231,12 @@ class WarehouseArticleController extends TTCrud {
|
||||
|
||||
// Check if ArticleDistributor exists
|
||||
$articleDistributor = WarehouseArticleDistributorModel::getAll(['articleId' => $articleId,
|
||||
'distributorId' => $distributorId]);
|
||||
'distributorId' => $distributorId]);
|
||||
if (empty($articleDistributor)) {
|
||||
WarehouseArticleDistributorModel::create(['articleId' => $articleId,
|
||||
'distributorId' => $distributorId,
|
||||
'purchasePrice' => $purchasePrice,
|
||||
'externalArticleNumber' => $item['Lieferant/ Hersteller Artikelnr:'],]);
|
||||
'distributorId' => $distributorId,
|
||||
'purchasePrice' => $purchasePrice,
|
||||
'externalArticleNumber' => $item['Lieferant/ Hersteller Artikelnr:'],]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,10 +6,15 @@ class WarehouseArticleModel extends TTCrudBaseModel {
|
||||
public string $description;
|
||||
public string $category;
|
||||
public ?float $cheapestPurchasePrice;
|
||||
public ?float $cheapestSellPrice;
|
||||
public ?string $cheapestSellPrice;
|
||||
public int $warningAmount;
|
||||
public int $criticalAmount;
|
||||
public int $isEShop;
|
||||
public int $isEShopHide;
|
||||
public float $defaultSellMultiplier;
|
||||
public string $unit;
|
||||
public int $isSerialDocumentation;
|
||||
public int $revenueAccount;
|
||||
|
||||
|
||||
}
|
||||
@@ -20,29 +20,37 @@ class WarehouseArticleDistributorController extends TTCrud {
|
||||
'delete' => 'Lieferanteintrag wurde gelöscht',
|
||||
'noChanges' => 'Keine Änderungen',];
|
||||
|
||||
protected function checkExistingThresholdEntry($postData): bool {
|
||||
$count = WarehouseLocationThresholdOverrideModel::count(['articleId' => $postData['articleId'],
|
||||
'distributorId' => $postData['distributorId']]);
|
||||
|
||||
if ($count > 0) {
|
||||
self::returnJson(['success' => false,
|
||||
'message' => 'Es existiert bereits ein Eintrag mit dieser Artikelnummer und diesem Lieferanten.']);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
protected function beforeCreate($postData): bool {
|
||||
return $this->checkExistingDistributorEntry($postData);
|
||||
}
|
||||
|
||||
protected function beforeCreate($postData): bool {
|
||||
return $this->checkExistingThresholdEntry($postData);
|
||||
protected function checkExistingDistributorEntry($postData): bool {
|
||||
if (isset($postData['id'])) {
|
||||
$count = WarehouseArticleDistributorModel::count(['articleId' => $postData['articleId'],
|
||||
'distributorId' => $postData['articlePriceTypeId'],
|
||||
'id' => $postData['id']]);
|
||||
|
||||
if ($count > 0) return true;
|
||||
} else {
|
||||
$count = WarehouseArticleDistributorModel::count(['articleId' => $postData['articleId'],
|
||||
'distributorId' => $postData['distributorId']]);
|
||||
if ($count > 0) {
|
||||
self::returnJson(['success' => false,
|
||||
'message' => 'Es existiert bereits ein Eintrag mit dieser Artikelnummer und diesem Lieferanten.']);
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function afterCreate($postData) {
|
||||
WarehouseArticleController::updateCheapestPurchasePrice($postData['articleId']);
|
||||
WarehouseArticleController::updateSellPrices($postData['articleId']);
|
||||
}
|
||||
|
||||
protected function beforeUpdate($postData): bool {
|
||||
$existing = $this->checkExistingThresholdEntry($postData);
|
||||
$existing = $this->checkExistingDistributorEntry($postData);
|
||||
|
||||
if (!$existing) {
|
||||
return false;
|
||||
@@ -55,6 +63,7 @@ class WarehouseArticleDistributorController extends TTCrud {
|
||||
|
||||
protected function afterUpdate($postData) {
|
||||
WarehouseArticleController::updateCheapestPurchasePrice($postData['articleId']);
|
||||
WarehouseArticleController::updateSellPrices($postData['articleId']);
|
||||
}
|
||||
|
||||
protected function getHistoryAction() {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property mixed|null $name
|
||||
*/
|
||||
class WarehouseArticlePacket extends mfBaseModel
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
class WarehouseArticlePacketController extends TTCrud {
|
||||
protected string $headerTitle = 'Artikel-Pakete';
|
||||
protected string $createText = 'Artikel-Paket erstellen';
|
||||
|
||||
// @formatter:off
|
||||
protected array $columns = [
|
||||
['key' => 'title', 'text' => 'Titel', 'required' => true],
|
||||
['key' => 'description', 'text' => 'Beschreibung', 'required' => true],
|
||||
['key' => 'category', 'text' => 'Kategorie', 'required' => true],
|
||||
['key' => 'overrideSellPrice', 'text' => 'Überschriebener Verkaufspreis', 'required' => false, 'modal' => ['type' => 'number'], 'table' => false],
|
||||
['key' => 'calculatedSellPrice', 'text' => 'Verkaufspreis', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false]],
|
||||
['key' => 'subItems', 'text' => 'Unterartikel', 'required' => true],
|
||||
['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center', 'priority' => 10]],
|
||||
];
|
||||
// @formatter:on
|
||||
|
||||
protected array $infoMessages = ['create' => 'Artikel-Paket wurde erstellt',
|
||||
'update' => 'Artikel-Paket wurde aktualisiert',
|
||||
'delete' => 'Artikel-Paket wurde gelöscht',
|
||||
'noChanges' => 'Keine Änderungen'];
|
||||
|
||||
protected function prepareCrudConfig() {
|
||||
$articles = array_map(function ($article) {
|
||||
return ['value' => $article->id, 'text' => $article->title];
|
||||
}, WarehouseArticleModel::getAll(
|
||||
['isEShop' => 1],
|
||||
));
|
||||
|
||||
$this->columns[5]['modal']['items'] = $articles;
|
||||
}
|
||||
|
||||
//TODO: make this so it does not update all packets at the same time
|
||||
protected function updatePacketPricesAction() {
|
||||
$packets = WarehouseArticlePacketModel::getAll();
|
||||
$articles = WarehouseArticleModel::getAll(['isEShop' => 1]);
|
||||
|
||||
// packet has $calculatedSellPrice for this but when overrideSellPrice is set, it should be used
|
||||
|
||||
foreach ($packets as $packet) {
|
||||
if ($packet->overrideSellPrice) {
|
||||
$calculatedSellPrice = $packet->overrideSellPrice;
|
||||
} else {
|
||||
$subItems = json_decode($packet->subItems);
|
||||
$calculatedSellPrice = 0;
|
||||
|
||||
foreach ($subItems as $subItem) {
|
||||
$article = WarehouseArticleModel::get($subItem->id);
|
||||
$cheapestSellPrices = json_decode($article->cheapestSellPrice);
|
||||
// find in array cheapestSellPrices by title === 'Energie Steiermark' and get the price
|
||||
$articlePrice = array_values(array_filter($cheapestSellPrices, function ($cheapestSellPrice) {
|
||||
return $cheapestSellPrice->title === 'Energie Steiermark';
|
||||
}))[0]->price;
|
||||
|
||||
$calculatedSellPrice += $subItem->amount * $articlePrice;
|
||||
}
|
||||
}
|
||||
|
||||
WarehouseArticlePacketModel::update([...get_object_vars($packet), // Unpack properties into an array
|
||||
'calculatedSellPrice' => $calculatedSellPrice]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function afterUpdate(): bool {
|
||||
return $this->updatePacketPricesAction();
|
||||
}
|
||||
|
||||
protected function afterCreate(): bool {
|
||||
return $this->updatePacketPricesAction();
|
||||
}
|
||||
|
||||
protected function beforeUpdate($postData): bool {
|
||||
(new WarehouseHistoryController)->create($postData, $this->mod);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getHistoryAction() {
|
||||
$history = WarehouseHistoryModel::getByRowId($this->request->id, $this->mod);
|
||||
|
||||
$history = array_map(function ($item) {
|
||||
$item = (array) $item;
|
||||
|
||||
$item['columnHeader'] = $this->columns[array_search($item['key'], array_column($this->columns, 'key'))]['text'];
|
||||
return $item;
|
||||
}, $history);
|
||||
|
||||
self::returnJson($history);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
class WarehouseArticlePacketModel extends TTCrudBaseModel {
|
||||
public int $id;
|
||||
public string $title;
|
||||
public string $description;
|
||||
public string $category;
|
||||
public ?float $overrideSellPrice;
|
||||
public ?float $calculatedSellPrice;
|
||||
public string $subItems;
|
||||
}
|
||||
@@ -22,7 +22,16 @@ class WarehouseArticlePriceController extends TTCrud {
|
||||
return $this->validate($postData);
|
||||
}
|
||||
|
||||
//TODO: phpdoc and simplify
|
||||
protected function validate($postData): bool {
|
||||
// if either priceOverride or priceMultiplier is empty set it to null
|
||||
if (isset($postData['priceOverride']) && $postData['priceOverride'] === '') {
|
||||
$postData['priceOverride'] = null;
|
||||
}
|
||||
if (isset($postData['priceMultiplier']) && $postData['priceMultiplier'] === '') {
|
||||
$postData['priceMultiplier'] = null;
|
||||
}
|
||||
|
||||
// check if postData priceOverride or priceMultiplier is set but only one of them
|
||||
if (isset($postData['priceOverride']) && isset($postData['priceMultiplier'])) {
|
||||
self::returnJson(['success' => false,
|
||||
@@ -34,11 +43,11 @@ class WarehouseArticlePriceController extends TTCrud {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (isset($postData['id'])) {
|
||||
$count = WarehouseArticlePriceModel::count(['articleId' => $postData['articleId'],
|
||||
'articlePriceTypeId' => $postData['articlePriceTypeId'],
|
||||
'id' => $postData['id']]);
|
||||
|
||||
if ($count > 0) return true;
|
||||
} else {
|
||||
$count = WarehouseArticlePriceModel::count(['articleId' => $postData['articleId'],
|
||||
@@ -78,4 +87,12 @@ class WarehouseArticlePriceController extends TTCrud {
|
||||
self::returnJson($history);
|
||||
}
|
||||
|
||||
public function afterCreate($postData) {
|
||||
WarehouseArticleController::updateSellPrices($postData['articleId']);
|
||||
}
|
||||
|
||||
public function afterUpdate($postData) {
|
||||
WarehouseArticleController::updateSellPrices($postData['articleId']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -51,6 +51,14 @@ class WarehouseArticlePriceTypeController extends TTCrud {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function afterCreate($postData) {
|
||||
WarehouseArticleController::updateSellPrices($postData['articleId']);
|
||||
}
|
||||
|
||||
public function afterUpdate($postData) {
|
||||
WarehouseArticleController::updateSellPrices($postData['articleId']);
|
||||
}
|
||||
|
||||
protected function getHistoryAction() {
|
||||
$history = WarehouseHistoryModel::getByRowId($this->request->id, $this->mod);
|
||||
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
<?php
|
||||
// Warrenkorb löschen
|
||||
// File Upload ermöglichen
|
||||
// Hide Articles
|
||||
|
||||
|
||||
|
||||
class WarehouseEShopController extends TTCrud {
|
||||
protected string $headerTitle = 'Energie Steiermark Shop';
|
||||
protected bool $createText = false;
|
||||
|
||||
protected array $columns = [
|
||||
['key' => 'title', 'text' => 'Titel'],
|
||||
['key' => 'category', 'text' => 'Kategorie'],
|
||||
['key' => 'title', 'text' => 'Artikel'],
|
||||
['key' => 'category', 'text' => 'Kategorie', 'table' => false],
|
||||
['key' => 'price', 'text' => 'Preis', 'table' => ['filter' => false,'sortable' => false,'class' => 'text-right']],
|
||||
['key' => 'amount', 'text' => 'Menge', 'table' => ['filter' => false,'sortable' => false,'class' => 'p-0 width-80']],
|
||||
['key' => 'add', 'text' => 'Hinzufügen', 'table' => ['filter' => false,'sortable' => false, 'class' => 'width-120 text-center']]
|
||||
];
|
||||
@@ -18,24 +24,36 @@ class WarehouseEShopController extends TTCrud {
|
||||
'noChanges' => 'Keine Änderungen',
|
||||
];
|
||||
|
||||
public function permissionCheck(): bool {
|
||||
return $this->user->can(["WarehouseEShop"]);
|
||||
}
|
||||
|
||||
public function getAction() {
|
||||
$filter = $this->postData['filters'] ?? [];
|
||||
$order = $this->postData['order'] ?? ['key' => null, 'order' => 'ASC'];
|
||||
$page = $this->postData['pagination']['page'] ?? 1;
|
||||
$perPage = $this->postData['pagination']['per_page'] ?? 10;
|
||||
|
||||
$filter['isEShop'] = 1;
|
||||
$warehouseArticleFilter = $filter;
|
||||
$warehouseArticleFilter['isEShop'] = 1;
|
||||
$warehouseArticleFilter['isEShopHide'] = 0;
|
||||
|
||||
$rows = WarehouseArticleModel::getAll($filter, $perPage, ($page - 1) * $perPage, $order);
|
||||
$filteredAvailable = WarehouseArticleModel::count($filter);
|
||||
$totalRows = WarehouseArticleModel::count(['isEShop' => 1]);
|
||||
$warehouseArticles = WarehouseArticleModel::getAll($warehouseArticleFilter, $perPage, ($page - 1) * $perPage, $order);
|
||||
$warehouseArticlesTotal = WarehouseArticleModel::count(['isEShop' => 1, 'isEShopHide' => 0]);
|
||||
$warehouseArticlesAvailable = WarehouseArticleModel::count($warehouseArticleFilter);
|
||||
|
||||
$warehousePackets = WarehouseArticlePacketModel::getAll();
|
||||
$warehousePacketsTotal = WarehouseArticlePacketModel::count();
|
||||
$warehousePacketsAvailable = WarehouseArticlePacketModel::count($filter);
|
||||
|
||||
$filteredAvailable = $warehouseArticlesAvailable + $warehousePacketsAvailable;
|
||||
$totalRows = $warehouseArticlesTotal + $warehousePacketsTotal;
|
||||
$rows = [...$warehouseArticles, ...$warehousePackets];
|
||||
|
||||
self::returnJson(["rows" => $rows,
|
||||
"pagination" => ["page" => $page,
|
||||
"total_pages" => ceil($filteredAvailable / $perPage),
|
||||
"per_page" => $perPage,
|
||||
"filtered_available" => intval($filteredAvailable),
|
||||
"total_rows" => intval($totalRows)]]); }
|
||||
|
||||
|
||||
"filtered_available" => $filteredAvailable,
|
||||
"total_rows" => $totalRows]]); }
|
||||
}
|
||||
@@ -9,7 +9,7 @@ class WarehouseEShopOrderController extends TTCrud {
|
||||
['key' => 'status', 'text' => 'Status', 'required' => true],
|
||||
['key' => 'deliveryMode', 'text' => 'Liefermodus', 'required' => true, 'modal' => ['type' => 'select', 'items' => [
|
||||
['value' => 'singleAddress', 'text' => 'Einzelne Adresse'],
|
||||
['value' => 'multipleAddresses', 'text' => 'Mehrere Adressen'],
|
||||
// ['value' => 'multipleAddresses', 'text' => 'Mehrere Adressen'],
|
||||
]]],
|
||||
['key' => 'deliveryAddressName', 'text' => 'Lieferadresse Name', 'required' => true, 'table' => false],
|
||||
['key' => 'deliveryAddressLine', 'text' => 'Lieferadresse', 'required' => true, 'required_length' => 4],
|
||||
@@ -31,6 +31,10 @@ class WarehouseEShopOrderController extends TTCrud {
|
||||
'noChanges' => 'Keine Änderungen',
|
||||
];
|
||||
|
||||
public function permissionCheck(): bool {
|
||||
return $this->user->can(["WarehouseEShop"]);
|
||||
}
|
||||
|
||||
protected function prepareCrudConfig() {
|
||||
$users = array_map(function($user) {
|
||||
return ['value' => intval($user->id), 'text' => $user->name];
|
||||
@@ -67,11 +71,24 @@ class WarehouseEShopOrderController extends TTCrud {
|
||||
|
||||
// now create WarehouseEShopOrderItems for each item in the shopping cart
|
||||
foreach ($shoppingCart as $item) {
|
||||
WarehouseEShopOrderItemModel::create([
|
||||
'orderId' => $id,
|
||||
'articleId' => $item['itemId'],
|
||||
'quantity' => intval($item['amount']),
|
||||
]);
|
||||
// itemId can either be P-[PACKETID] or I-[ARTICLEID]
|
||||
// parse this and either fill articleId or articlePacketId for warehouseEShopOrderItem
|
||||
if (strpos($item['itemId'], 'P-') === 0) {
|
||||
WarehouseEShopOrderItemModel::create([
|
||||
'orderId' => $id,
|
||||
'articlePacketId' => intval(substr($item['itemId'], 2)),
|
||||
'quantity' => intval($item['amount']),
|
||||
]);
|
||||
} else if (strpos($item['itemId'], 'I-') === 0) {
|
||||
WarehouseEShopOrderItemModel::create([
|
||||
'orderId' => $id,
|
||||
'articleId' => intval(substr($item['itemId'], 2)),
|
||||
'quantity' => intval($item['amount']),
|
||||
]);
|
||||
} else {
|
||||
self::returnJson(['success' => false, 'message' => 'Invalid item id']);
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
self::returnJson(['success' => true,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
class WarehouseEShopOrderItemModel extends TTCrudBaseModel {
|
||||
public int $id;
|
||||
public int $orderId;
|
||||
public int $articleId;
|
||||
public ?int $articleId;
|
||||
public ?int $articlePacketId;
|
||||
public int $quantity;
|
||||
}
|
||||
@@ -24,9 +24,8 @@ class WarehouseHistoryModel {
|
||||
public static function create($data) {
|
||||
$FronkDB = FronkDB::singleton();
|
||||
$db = $FronkDB->link;
|
||||
$sql = /** @lang text */ "INSERT INTO `WarehouseHistory` (`table`, `row_id`, `key`, `old_value`, `new_value`, `note`, `user_id`, `create`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute([
|
||||
|
||||
$dataArr = [
|
||||
$data["table"],
|
||||
$data["row_id"],
|
||||
$data["key"],
|
||||
@@ -35,9 +34,16 @@ class WarehouseHistoryModel {
|
||||
$data["note"],
|
||||
$data["user_id"],
|
||||
$data["create"]
|
||||
]);
|
||||
];
|
||||
|
||||
return $stmt->insert_id;
|
||||
$sqlValueStr = "(" . implode(", ", array_map(function ($item) use ($db) {
|
||||
return "'" . $db->real_escape_string($item) . "'";
|
||||
}, $dataArr)) . ")";
|
||||
|
||||
$sql = /** @lang text */ "INSERT INTO `WarehouseHistory` (`table`, `row_id`, `key`, `old_value`, `new_value`, `note`, `user_id`, `create`) VALUES $sqlValueStr";
|
||||
$db->query($sql) or die($db->error);
|
||||
|
||||
return $db->insert_id;
|
||||
}
|
||||
/**
|
||||
* Retrieves an array of WarehouseHistoryModel objects by row ID.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property mixed|null $name
|
||||
*/
|
||||
class WarehouseRevenueAccount extends mfBaseModel
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
class WarehouseRevenueAccountController extends TTCrud {
|
||||
protected string $headerTitle = 'Erlöskontos';
|
||||
protected string $createText = 'Erlöskonto erstellen';
|
||||
|
||||
// @formatter:off
|
||||
protected array $columns = [
|
||||
['key' => 'title', 'text' => 'Titel', 'required' => true],
|
||||
['key' => 'revenueAccountNumber', 'text' => 'Erlöskonto Nummer', 'required' => true, 'modal' => ['type' => 'number']],
|
||||
['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center', 'priority' => 10]],
|
||||
];
|
||||
// @formatter:on
|
||||
|
||||
protected array $infoMessages = ['create' => 'Erlöskonto wurde erstellt',
|
||||
'update' => 'Erlöskonto wurde aktualisiert',
|
||||
'delete' => 'Erlöskonto wurde gelöscht',
|
||||
'noChanges' => 'Keine Änderungen'];
|
||||
|
||||
protected function beforeUpdate($postData): bool {
|
||||
(new WarehouseHistoryController)->create($postData, $this->mod);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getHistoryAction() {
|
||||
$history = WarehouseHistoryModel::getByRowId($this->request->id, $this->mod);
|
||||
|
||||
$history = array_map(function ($item) {
|
||||
$item = (array) $item;
|
||||
|
||||
$item['columnHeader'] = $this->columns[array_search($item['key'], array_column($this->columns, 'key'))]['text'];
|
||||
return $item;
|
||||
}, $history);
|
||||
|
||||
self::returnJson($history);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
class WarehouseRevenueAccountModel extends TTCrudBaseModel {
|
||||
public int $id;
|
||||
public int $revenueAccountNumber;
|
||||
public string $title;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php /** @noinspection ALL */
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class WorkerPermissionAddcanWarehouse extends AbstractMigration {
|
||||
public function up(): void {
|
||||
if ($this->getEnvironment() == "thetool") {
|
||||
$table = $this->table("WorkerPermission");
|
||||
$table->addColumn("canWarehouseAdmin", "enum", ["null" => false, "values" => 'false,true', "default" => "false", "after" => "canSuperexpert"]);
|
||||
$table->addColumn("canWarehouseUser", "enum", ["null" => false, "values" => 'false,true', "default" => "false", "after" => "canSuperexpert"]);
|
||||
$table->addColumn("canWarehouseEShop", "enum", ["null" => false, "values" => 'false,true', "default" => "false", "after" => "canSuperexpert"]);
|
||||
$table->update();
|
||||
}
|
||||
|
||||
if ($this->getEnvironment() == "addressdb") {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void {
|
||||
if ($this->getEnvironment() == "thetool") {
|
||||
$table = $this->table("WorkerPermission");
|
||||
$table->removeColumn("canWarehouseAdmin");
|
||||
$table->removeColumn("canWarehouseUser");
|
||||
$table->removeColumn("canWarehouseEShop");
|
||||
$table->save();
|
||||
}
|
||||
|
||||
if ($this->getEnvironment() == "addressdb") {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
62
db/migrations/20240724143300_update_warehouse_tables.php
Normal file
62
db/migrations/20240724143300_update_warehouse_tables.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php /** @noinspection ALL */
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class UpdateWarehouseTables extends AbstractMigration {
|
||||
public function up(): void {
|
||||
if ($this->getEnvironment() == "thetool") {
|
||||
$WarehouseArticle = $this->table("WarehouseArticle");
|
||||
$WarehouseArticle->changeColumn("cheapestSellPrice", "text", ["null" => false]);
|
||||
$WarehouseArticle->addColumn("defaultSellMultiplier", "float", ["null" => false, "default" => 1]);
|
||||
$WarehouseArticle->addColumn("unit", "string", ["null" => false]);
|
||||
$WarehouseArticle->addColumn("isSerialDocumentation", "integer", ["null" => false]);
|
||||
$WarehouseArticle->addColumn("revenueAccount", "integer", ["null" => false]);
|
||||
$WarehouseArticle->update();
|
||||
|
||||
$WarehouseArticlePacket = $this->table("WarehouseArticlePacket", ["signed" => true]);
|
||||
$WarehouseArticlePacket->addColumn("title", "string", ["null" => false]);
|
||||
$WarehouseArticlePacket->addColumn("description", "text", ["null" => false]);
|
||||
$WarehouseArticlePacket->addColumn("category", "string", ["null" => false]);
|
||||
$WarehouseArticlePacket->addColumn("overrideSellPrice", "float", ["null" => true]);
|
||||
$WarehouseArticlePacket->addColumn("calculatedSellPrice", "float", ["null" => true]);
|
||||
$WarehouseArticlePacket->addColumn("subItems", "text", ["null" => false]);
|
||||
$WarehouseArticlePacket->create();
|
||||
|
||||
$WarehouseEShopOrderItem = $this->table("WarehouseEShopOrderItem");
|
||||
$WarehouseEShopOrderItem->changeColumn("articleId", "integer", ["null" => true]);
|
||||
$WarehouseEShopOrderItem->addColumn("articlePacketId", "integer", ["null" => true]);
|
||||
$WarehouseEShopOrderItem->update();
|
||||
|
||||
$WarehouseRevenueAccount = $this->table("WarehouseRevenueAccount", ["signed" => true]);
|
||||
$WarehouseRevenueAccount->addColumn("revenueAccountNumber", "integer", ["null" => false]);
|
||||
$WarehouseRevenueAccount->addColumn("title", "string", ["null" => false]);
|
||||
$WarehouseRevenueAccount->create();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void {
|
||||
if ($this->getEnvironment() == "thetool") {
|
||||
$WarehouseArticle = $this->table("WarehouseArticle");
|
||||
$WarehouseArticle->changeColumn("cheapestSellPrice", "float", ["null" => false]);
|
||||
$WarehouseArticle->removeColumn("defaultSellMultiplier");
|
||||
$WarehouseArticle->removeColumn("unit");
|
||||
$WarehouseArticle->removeColumn("isSerialDocumentation");
|
||||
$WarehouseArticle->removeColumn("revenueAccount");
|
||||
$WarehouseArticle->update();
|
||||
|
||||
$WarehouseArticlePacket = $this->table("WarehouseArticlePacket");
|
||||
$WarehouseArticlePacket->drop()->save();
|
||||
|
||||
$WarehouseEShopOrderItem = $this->table("WarehouseEShopOrderItem");
|
||||
$WarehouseEShopOrderItem->changeColumn("articleId", "integer", ["null" => false]);
|
||||
$WarehouseEShopOrderItem->removeColumn("articlePacketId");
|
||||
$WarehouseEShopOrderItem->update();
|
||||
|
||||
$WarehouseRevenueAccount = $this->table("WarehouseRevenueAccount");
|
||||
$WarehouseRevenueAccount->drop()->save();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
22
db/migrations/20240724155700_warehouse_add_e_shop_hide.php
Normal file
22
db/migrations/20240724155700_warehouse_add_e_shop_hide.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php /** @noinspection ALL */
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class WarehouseAddEShopHide extends AbstractMigration {
|
||||
public function up(): void {
|
||||
if ($this->getEnvironment() == "thetool") {
|
||||
$WarehouseArticle = $this->table("WarehouseArticle");
|
||||
$WarehouseArticle->addColumn("isEShopHide", "integer", ["null" => false]);
|
||||
$WarehouseArticle->update();
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void {
|
||||
if ($this->getEnvironment() == "thetool") {
|
||||
$WarehouseArticle = $this->table("WarehouseArticle");
|
||||
$WarehouseArticle->removeColumn("isEShopHide");
|
||||
$WarehouseArticle->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,8 @@ class Helper {
|
||||
$sql .= " AND `$columnName` LIKE '%" . $item . "%'";
|
||||
}
|
||||
}
|
||||
} else if ($filterValue === 0) {
|
||||
$sql .= " AND `$columnName` = 0";
|
||||
}
|
||||
|
||||
return $sql;
|
||||
@@ -61,6 +63,11 @@ class Helper {
|
||||
$value = $data[$key] ?? null;
|
||||
$title = $rules['title'] ?? $key;
|
||||
|
||||
//TODO: fix this, skip arrays for now
|
||||
if (is_array($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Apply default values for missing rules
|
||||
|
||||
$rules = array_merge([
|
||||
|
||||
@@ -23,7 +23,12 @@ class TTCrud extends mfBaseController {
|
||||
$this->user = $me;
|
||||
$this->layout()->set('me', $me);
|
||||
|
||||
if (!$me->is(["Admin"])) {
|
||||
if (method_exists($this, 'permissionCheck')) {
|
||||
$allowed = $this->permissionCheck();
|
||||
if (!$allowed) {
|
||||
$this->redirect("Dashboard");
|
||||
}
|
||||
} else if (!$me->is(["Admin"])) {
|
||||
$this->redirect("Dashboard");
|
||||
}
|
||||
|
||||
@@ -118,7 +123,7 @@ class TTCrud extends mfBaseController {
|
||||
$id = $this->model::create($this->postData);
|
||||
|
||||
if (method_exists($this, 'afterCreate')) {
|
||||
$this->afterCreate($this->postData);
|
||||
$this->afterCreate(array_merge($this->postData, ['id' => $id]));
|
||||
}
|
||||
|
||||
self::returnJson(['success' => true,
|
||||
|
||||
@@ -68,12 +68,17 @@ class TTCrudBaseModel {
|
||||
}
|
||||
|
||||
|
||||
public static function get($id): TTCrudBaseModel {
|
||||
public static function get($id, $die= false): TTCrudBaseModel {
|
||||
$FronkDB = FronkDB::singleton();
|
||||
$db = $FronkDB->link;
|
||||
$id = $db->real_escape_string($id);
|
||||
$table = self::getTable();
|
||||
$sql = "SELECT * FROM `$table` WHERE `id` = $id";
|
||||
|
||||
if($die) {
|
||||
die($sql);
|
||||
}
|
||||
|
||||
$result = $db->query($sql);
|
||||
// as TTCRudBaseModel is abstract, we need to get the class name of the child class
|
||||
$class = get_called_class();
|
||||
@@ -148,6 +153,13 @@ class TTCrudBaseModel {
|
||||
if ($field === "id") {
|
||||
continue;
|
||||
}
|
||||
// TODO: make this cleaner
|
||||
if ($value === "" && (new ReflectionProperty(get_called_class(), $field))->getType()->getName() === "float") {
|
||||
$value = null;
|
||||
}
|
||||
if ($value === "" && (new ReflectionProperty(get_called_class(), $field))->getType()->getName() === "int") {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
$values[] = $value === null ? "`$field` = NULL" : "`$field` = '" . $db->real_escape_string($value) . "'";
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ Vue.component('IpNetwork', {
|
||||
<i class="fas fa-sync-alt"></i>Go Back
|
||||
</button>
|
||||
|
||||
<button type="button" class="btn btn-primary" @click="addModal = true">
|
||||
<button type="button" class="btn btn-primary" @click="openModal(false)">
|
||||
<i class="fas fa-sync-alt"></i>Add new Network Space
|
||||
</button>
|
||||
|
||||
@@ -28,6 +28,13 @@ Vue.component('IpNetwork', {
|
||||
<span style="white-space: pre;" v-if="row.description" v-text="row.description"></span>
|
||||
<span v-else>No description</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:actions="{ row }">
|
||||
<div style="display: flex; justify-content: space-around; align-items: center; min-width: 20px">
|
||||
<a style="cursor: pointer;" @click.stop="openModal(row)"><i class="far fa-edit text-primary"
|
||||
title="Editieren"></i></a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</tt-table>
|
||||
|
||||
@@ -47,11 +54,12 @@ Vue.component('IpNetwork', {
|
||||
<div class="form-group">
|
||||
<label for="network_address">Network Address</label>
|
||||
<input type="text" class="form-control" id="network_address"
|
||||
:disabled="!!addModalData.id"
|
||||
v-model="addModalData.network_address">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cidr">CIDR</label>
|
||||
<input type="text" class="form-control" id="cidr" v-model="addModalData.cidr">
|
||||
<input type="text" class="form-control" id="cidr" :disabled="!!addModalData.id" v-model="addModalData.cidr">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="status">Status</label>
|
||||
@@ -83,6 +91,7 @@ Vue.component('IpNetwork', {
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" @click="addSubmit">Save</button>
|
||||
<button class="btn btn-danger" @click="deleteSubmit" v-if="addModalData.id">Delete</button>
|
||||
<button class="btn btn-secondary" @click="addModal = false">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -112,6 +121,7 @@ Vue.component('IpNetwork', {
|
||||
{value: 'reserved', text: 'Reserved', icon: 'fas fa-lock text-warning'}]
|
||||
},
|
||||
{text: 'Children', key: 'children', filter: 'numberRange'},
|
||||
{text: 'Aktionen', key: 'actions', sortable: false},
|
||||
],
|
||||
tableHeader: 'IPAM',
|
||||
key: 'IpNetwork'
|
||||
@@ -140,6 +150,34 @@ Vue.component('IpNetwork', {
|
||||
|
||||
},
|
||||
methods: {
|
||||
openModal(row = false) {
|
||||
if (row) {
|
||||
const data = JSON.parse(JSON.stringify(row));
|
||||
|
||||
|
||||
this.addModalData = {
|
||||
id: data.id,
|
||||
network_address: data.network_address_str.split('/')[0],
|
||||
cidr: data.cidr,
|
||||
parent_network_id: this.currentNetworkData ? this.currentNetworkData.id : '',
|
||||
status: data.status,
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
location: data.location,
|
||||
}
|
||||
} else {
|
||||
this.addModalData = {
|
||||
network_address: '',
|
||||
cidr: '',
|
||||
parent_network_id: this.currentNetworkData ? this.currentNetworkData.id : '',
|
||||
status: 'active',
|
||||
name: '',
|
||||
description: '',
|
||||
location: '',
|
||||
};
|
||||
}
|
||||
this.addModal = true;
|
||||
},
|
||||
async switchCurrentNetwork(networkId = null) {
|
||||
if (!networkId) {
|
||||
this.$refs.table.$set(this.$refs.table.filters, 'parent_network_id', undefined);
|
||||
@@ -159,18 +197,30 @@ Vue.component('IpNetwork', {
|
||||
await this.$refs.table.fetchData();
|
||||
},
|
||||
async addSubmit() {
|
||||
const response = await axios.post(`${this.apiUrl}?do=create`,
|
||||
const response = await axios.post(`${this.apiUrl}?do=${this.addModalData.id ? 'update' : 'create'}`,
|
||||
{
|
||||
...this.addModalData,
|
||||
parent_network_id: this.currentNetworkData ? this.currentNetworkData.id : null
|
||||
});
|
||||
if (response.data.status === 'success') {
|
||||
this.addModal = false;
|
||||
this.addModalData = {};
|
||||
window.notify('success', 'Network space created successfully');
|
||||
await this.$refs.table.fetchData();
|
||||
} else {
|
||||
window.notify('error', response.data.message);
|
||||
}
|
||||
},
|
||||
async deleteSubmit() {
|
||||
const response = await axios.post(`${this.apiUrl}?do=delete`, {id: this.addModalData.id});
|
||||
if (response.data.status === 'success') {
|
||||
this.addModal = false;
|
||||
this.addModalData = {};
|
||||
window.notify('success', 'Network space deleted successfully');
|
||||
await this.$refs.table.fetchData();
|
||||
} else {
|
||||
window.notify('error', response.data.message);
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@@ -37,7 +37,7 @@ Vue.component('warehouse-distributor-modal', {
|
||||
|
||||
this.rows = response.data.rows
|
||||
}, addRow() {
|
||||
this.rows.push({distributor: null, price: null, externalArticleNumber: null});
|
||||
this.rows.push({distributorId: undefined, price: null, externalArticleNumber: null});
|
||||
}, async saveRow(index) {
|
||||
// post to /WarehouseArticleDistributor/save with rows data and articleId
|
||||
const row = this.rows[index];
|
||||
@@ -256,6 +256,12 @@ Vue.component('warehouse-article', {
|
||||
@editPricesEntries="priceModal = true; priceModalId = $event.id"
|
||||
@editThresholdEntries="thresholdModal = true; thresholdModalId = $event.id">
|
||||
|
||||
<template v-slot:cheapestsellprice="{ row }">
|
||||
<template v-for="price in JSON.parse(row.cheapestSellPrice)">
|
||||
<span v-if="price">{{price.title}}: {{(price.price)}} €</span><br>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-slot:cheapestPurchasePrice="{ row }">
|
||||
<span>{{(row.cheapestPurchasePrice * row.sellPriceMultiplier).toFixed(2)}} €</span>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
Vue.component('WarehouseArticlePacket', {
|
||||
//language=Vue
|
||||
template: `
|
||||
<tt-card>
|
||||
<tt-table-crud @openHistory="historyModal = true; historyModalId = $event.id" ref="WarehouseArticlePacketCrud">
|
||||
|
||||
<template v-slot:subitems="{row}">
|
||||
<template v-for="item in JSON.parse(row.subItems)">
|
||||
<span v-if="articles.find(article => article.value === item.id)">
|
||||
{{item.amount + 'x '}}{{articles.find(article => article.value === item.id).text}}<br>
|
||||
</span>
|
||||
<span v-else></span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-slot:subitems-modal="{crudModalData}">
|
||||
<!-- TODO: add autocomplete and list with items, each removable, just simple quick-->
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr auto;grid-gap: 8px">
|
||||
<tt-autocomplete v-model="subItemsAutocomplete"
|
||||
:items="articles"
|
||||
ref="subItemsAutocomplete"
|
||||
label="Subitems" sm/>
|
||||
<tt-input v-model="newSubItemAmount" label="Menge" sm/>
|
||||
<button type="button" class="btn btn-primary" @click="addSubItem" style="max-height: 32px; align-self: center">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<ul class="list-group" v-if="typeof subItems !== 'undefined' && subItems.length > 0" :key="updateCounter">
|
||||
<template v-for="item in subItems">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
Menge {{item.amount}} | Artikel {{articles.find(article => article.value === item.id).text}}
|
||||
<button type="button" class="btn btn-danger btn-sm" @click="removeSubItem(item)">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<span v-else>Keine Artikel hinzugefügt</span>
|
||||
|
||||
</template>
|
||||
|
||||
</tt-table-crud>
|
||||
<warehouse-history-modal :show.sync="historyModal" :id="historyModalId"/>
|
||||
</tt-card>
|
||||
`, data() {
|
||||
return {
|
||||
window: window,
|
||||
historyModal: false,
|
||||
historyModalId: null,
|
||||
subItemsAutocomplete: '',
|
||||
articles: [],
|
||||
updateCounter: 0,
|
||||
newSubItemAmount: 1,
|
||||
subItems: []
|
||||
}
|
||||
}, beforeMount() {
|
||||
this.articles = window['TT_CONFIG']['CRUD_CONFIG'].columns.find(column => column.key === 'subItems').modal.items;
|
||||
}, methods: {
|
||||
updateCrudModalData() {
|
||||
const ref = this.$refs.WarehouseArticlePacketCrud;
|
||||
ref.$set(ref.crudModalData, 'subItems', JSON.stringify(this.subItems));
|
||||
this.updateCounter++;
|
||||
}, removeSubItem(item) {
|
||||
this.subItems = this.subItems.filter(subItem => subItem !== item);
|
||||
this.updateCrudModalData();
|
||||
}, addSubItem() {
|
||||
// only continue if id and amount are set else use window.notify('error', 'Bitte Artikel und Menge auswählen');
|
||||
if (this.subItemsAutocomplete === '' || this.newSubItemAmount === '') {
|
||||
window.notify('error', 'Bitte Artikel und Menge auswählen');
|
||||
return;
|
||||
}
|
||||
|
||||
this.subItems.push({id: this.subItemsAutocomplete, amount: this.newSubItemAmount});
|
||||
this.updateCrudModalData();
|
||||
this.$refs.subItemsAutocomplete.clear();
|
||||
this.newSubItemAmount = 1;
|
||||
}
|
||||
}, mounted() {
|
||||
this.$watch(() => {
|
||||
return this.$refs.WarehouseArticlePacketCrud.crudModal
|
||||
}, () => {
|
||||
// check if this.$refs.WarehouseArticlePacketCrud.crudModalData.subItems is defined
|
||||
if (typeof this.$refs.WarehouseArticlePacketCrud.crudModalData.subItems === 'undefined') {
|
||||
this.$set(this.$refs.WarehouseArticlePacketCrud.crudModalData, 'subItems', JSON.stringify([]));
|
||||
}
|
||||
this.subItems = JSON.parse(this.$refs.WarehouseArticlePacketCrud.crudModalData.subItems);
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
@@ -25,9 +25,12 @@ Vue.component('tt-expandable-shopping-cart', {
|
||||
<h3>Einkaufswagen</h3>
|
||||
<ul class="list-group">
|
||||
<template v-for="item in cartItems">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<li class="list-group-item" style="display:grid;grid-template-columns: 1fr auto;gap: 10px;">
|
||||
{{ item.title }}
|
||||
<span class="badge badge-primary badge-pill">{{ item.amount }}</span>
|
||||
<div style="display:grid;grid-template-columns: 1fr 1fr;gap: 10px;">
|
||||
<span class="badge badge-primary badge-pill" style="height: 16px">{{ item.amount }}</span>
|
||||
<i style="cursor: pointer" class="fas fa-trash-alt text-danger" @click="cartItems.splice(cartItems.indexOf(item), 1)"></i>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
@@ -52,7 +55,7 @@ Vue.component('warehouse-e-shop', {
|
||||
|
||||
<tt-select v-model="createOrderDialogData.deliveryMode" label="Adresse" :options="[
|
||||
{text: 'Einzelne Adresse', value: 'singleAddress'},
|
||||
{text: 'Mehrere Adressen', value: 'multipleAddresses'},
|
||||
// {text: 'Mehrere Adressen', value: 'multipleAddresses'},
|
||||
]" sm row/>
|
||||
<tt-input v-model="createOrderDialogData.deliveryAddressName" label="Name" sm row/>
|
||||
<tt-input v-model="createOrderDialogData.deliveryAddressLine" label="Straße" sm row/>
|
||||
@@ -63,13 +66,18 @@ Vue.component('warehouse-e-shop', {
|
||||
|
||||
<tt-table-crud>
|
||||
|
||||
<template v-slot:price="{ row }">
|
||||
<span v-if="row.hasOwnProperty('calculatedSellPrice')"> {{ row.calculatedSellPrice.toFixed(2) }} €</span>
|
||||
<span v-else>{{ JSON.parse(row.cheapestSellPrice).find(price => price.title === 'Energie Steiermark').price.toFixed(2) }} €</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:amount="{ row }">
|
||||
<!-- this has no padding - add a full width full height tt-input with -->
|
||||
<tt-input type="number" style="width: 100%; height: 100%;margin:0 !important" v-model="itemAmounts[row.id]"/>
|
||||
<tt-input type="number" style="width: 100%; height: 100%;margin:0 !important" v-model="itemAmounts[row.hasOwnProperty('calculatedSellPrice') ? 'P-' + row.id : 'I-' + row.id]" sm/>
|
||||
</template>
|
||||
|
||||
<template v-slot:add="{ row }">
|
||||
<a style="cursor: pointer;" @click="addToCart(row)">
|
||||
<a style="cursor: pointer;" @click="addToCart(row, row.hasOwnProperty('calculatedSellPrice') ? 'P' : 'I')">
|
||||
<i class="fas fa-shopping-cart text-primary"></i>
|
||||
</a>
|
||||
</template>
|
||||
@@ -110,12 +118,16 @@ Vue.component('warehouse-e-shop', {
|
||||
'Ein Fehler ist aufgetreten');
|
||||
}
|
||||
},
|
||||
addToCart(row) {
|
||||
addToCart(row, type) {
|
||||
row = JSON.parse(JSON.stringify(row));
|
||||
row.id = `${type}-${row.id}`;
|
||||
if (!this.itemAmounts[row.id] || this.itemAmounts[row.id] === 0) {
|
||||
window.notify('error', 'Bitte geben Sie eine Menge ein.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(this.shoppingCart, row)
|
||||
|
||||
// Check if Article is already in the shopping cart
|
||||
if (this.shoppingCart.some(item => item.itemId === row.id)) {
|
||||
window.notify('warning', `${row.title} ist bereits im Warenkorb.`);
|
||||
|
||||
@@ -323,8 +323,8 @@ td {
|
||||
|
||||
.tt-expandable-shopping-cart.expanded .cart-count {
|
||||
position: unset !important;
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
grid-column-start: 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,17 +11,26 @@ Vue.component('tt-autocomplete', {
|
||||
class="form-control"
|
||||
:class="{'form-control-sm': sm}"
|
||||
v-model="displayValue"
|
||||
:placeholder="placeholder"
|
||||
@input="onInput"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
:style="{'padding-right': $slots.append ? '30px' : '0'}"
|
||||
/>
|
||||
<slot name="append"></slot>
|
||||
<button v-show="displayValue.length > 0" @click="displayValue = ''" type="button" class="btn btn-link position-absolute" style="right: -5px; top: 50%; transform: translateY(-50%);">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
|
||||
<ul v-show="showSuggestions && displayValue.length > 0 || isLoading"
|
||||
class="dropdown-menu show dropdown-shadow">
|
||||
|
||||
<div v-show="isLoading" class="loader"></div>
|
||||
<li class="dropdown-item" v-show="isLoading">
|
||||
<div class="spinner-border spinner-border-sm text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
Einträge werden geladen...
|
||||
</li>
|
||||
|
||||
<template v-show="showSuggestions && displayingItems.length > 0 && isLoading !== true">
|
||||
<li
|
||||
@@ -56,6 +65,7 @@ Vue.component('tt-autocomplete', {
|
||||
value: { type: [String, Number] },
|
||||
label: { type: String, required: false },
|
||||
apiUrl: String,
|
||||
placeholder: { type: String, default: '' },
|
||||
items: { type: Array, default: () => [] },
|
||||
sm: { type: Boolean, default: true },
|
||||
row: { type: Boolean, default: false },
|
||||
@@ -68,6 +78,7 @@ Vue.component('tt-autocomplete', {
|
||||
const selectedItem = this.items.find(item => item.value === this.value);
|
||||
this.displayValue = selectedItem ? selectedItem.text : '';
|
||||
} else {
|
||||
this.$emit('input', '');
|
||||
this.displayValue = '';
|
||||
}
|
||||
|
||||
@@ -85,7 +96,6 @@ Vue.component('tt-autocomplete', {
|
||||
watch: {
|
||||
value(newValue) {
|
||||
const selectedItem = this.displayingItems.find(item => item.value === newValue);
|
||||
console.log(selectedItem);
|
||||
this.displayValue = selectedItem ? selectedItem.text : '';
|
||||
},
|
||||
apiUrl() {
|
||||
@@ -94,8 +104,12 @@ Vue.component('tt-autocomplete', {
|
||||
},
|
||||
methods: {
|
||||
onInput(event) {
|
||||
console.log('input', event.target.value);
|
||||
this.displayValue = event.target.value;
|
||||
console.log('displayValue', this.displayValue);
|
||||
this.$emit('input', '');
|
||||
console.log('value', this.value);
|
||||
console.log('displayValue', this.displayValue);
|
||||
this.fetchSuggestions();
|
||||
},
|
||||
onFocus() {
|
||||
@@ -136,7 +150,7 @@ Vue.component('tt-autocomplete', {
|
||||
this.fetchSuggestionsDebounceTimer = setTimeout(() => {
|
||||
// Simulate the API call
|
||||
setTimeout(async () => {
|
||||
const response = await axios.get(`${this.apiUrl}&autocomplete=1&q=${this.displayValue}`);
|
||||
const response = await axios.get(`${this.apiUrl}&autocomplete=1&q=${encodeURIComponent(this.displayValue)}`);
|
||||
if (response.data?.status === 'error') {
|
||||
this.displayingItems = [];
|
||||
} else {
|
||||
@@ -154,5 +168,9 @@ Vue.component('tt-autocomplete', {
|
||||
this.displayValue = item.text;
|
||||
this.showSuggestions = false;
|
||||
},
|
||||
clear() {
|
||||
this.displayValue = '';
|
||||
this.$emit('input', '');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -18,6 +18,9 @@ Vue.component('tt-checkbox', {
|
||||
this.checkedValue = val;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('input', this.checkedValue);
|
||||
},
|
||||
template: `
|
||||
<div class="form-group" :class="{'row': row}">
|
||||
<slot name="prepend"></slot>
|
||||
|
||||
@@ -51,14 +51,17 @@ Vue.component('tt-table-crud', {
|
||||
|
||||
<template v-for="column in modalConfig.headers">
|
||||
<!-- @formatter:off -->
|
||||
<tt-input v-if="column.type === 'text'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
<tt-input v-if="column.type === 'number'" v-model="crudModalData[column.key]" :label="column.text" type="number" sm row/>
|
||||
<tt-textarea v-if="column.type === 'textarea'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
<tt-select v-if="column.type === 'select'" v-model="crudModalData[column.key]" :label="column.text" :options="column.items" sm row/>
|
||||
<tt-autocomplete v-if="column.type === 'autocomplete'" v-model="crudModalData[column.key]" :label="column.text" :items="column.items" sm row/>
|
||||
<tt-date-picker v-if="column.type === 'datepicker'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
<tt-icon-select v-if="column.type === 'icon-select'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
<tt-checkbox v-if="column.type === 'checkbox'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
<!-- <slot v-if="$scopedSlots[column.key.toLowerCase() + '-modal'] && column.type !== false && 1 < 0" :name="column.key.toLowerCase() + '-modal'" slot-scope="{crudModalData}"></slot>-->
|
||||
<slot :name="column.key.toLowerCase() + '-modal'" :crudModalData="crudModalData">
|
||||
<tt-input v-if="column.type === 'text'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
<tt-input v-else-if="column.type === 'number'" v-model="crudModalData[column.key]" :label="column.text" type="number" sm row/>
|
||||
<tt-textarea v-else-if="column.type === 'textarea'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
<tt-select v-else-if="column.type === 'select'" v-model="crudModalData[column.key]" :label="column.text" :options="column.items" sm row/>
|
||||
<tt-autocomplete v-else-if="column.type === 'autocomplete'" v-model="crudModalData[column.key]" :label="column.text" :items="column.items" sm row/>
|
||||
<tt-date-picker v-else-if="column.type === 'datepicker'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
<tt-icon-select v-else-if="column.type === 'icon-select'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
<tt-checkbox v-else-if="column.type === 'checkbox'" v-model="crudModalData[column.key]" :label="column.text" sm row/>
|
||||
</slot>
|
||||
<!-- @formatter:on -->
|
||||
</template>
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ Vue.component('tt-table-pagination', {
|
||||
<div class="tt-table-pagination-container">
|
||||
<div v-if="pagination && typeof pagination.total_rows === 'number'"
|
||||
class="tt-table-pagination-wrapper">
|
||||
|
||||
<span class="tt-table-text-center" v-text="pageInfoText"
|
||||
:style="{ 'grid-row': reverse ? 2 : 1, 'grid-column': 1 }"></span>
|
||||
|
||||
@@ -124,12 +125,6 @@ Vue.component('tt-table', {
|
||||
<div class="tt-table-top-pagination-container">
|
||||
<!-- if excelExport is true, show the export button fontawesome icon excel -->
|
||||
<div style="display:flex;align-items: center;">
|
||||
<i v-if="!Object.values(columns).every(column => column.filter === false)"
|
||||
title="Filter zurücksetzen"
|
||||
@click="resetTable" class="fas fa-times cursor-pointer text-danger"
|
||||
style="font-size: 24px;margin-right: 6px;cursor: pointer; color: var(--orange)"></i>
|
||||
<i v-if="excelExport" title="EXCEL Export" @click="exportToExcel" class="fa fa-file-excel"
|
||||
style="font-size: 24px;margin-right: 6px;cursor: pointer; color: var(--success)"></i>
|
||||
<h4 style="margin: 0">{{ config.tableHeader }}</h4>
|
||||
</div>
|
||||
|
||||
@@ -250,8 +245,23 @@ Vue.component('tt-table', {
|
||||
</table>
|
||||
<!-- Pagination Controls -->
|
||||
<nav aria-label="Page navigation">
|
||||
<tt-table-pagination :pagination="pagination" @fetch-rows="fetchRows"
|
||||
v-if="pagination"></tt-table-pagination>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<button v-if="!Object.values(columns).every(column => column.filter === false) || disableFiltering"
|
||||
@click="resetTable" class="btn btn-outline-secondary mr-2"
|
||||
>
|
||||
<i class="fas fa-filter"></i>
|
||||
Filter zurücksetzen
|
||||
</button>
|
||||
<button v-if="excelExport" title="EXCEL Export" @click="exportToExcel" class="btn btn-outline-success">
|
||||
<i class="fa fa-file-excel" style="color: var(--success)"></i>
|
||||
Excel Export
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<tt-table-pagination :pagination="pagination" @fetch-rows="fetchRows"
|
||||
v-if="pagination"></tt-table-pagination>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
`, props: {
|
||||
@@ -383,6 +393,7 @@ Vue.component('tt-table', {
|
||||
}
|
||||
}, saveSettingsToLocalStorage() {
|
||||
if (this.isInitialised === false) return;
|
||||
if (this.disableFiltering) return;
|
||||
|
||||
const filters = Object.entries(this.filters).reduce((acc, [key, value]) => {
|
||||
if (!value) {
|
||||
@@ -403,6 +414,8 @@ Vue.component('tt-table', {
|
||||
order: this.order.key ? this.order : undefined,
|
||||
}));
|
||||
}, parseSettingsFromLocalStorage() {
|
||||
if (this.disableFiltering) return false;
|
||||
|
||||
const settings = JSON.parse(localStorage.getItem(`tt-table-${this.config.key}`) || '{}');
|
||||
if (settings) {
|
||||
this.disableDebounce = true;
|
||||
|
||||
@@ -16,7 +16,7 @@ require_once(LIBDIR . "/mvcfronk/mfRouter/mfRouter.php");
|
||||
require_once(LIBDIR . "/mvcfronk/mfBase/mfBaseModel.php");
|
||||
require_once(LIBDIR . "/mvcfronk/mfBase/mfBaseController.php");
|
||||
|
||||
$me = new \User(1);
|
||||
$me = new \User(TT_RIMO_IMPORT_USER_ID);
|
||||
|
||||
define("INTERNAL_USER_ID", $me->id);
|
||||
define("INTERNAL_USER_USERNAME", $me->username);
|
||||
@@ -243,6 +243,7 @@ foreach ($clusters as $cluster_data) {
|
||||
}
|
||||
$hausnummer_found_count++;
|
||||
|
||||
$hausnummer_id = $hausnummer->id;
|
||||
/*
|
||||
* Set Building Status based on Operational-/Executionstate
|
||||
*/
|
||||
@@ -254,18 +255,23 @@ foreach ($clusters as $cluster_data) {
|
||||
if($b_executionstate_label != $hausnummer->rimo_ex_state) {
|
||||
$hausnummer->rimo_ex_state = $b_executionstate_label;
|
||||
$hausnummer->save();
|
||||
$hausnummer = new \ADBHausnummer($hausnummer_id);
|
||||
}
|
||||
if($b_operationalstate_label != $hausnummer->rimo_op_state) {
|
||||
$hausnummer->rimo_op_state = $b_operationalstate_label;
|
||||
$hausnummer->save();
|
||||
$hausnummer = new \ADBHausnummer($hausnummer_id);
|
||||
}
|
||||
|
||||
if($b_executionstate_id == "99" && $hausnummer->visibility != "private") {
|
||||
echo "== Setting visibility to private because execution state $b_executionstate_id ($b_executionstate_label) [".$hausnummer->id."]\n";
|
||||
$hausnummer->visibility = "private";
|
||||
$hausnummer->save();
|
||||
$hausnummer = new \ADBHausnummer($hausnummer_id);
|
||||
}
|
||||
|
||||
\mfValuecache::singleton()->set("adbhausnummer-save-nesting-level-".$hausnummer->id, 0);
|
||||
|
||||
$last_unit_num = 0;
|
||||
$existing_units = [];
|
||||
$existing_units_extref = [];
|
||||
@@ -300,6 +306,7 @@ foreach ($clusters as $cluster_data) {
|
||||
$rimo_home_count = count($building->homes->item);
|
||||
|
||||
foreach ($building->homes->item as $home) {
|
||||
$hausnummer = new \ADBHausnummer($hausnummer_id);
|
||||
//print_r($home);exit;
|
||||
$homes_count++;
|
||||
$home_rimo_id = $home->id;
|
||||
@@ -325,6 +332,8 @@ foreach ($clusters as $cluster_data) {
|
||||
if (!$unit->save()) {
|
||||
die("Error saving new unit\n" . print_r($home, true));
|
||||
}
|
||||
\mfValuecache::singleton()->set("adbhausnummer-save-nesting-level-".$hausnummer->id, 0);
|
||||
\mfValuecache::singleton()->set("adbwohneinheit-save-nesting-level-".$unit->id, 0);
|
||||
}
|
||||
|
||||
if ($unit->extref != $home_rimo_id) {
|
||||
@@ -332,19 +341,27 @@ foreach ($clusters as $cluster_data) {
|
||||
if (!$unit->save()) {
|
||||
die("Error saving new extref on unit\n" . print_r($home, true));
|
||||
}
|
||||
\mfValuecache::singleton()->set("adbhausnummer-save-nesting-level-".$hausnummer->id, 0);
|
||||
\mfValuecache::singleton()->set("adbwohneinheit-save-nesting-level-".$unit->id, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Status based on execution-/operational-state
|
||||
* TODO: Status based on execution-/operationalstate
|
||||
*/
|
||||
|
||||
if($home->executionState->userLabel != $unit->rimo_ex_state) {
|
||||
$unit->rimo_ex_state = $home->executionState->userLabel;
|
||||
$unit->save();
|
||||
$hausnummer = new \ADBHausnummer($hausnummer_id);
|
||||
\mfValuecache::singleton()->set("adbhausnummer-save-nesting-level-".$hausnummer->id, 0);
|
||||
\mfValuecache::singleton()->set("adbwohneinheit-save-nesting-level-".$unit->id, 0);
|
||||
}
|
||||
if($home->operationalState->userLabel != $unit->rimo_op_state) {
|
||||
$unit->rimo_op_state = $home->operationalState->userLabel;
|
||||
$unit->save();
|
||||
$hausnummer = new \ADBHausnummer($hausnummer_id);
|
||||
\mfValuecache::singleton()->set("adbhausnummer-save-nesting-level-".$hausnummer->id, 0);
|
||||
\mfValuecache::singleton()->set("adbwohneinheit-save-nesting-level-".$unit->id, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -523,6 +540,8 @@ foreach ($clusters as $cluster_data) {
|
||||
if ($wo) {
|
||||
//echo "Updating Workorder $rimo_workorder_id ($workorder_home_id)\n";
|
||||
if ($workorder_status != $wo->rimo_status) {
|
||||
\mfValuecache::singleton()->set("adbhausnummer-save-nesting-level-".$hausnummer->id, 0);
|
||||
\mfValuecache::singleton()->set("adbwohneinheit-save-nesting-level-".$unit->id, 0);
|
||||
$wo->rimo_status = $workorder_status;
|
||||
$wo->save();
|
||||
}
|
||||
@@ -544,6 +563,8 @@ foreach ($clusters as $cluster_data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
\mfValuecache::singleton()->set("adbhausnummer-save-nesting-level-".$hausnummer->id, 0);
|
||||
\mfValuecache::singleton()->set("adbwohneinheit-save-nesting-level-".$unit->id, 0);
|
||||
//echo "Creating Workorder $rimo_workorder_id ($workorder_home_id)\n";
|
||||
$wo = \RimoWorkorderModel::create([
|
||||
"adb_wohneinheit_id" => $wo_home->id,
|
||||
@@ -595,6 +616,7 @@ foreach ($clusters as $cluster_data) {
|
||||
if ($hausnummer->home_trench != $home_trench) {
|
||||
$hausnummer->home_trench = json_encode($home_trench);
|
||||
$hausnummer->save();
|
||||
$hausnummer = new \ADBHausnummer($hausnummer_id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -611,6 +633,7 @@ foreach ($clusters as $cluster_data) {
|
||||
$hausnummer->borderpoint_lat = $lat;
|
||||
$hausnummer->borderpoint_long = $long;
|
||||
$hausnummer->save();
|
||||
$hausnummer = new \ADBHausnummer($hausnummer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -631,6 +654,7 @@ foreach ($clusters as $cluster_data) {
|
||||
//var_dump($trenches);exit;
|
||||
$hausnummer->trenches = json_encode($trenches);
|
||||
$hausnummer->save();
|
||||
$hausnummer = new \ADBHausnummer($hausnummer_id);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user