fix: Reset save button after error handling

feat: Clear review mode and revert to edit mode when navigating to next item
feat: Implement close button functionality
fix: Handle edge case with zero delivery notes
feat: Add new type field with free text option
fix: Enable cancellation reversal in WarehouseAdmin
improve: Enhance article search autocomplete functionality
This commit is contained in:
Luca Haid
2025-04-07 16:21:27 +02:00
parent fb0d7b7f1c
commit 037f1600f1
10 changed files with 74 additions and 24 deletions

View File

@@ -16,6 +16,7 @@ class WarehouseShippingNoteController extends TTCrud {
['value' => 'cancelled', 'text' => 'Storniert', 'icon' => 'fas fa-ban text-danger'],
['value' => 'on_hold', 'text' => 'In Wartestellung', 'icon' => 'fas fa-pause text-warning'],
]]],
['key' => 'type', 'text' => 'Typ', 'required' => true],
['key' => 'deliveryAddressName', 'text' => 'L.-Adr. Name', 'required' => true],
['key' => 'deliveryAddressLine', 'text' => 'L.-Adr.', 'required' => true],
['key' => 'deliveryAddressPLZ', 'text' => 'L.-Adr. PLZ', 'required' => true],
@@ -378,23 +379,13 @@ class WarehouseShippingNoteController extends TTCrud {
}
protected function changeStatusAction() {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
$json = json_decode(file_get_contents('php://input'), true);
$id = $json['id'];
$status = $json['status'];
if (strlen($id) < 1) {
http_response_code(500);
self::returnJson(['success' => false, 'message' => 'Lieferschein wurde nicht gefunden']);
}
if (empty($json['id'])) self::sendError('Lieferschein wurde nicht gefunden');
$shippingNote = (array) WarehouseShippingNoteModel::get($id);
if ($shippingNote['status'] === 'invoiced') {
http_response_code(500);
self::returnJson(['success' => false, 'message' => 'Status kann nicht geändert werden']);
}
$shippingNote = (array) WarehouseShippingNoteModel::get($json['id']);
if ($shippingNote['status'] === 'invoiced') self::sendError('Status kann nicht geändert werden');
$shippingNote['status'] = $status;
$shippingNote['status'] = $json['status'];
WarehouseShippingNoteModel::update($shippingNote);
$statusNiceText = [
'new' => 'Neu',
@@ -404,7 +395,7 @@ class WarehouseShippingNoteController extends TTCrud {
'cancelled' => 'Storniert',
'on_hold' => 'In Wartestellung',
];
self::returnJson(['success' => true, 'message' => 'Status wurde auf ' . $statusNiceText[$status] . ' geändert']);
self::returnJson(['success' => true, 'message' => 'Status wurde auf ' . $statusNiceText[$json['status']] . ' geändert']);
}
//TODO: either move this to TimerecordingCarController or make it better

View File

@@ -3,6 +3,7 @@
class WarehouseShippingNoteModel extends TTCrudBaseModel {
public int $id;
public ?int $billingAddressId;
public string $type;
public string $deliveryAddressName;
public string $deliveryAddressLine;
public string $deliveryAddressPLZ;

View File

@@ -0,0 +1,25 @@
<?php declare(strict_types = 1);
use Phinx\Migration\AbstractMigration;
final class WarehouseModify17 extends AbstractMigration {
public function up(): void {
if ($this->getEnvironment() == "thetool") {
$WarehouseShippingNoteTable = $this->table("WarehouseShippingNote");
$WarehouseShippingNoteTable
->addColumn("type", "string", ["limit" => 255, "default" => ""])
->save();
}
}
public function down(): void {
if ($this->getEnvironment() == "thetool") {
$WarehouseShippingNoteTable = $this->table("WarehouseShippingNote");
if ($WarehouseShippingNoteTable->hasColumn("type")) {
$WarehouseShippingNoteTable
->removeColumn("type")
->save();
}
}
}
}

View File

@@ -32,7 +32,7 @@ class Helper {
$sql .= " AND `$columnName` = '" . $filterValue . "'";
} else if (strpos($columnName, "|") !== false) {
foreach (explode(" ", $filterValue) as $item)
$sql .= " AND CONCAT(" . join(",", explode("|", $columnName)) . ") LIKE '%" . str_replace("%", "", $item) . "%'";
$sql .= " AND CONCAT(" . join(",", explode("|", $columnName)) . ") LIKE '%" . $item . "%'";
} else if ($filterValue[0] === "%") {
$sql .= " AND `$columnName` LIKE '" . $filterValue . "'";
} else if ($filterValue[strlen($filterValue) - 1] === "%") {

View File

@@ -278,8 +278,10 @@ class TTCrud extends mfBaseController {
$data = [];
if (count($data) < 11) {
$filter = [$filterKey => '%' . $this->request->q . '%'];
$lazyData = $this->model::getAll($filter, 10);
// $this->request->q replace ? with
$data = $this->model::getAll([$textKey => $this->request->q . '%'], 10);
$lazyData = $this->model::getAll([$filterKey => $this->request->q], 10);
$data = array_merge($data, $lazyData);
$data = array_unique($data, SORT_REGULAR);
$data = array_slice($data, 0, 10);

View File

@@ -371,7 +371,7 @@ class mfBaseController
}
public static function sendError(string $message): void {
http_response_code(422); // More appropriate status for validation errors
http_response_code(500);
self::returnJson(['success' => false, 'message' => $message]);
exit;
}

View File

@@ -189,3 +189,8 @@ input:disabled + .ios-switch-slider {
position: unset !important;
background: unset !important;
}
.see-through-test-modal .btn-secondary {
display:none;
}

View File

@@ -29,6 +29,12 @@ window.TT_CONFIG["CRUD_CONFIG"]["additionalActions"] = [
"class": "fas fa-ban text-danger",
"condition": (row) => (window.TT_CONFIG['WAREHOUSE_ADMIN'] === '1' && ['new', 'in_progress', 'accepted'].includes(row.status)) || (row.status === 'new' && row.signature === null),
},
{
"key": "status_to_new",
"title": "Lieferschein wiedereröffnen",
"class": "fas fa-redo-alt text-success",
"condition": (row) => (window.TT_CONFIG['WAREHOUSE_ADMIN'] === '1' && row.status === 'cancelled'),
},
{
"key": "add_log",
"title": "Log Eintrag hinzufügen",
@@ -294,8 +300,8 @@ Vue.component('warehouse-shipping-note-see-through', {
<warehouse-shipping-note-modal v-if="currentRow" :id="currentRow.id" @close="fetchData" ref="modal"/>
</div>
<div v-if="activeTab === 'Logs'" style="flex: 1; overflow: auto;" class="see-through-test-modal">
<warehouse-shipping-note-logs :shipping-note-id="currentRow.id"/>
<add-log-modal-sn v-if="currentRow" :shipping-note-id="currentRow.id" @close="fetchData"/>
<warehouse-shipping-note-logs :shipping-note-id="currentRow.id" :key="'logs' + logModalKey"/>
<add-log-modal-sn v-if="currentRow" :shipping-note-id="currentRow.id" @close="logModalKey++" :key="'modal'+logModalKey"/>
</div>
</div>
</template>
@@ -305,6 +311,7 @@ Vue.component('warehouse-shipping-note-see-through', {
`,
data() {
return {
logModalKey: 0,
currentPage: 1,
perPage: 1,
rows: [],
@@ -355,6 +362,10 @@ Vue.component('warehouse-shipping-note-see-through', {
})
this.rows = response.data.rows;
if (this.rows.length === 0) {
this.$emit('close');
this.window.notify('info', 'Keine Lieferscheine mit diesem Status gefunden');
}
this.loading = false;
}
@@ -408,6 +419,7 @@ Vue.component('warehouse-shipping-note', {
@status_to_invoiced="changeStatus($event.id, 'invoiced')"
@status_to_on_hold="changeStatus($event.id, 'on_hold')"
@status_to_cancelled="changeStatus($event.id, 'cancelled')"
@status_to_new="changeStatus($event.id, 'new')"
@add_log="addLogModalId = $event.id"
@edit="shippingNoteModalId = $event.id"
ref="table">

View File

@@ -21,6 +21,13 @@ Vue.component('warehouse-shipping-note-modal', {
textElements: [],
hoursEntries: [],
},
availableTypes: [
{text: 'Xinon Intern (XI)', value: 'XI'},
{text: 'Xinon Hersteller (XH)', value: 'XH'},
{text: 'Energie Steiermark (ESTMK)', value: 'ESTMK'},
{text: 'Steirische Breitband- und Digitalinfrastrukturgesellschaft (SBIDI)', value: 'SBIDI'},
{text: 'Verrechnen (V)', value: 'V'},
],
hoursLoading: false,
geoAddr: '',
selectedBillingAddress: '',
@@ -108,6 +115,7 @@ Vue.component('warehouse-shipping-note-modal', {
<template v-if="window.TT_CONFIG['WAREHOUSE_ADMIN'] == true">
<hr>
<tt-autocomplete v-model="shippingNote.billingAddressId" :api-url="billAddrAutoCompleteUrl" label="Rechnungsadresse" sm row/>
<tt-autocomplete v-model="shippingNote.type" :items="availableTypes" label="Typ" sm row return-text/>
</template>
<tt-textarea v-model="shippingNote.note" label="Art der Arbeit" sm row/>
@@ -171,8 +179,14 @@ Vue.component('warehouse-shipping-note-modal', {
methods: {
async submit() {
this.loading = true;
if (!this.shippingNote.positions.length && !this.shippingNote.hoursEntries.length)
if (!this.shippingNote.positions.length && !this.shippingNote.hoursEntries.length) {
this.loading = false;
return window.notify('error', 'Mindestens eine Position oder eine Stundenbuchung sind erforderlich');
}
if (this.availableTypes.find(t => t.name === this.shippingNote.type)) {
this.shippingNote.type = this.availableTypes.find(t => t.name === this.shippingNote.type).value;
}
const response = await axios.post(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseShippingNote/${this.id === 'create' ? 'create' : 'update'}`, this.shippingNote);

View File

@@ -126,7 +126,7 @@ Vue.component('tt-autocomplete', {
this.displayValue = response.data[0].text;
} else if (this.value) {
const selectedItem = this.items.find(item => item.value === this.value);
this.displayValue = selectedItem ? selectedItem.text : '';
this.displayValue = selectedItem ? selectedItem.text : this.displayValue;
} else {
if (this.returnText === false && !(typeof this.value === 'undefined' || this.value === '')) this.$emit('input', '');
this.displayValue = this.displayValue.replace(this.oldDisplayValue, '');