Merge branch 'master' into fronkdev

This commit is contained in:
Frank Schubert
2024-07-25 13:50:02 +02:00
43 changed files with 1063 additions and 118 deletions
+41 -3
View File
@@ -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() {
+31 -1
View File
@@ -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) {
+77 -1
View File
@@ -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()
];
}
}
}
+36
View File
@@ -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");
}
}
}
+13 -1
View File
@@ -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();
+21 -1
View File
@@ -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) {
+2 -3
View File
@@ -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;
+3
View File
@@ -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;
}