Add price type selection modal and backend functionality for addresses

This commit is contained in:
2025-12-02 07:35:26 +01:00
parent 62b0381db7
commit d328f1791c
5 changed files with 192 additions and 2 deletions

View File

@@ -13,7 +13,7 @@
<div class="page-title-right"> <div class="page-title-right">
<ol class="breadcrumb m-0"> <ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="<?=self::getUrl("Dashboard")?>"><?=MFAPPNAME_SLUG?></a></li> <li class="breadcrumb-item"><a href="<?=self::getUrl("Dashboard")?>"><?=MFAPPNAME_SLUG?></a></li>
<?php if(is_array($filter['addresstype']) && count($filter['addresstype'])): ?> <?php if(array_key_exists('addresstype', $filter) && is_array($filter['addresstype']) && count($filter['addresstype'])): ?>
<li class="breadcrumb-item"><a href="<?=self::getUrl("Address")?>">Personen & Firmen</a></li> <li class="breadcrumb-item"><a href="<?=self::getUrl("Address")?>">Personen & Firmen</a></li>
<li class="breadcrumb-item active"> <li class="breadcrumb-item active">
<?php foreach($filter['addresstype'] as $type) { $types[] = __($type); } ?> <?php foreach($filter['addresstype'] as $type) { $types[] = __($type); } ?>
@@ -233,7 +233,7 @@
<td><?=$address->phone?></td> <td><?=$address->phone?></td>
<td><?=$address->email?></td> <td><?=$address->email?></td>
<td style="text-align: left; letter-spacing: 4px; font-size: 1.1em;"> <td style="text-align: left; letter-spacing: 4px; font-size: 1.1em;">
<a href="<?=self::getUrl("User", "Index", ["filter" => ["address_id" => $address->id]])?>" title="Benutzer anzeigen"><i class="fas fa-users"></i></a> <a href="#" onclick="openPriceTypeModal(<?=$address->id?>, '<?=$address->getCompanyOrName()?>')" title="Kunden-Preistyp auswählen"><i class="fas fa-tag"></i></a>
<a href="<?=self::getUrl("Address", "view", ["id" => $address->id, 's' => $pagination['start']])?>"><i class="far fa-eyes" title="Anzeigen"></i></a> <a href="<?=self::getUrl("Address", "view", ["id" => $address->id, 's' => $pagination['start']])?>"><i class="far fa-eyes" title="Anzeigen"></i></a>
<a href="<?=self::getUrl("Address", "sendServicePin", ["id" => $address->id])?>" onclick="if(!confirm('Soll der Service-PIN an den Kunden gesendet werden?')) return false;"><i class="fas fa-paper-plane" title="Service PIN als PDF per Email an Kunde"></i></a> <a href="<?=self::getUrl("Address", "sendServicePin", ["id" => $address->id])?>" onclick="if(!confirm('Soll der Service-PIN an den Kunden gesendet werden?')) return false;"><i class="fas fa-paper-plane" title="Service PIN als PDF per Email an Kunde"></i></a>
<a href="#" onclick="openCreateTicketModal(`<?=$address->getCompanyOrName()?>`, '<?=$address->customer_number?>', '<?=$address->street . ', ' . $address->zip . ' ' . $address->city?>', '<?=$address->phone?>', '<?=$address->email?>', '<?=$address->spin?>')" title="Störungs-Ticket erstellen" class="text-warning"><i class="fas fa-exclamation-triangle"></i></a> <a href="#" onclick="openCreateTicketModal(`<?=$address->getCompanyOrName()?>`, '<?=$address->customer_number?>', '<?=$address->street . ', ' . $address->zip . ' ' . $address->city?>', '<?=$address->phone?>', '<?=$address->email?>', '<?=$address->spin?>')" title="Störungs-Ticket erstellen" class="text-warning"><i class="fas fa-exclamation-triangle"></i></a>
@@ -254,6 +254,79 @@
</div> </div>
</div> </div>
<!-- PRICE TYPE MODAL START -->
<div class="modal fade" id="priceTypeModal" tabindex="-1" role="dialog" aria-labelledby="priceTypeModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="priceTypeModalLabel">Kunden-Preistyp auswählen</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form id="priceTypeForm">
<input type="hidden" name="address_id" id="priceType_address_id" />
<div class="form-group">
<label class="form-label" for="priceType_type_id">Preistyp für <strong id="priceType_customer_name"></strong></label>
<select class="form-control" name="priceType_type_id" id="priceType_type_id">
<option value="">Kein Preistyp (Standard)</option>
<?php
require_once(dirname(__FILE__)."/../../../application/WarehouseArticlePriceType/WarehouseArticlePriceTypeModel.php");
$priceTypes = WarehouseArticlePriceTypeModel::getAll();
foreach($priceTypes as $priceType):
?>
<option value="<?=$priceType->id?>"><?=$priceType->title?> (Faktor: <?=$priceType->defaultPriceFactor?>)</option>
<?php endforeach; ?>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" onclick="savePriceType()">Speichern</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Schließen</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
const priceTypeGetUrl = '<?=self::getUrl("AddressPriceType", "get")?>';
const priceTypeSaveUrl = '<?=self::getUrl("AddressPriceType", "save")?>';
function openPriceTypeModal(addressId, customerName) {
$("#priceType_address_id").val(addressId);
$("#priceType_customer_name").text(customerName);
$("#priceType_type_id").val('');
$.get(priceTypeGetUrl, { address_id: addressId }, function(response) {
if(response && response.priceType_id) {
$("#priceType_type_id").val(response.priceType_id);
}
}, 'json');
$("#priceTypeModal").modal("show");
}
function savePriceType() {
const addressId = $("#priceType_address_id").val();
const priceTypeId = $("#priceType_type_id").val();
$.post(priceTypeSaveUrl, {
address_id: addressId,
priceType_id: priceTypeId
}, function(response) {
if(response && response.success) {
$("#priceTypeModal").modal("hide");
window.notify('success', response.message || 'Preistyp erfolgreich gespeichert');
} else {
window.notify('error', response.message || 'Fehler beim Speichern des Preistyps');
}
}, 'json');
}
</script>
<!-- PRICE TYPE MODAL END -->
<!-- CREATE TICKET MODAL START --> <!-- CREATE TICKET MODAL START -->
<!--add a bootstrap modal here and below add a new <script> which creates a form for self::getUrl("Address", "createTicket") with post parameters <!--add a bootstrap modal here and below add a new <script> which creates a form for self::getUrl("Address", "createTicket") with post parameters

View File

@@ -0,0 +1,63 @@
<?php
class AddressPriceTypeController extends mfBaseController {
protected function init() {
$this->needlogin = true;
$user = new User();
$user->loadMe();
$this->me = $user;
}
public function getAction() {
$addressId = $_GET['address_id'] ?? null;
if (!$addressId) {
self::returnJson(['success' => false, 'message' => 'Address ID required']);
}
$priceType = AddressPriceTypeModel::getFirst(['address_id' => $addressId]);
self::returnJson([
'success' => true,
'priceType_id' => $priceType ? $priceType->priceType_id : null
]);
}
public function saveAction() {
$addressId = $_POST['address_id'] ?? null;
$priceTypeId = $_POST['priceType_id'] ?? null;
if (!$addressId) {
self::returnJson(['success' => false, 'message' => 'Address ID required']);
}
$existing = AddressPriceTypeModel::getFirst(['address_id' => $addressId]);
if (empty($priceTypeId)) {
if ($existing) {
AddressPriceTypeModel::delete($existing->id);
}
self::returnJson(['success' => true, 'message' => 'Preistyp entfernt']);
}
if ($existing) {
$updateData = (array) $existing;
$updateData['priceType_id'] = $priceTypeId;
$result = AddressPriceTypeModel::update($updateData);
} else {
$result = AddressPriceTypeModel::create([
'address_id' => $addressId,
'priceType_id' => $priceTypeId,
'create' => time(),
'createBy' => $this->me->id
]);
}
if ($result) {
self::returnJson(['success' => true, 'message' => 'Preistyp gespeichert']);
} else {
self::returnJson(['success' => false, 'message' => 'Fehler beim Speichern']);
}
}
}

View File

@@ -0,0 +1,9 @@
<?php
class AddressPriceTypeModel extends TTCrudBaseModel {
public int $id;
public int $address_id;
public int $priceType_id;
public int $create;
public int $createBy;
}

View File

@@ -48,6 +48,18 @@ class WarehouseArticlePriceTypeController extends TTCrud {
$WarehouseArticleController->updatePricesAction(); $WarehouseArticleController->updatePricesAction();
} }
protected function beforeDelete(): bool {
$priceTypeId = $this->request->id;
$usedByAddresses = AddressPriceTypeModel::getAll(['priceType_id' => $priceTypeId]);
if (!empty($usedByAddresses)) {
$this->infoMessages['delete'] = 'Dieser Preistyp kann nicht gelöscht werden, da er von ' . count($usedByAddresses) . ' Kunde(n) verwendet wird.';
return false;
}
return true;
}
protected function getHistoryAction() { protected function getHistoryAction() {
$history = WarehouseHistoryModel::getByRowId($this->request->id, $this->mod); $history = WarehouseHistoryModel::getByRowId($this->request->id, $this->mod);

View File

@@ -0,0 +1,33 @@
<?php
use Phinx\Migration\AbstractMigration;
final class AddAddressPriceType extends AbstractMigration
{
public function up(): void
{
if ($this->getEnvironment() == "thetool") {
$table = $this->table("AddressPriceType", ["signed" => true]);
$table->addColumn("address_id", "integer", ["null" => false]);
$table->addColumn("priceType_id", "integer", ["null" => false]);
$table->addColumn("create", "integer", ["null" => false]);
$table->addColumn("createBy", "integer", ["null" => false]);
$table->addIndex("address_id", ["unique" => true]);
$table->save();
}
if ($this->getEnvironment() == "addressdb") {
}
}
public function down(): void
{
if ($this->getEnvironment() == "thetool") {
$this->table("AddressPriceType")->drop()->save();
}
if ($this->getEnvironment() == "addressdb") {
}
}
}
?>