diff --git a/Layout/default/Calendar/View.php b/Layout/default/Calendar/View.php index a52f39e77..99c5474a9 100644 --- a/Layout/default/Calendar/View.php +++ b/Layout/default/Calendar/View.php @@ -102,18 +102,20 @@ endforeach;
-

Kalender +

Kalender

groups) : ?> + if ($Calendar[0]->groups) : + $Rights = $rights; + + ?>
groups, true); foreach ($groups as $group) : - ?>
@@ -131,7 +133,10 @@ endforeach;
- + +
user->name) ?: $specialCalendars[$calendar['calendar_id']] ?>
- + $calendar): + ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + user->name) ?: $specialCalendars[$calendar['calendar_id']] + ?> + + +
@@ -248,24 +295,26 @@ endforeach;
- - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +
-
- -
-
+
+ Typ
+
+ +
@@ -361,11 +411,10 @@ endforeach;
-
- -
-
-
+
+
+
-
@@ -439,7 +487,6 @@ endforeach;
-
@@ -541,7 +588,9 @@ endforeach;
- +
+ +
diff --git a/Layout/default/Preorder/Index.php b/Layout/default/Preorder/Index.php index f30ff87b0..0f9416bdc 100644 --- a/Layout/default/Preorder/Index.php +++ b/Layout/default/Preorder/Index.php @@ -146,13 +146,20 @@ + +
- + + + +
@@ -164,6 +171,17 @@ + +
+ + +
@@ -173,14 +191,15 @@
- -
- - -
+ + + + + + + + +
@@ -192,6 +211,11 @@ " />
+ +
+ + " /> +
@@ -219,15 +243,33 @@
+ +
+ + +
-
- +
+
+ +
+ + +
@@ -251,11 +293,6 @@
-
- - " /> -
-
-
- - -
-
@@ -442,6 +470,8 @@ $(document).ready(function() { $("#filter_type").select2({closeOnSelect: false}); $("#filter_status").select2({closeOnSelect: false}); + $("#filter_partner_id").select2({closeOnSelect: false}); + $("#connection_type_id").select2({closeOnSelect: false}); var attributes = ["bep_specified", "inhouse_cabling_supplied"]; diff --git a/Layout/default/WarehouseShippingNote/PDF_MAIN.php b/Layout/default/WarehouseShippingNote/PDF_MAIN.php index 4615b4861..3c2806f8f 100644 --- a/Layout/default/WarehouseShippingNote/PDF_MAIN.php +++ b/Layout/default/WarehouseShippingNote/PDF_MAIN.php @@ -98,10 +98,10 @@ TODO: enable option for showing prices - - - - + + + + @@ -112,7 +112,7 @@ TODO: enable option for showing prices - + @@ -123,7 +123,7 @@ TODO: enable option for showing prices - + diff --git a/application/Address/AddressController.php b/application/Address/AddressController.php index 319b63571..7a10638df 100644 --- a/application/Address/AddressController.php +++ b/application/Address/AddressController.php @@ -79,7 +79,15 @@ class AddressController extends mfBaseController { if(array_key_exists("kunde", $filter) && $filter["kunde"]) { $kunde = $this->db()->escape($filter['kunde']); - $new_filter['add-where'] .= " AND (company like '%$kunde%' OR firstname like '%$kunde%' OR lastname like '%$kunde%' OR concat(firstname, ' ', lastname) like '%$kunde%' OR concat(lastname, ' ', firstname) like '%$kunde%')"; + // if kunde contains ß or ss we want to search both cases but not with % because it can lead to wrong results + if (strpos($kunde, "ß") !== false || strpos($kunde, "ss") !== false) { + $kundeWithSS = str_replace("ß", "ss", $kunde); + $kundeWithoutSS = str_replace("ss", "ß", $kunde); + $new_filter['add-where'] .= " AND (company like '%$kundeWithoutSS%' OR firstname like '%$kundeWithoutSS%' OR lastname like '%$kundeWithoutSS%' OR concat(firstname, ' ', lastname) like '%$kundeWithoutSS%' OR concat(lastname, ' ', firstname) like '%$kundeWithoutSS%')"; + $new_filter['add-where'] .= " OR (company like '%$kundeWithSS%' OR firstname like '%$kundeWithSS%' OR lastname like '%$kundeWithSS%' OR concat(firstname, ' ', lastname) like '%$kundeWithSS%' OR concat(lastname, ' ', firstname) like '%$kundeWithSS%')"; + } else { + $new_filter['add-where'] .= " AND (company like '%$kunde%' OR firstname like '%$kunde%' OR lastname like '%$kunde%' OR concat(firstname, ' ', lastname) like '%$kunde%' OR concat(lastname, ' ', firstname) like '%$kunde%')"; + } } if(!array_key_exists("parents_only", $filter)) { @@ -110,7 +118,7 @@ class AddressController extends mfBaseController { $new_filter[$name] = $value; } } - + return $new_filter; } diff --git a/application/Api/v1/CalendarApicontroller.php b/application/Api/v1/CalendarApicontroller.php index 4bf247b28..e9570b0e6 100644 --- a/application/Api/v1/CalendarApicontroller.php +++ b/application/Api/v1/CalendarApicontroller.php @@ -152,6 +152,7 @@ class CalendarApicontroller extends mfBaseApicontroller $now = floor(microtime(true) * 1000); $timenow = time(); while (true) { + $colors = $redis->get('thetool_calendar_usercolors_' . $decstring); if ($colors) { $calendarColors = json_decode($colors, true); @@ -172,11 +173,15 @@ class CalendarApicontroller extends mfBaseApicontroller $message[0]['start_time'] = date('Y-m-d H:i', $json['start_time']); $message[0]['end_time'] = date('Y-m-d H:i', $json['end_time']); } + $message[0]['name']= $Calendarevent['data'][0]['category']['category']; + $message[0]['description'] = $Calendarevent['data'][0]['description']['description']; + $message[0]['location'] = $Calendarevent['data'][0]['location']['location']; $message[0]['event_type'] = $Calendarevent['data'][0]['event_type']['event_type']; $message[0]['attachment'] = $Calendarevent['data'][0]['attachment']['attachment']; $message[0]['attachments'] = $Calendarevent['data'][0]['attachments']['attachments']; $message[0]['calendar_name'] = $Calendarevent['data'][0]['calendar_name']['calendar_name']; $message[0]['isorganizer'] = $Calendarevent['data'][0]['isorganizer']['isorganizer']; + $message[0]['privateflag'] = $Calendarevent['data'][0]['privateflag']['privateflag']; $message[0]['rrule'] = $Calendarevent['data'][0]['rrule']['rrule']; $message[0]['duration'] = $Calendarevent['data'][0]['duration']['duration']; $message[0]['mtime'] = $Calendarevent['data'][0]['mtime']['mtime']; @@ -189,6 +194,7 @@ class CalendarApicontroller extends mfBaseApicontroller $message[0]['bgColor'] = $calendarColors[$json['calendar_id']]['bgcolor']; $message[0]['txtColor'] = $calendarColors[$json['calendar_id']]['txtcolor']; $message[0]['rights'] = $rights[$json['calendar_id']]; + $message[0]['me'] = $decstring; $result = json_encode($message); if (in_array($message[0]['calendar_id'], $allowedCalendar)) { diff --git a/application/Calendar/CalendarModel.php b/application/Calendar/CalendarModel.php index 62a13db1c..6ef796282 100644 --- a/application/Calendar/CalendarModel.php +++ b/application/Calendar/CalendarModel.php @@ -38,11 +38,30 @@ class CalendarModel '#c8a7d5', '#aad8d0', '#dcadc3', '#d9e8e5', '#e4d8d5', '#b4dcc5', '#b9d1e2', '#a3c1c2', '#cdd2b9', '#e3c8ce', '#aae2c5', '#c7d0cc', '#d0c0da', '#dbdfc8', '#b4e3d7', - '#c3e4e3', '#c5c4e3', '#d0b7e5', '#b6e98c', '#e3d1de' + '#c3e4e3', '#c5c4e3', '#d0b7e5', '#b6e98c', '#e3d1de', + '#dbbeb3', '#e9aebc', '#b5cae7', '#dec2d4', '#aebbd5', + '#e2baaf', '#b6ebd5', '#a9c4bb', '#d7d2c5', '#d7e3d4' ]; public static $specialCalendarColors = array(997 => '#bd0000', 998 => '#8000A3', 999 => '#08769b'); + public static function convertToSummertime($timestamp) + { + // Create a DateTime object from the Unix timestamp + $date = new DateTime(); + $date->setTimestamp($timestamp); + + // Set the timezone to Europe/Berlin + $date->setTimezone(new DateTimeZone('Europe/Berlin')); + if ($date->format('I') == 1) { + $cest = 7200; + } else { + $cest = 3600; + } + $unixtimestamp = $date->getTimestamp() + $cest; + // Format the date and time + return date('Y-m-d H:i:s', $unixtimestamp); + } public static function replace_unicode_sequences($string) { @@ -96,16 +115,18 @@ class CalendarModel $rows = array(); while ($data = $dbcal->fetch_array($res)) { - if ($data['location']) { - $searchName = $data['name'] . " @" . $data['location']; - } else { - $searchName = $data['name']; + if ($data['private'] != 1 || $data['calendar_id'] == $r->cal_id) { + if ($data['location']) { + $searchName = $data['name'] . " @" . $data['location']; + } else { + $searchName = $data['name']; + } + $id = $data['id'] . ";" . date("Y-m-d", $data['start_time']); + $rows[] = array( + 'id' => $id, + 'text' => $searchName . " (" . date("Y-m-d", $data['start_time']) . ")" + ); } - $id = $data['id'] . ";" . date("Y-m-d", $data['start_time']); - $rows[] = array( - 'id' => $id, - 'text' => $searchName . " (" . date("Y-m-d", $data['start_time']) . ")" - ); } $json['incomplete_results'] = false; $json['total_count'] = count($rows); @@ -118,7 +139,7 @@ class CalendarModel public static function getCalendarEvents($me, $id = 0, $r = 0) { - $rrulefreq = array('daily' => 'DAILY', 'weekly' => 'WEEKLY', 'relativeMonthly' => 'MONTHLY', 'yearly' => 'YEARLY'); + $rrulefreq = array('daily' => 'DAILY', 'weekly' => 'WEEKLY', 'relativeMonthly' => 'MONTHLY', 'yearly' => 'YEARLY', 'absoluteMonthly' => 'absoluteMonthly'); $calendar = self::search(array("user_id" => $me)); $standardCalendarColors = CalendarModel::$standardCalendarColors; $calendarColors = json_decode($calendar[0]->colors, true); @@ -195,7 +216,11 @@ class CalendarModel if ($data['recurrence']) { $recurrence = json_decode($data['recurrence'], true); - $rrule_events= json_decode($data['rrule_events'], true); + $rrule_events = json_decode($data['rrule_events'], true); + foreach ($rrule_events as $key => $value) { + $rrule_events[$key]['start'] = self::convertToSummertime(strtotime($value['start'])); + $rrule_events[$key]['end'] = self::convertToSummertime(strtotime($value['end'])); + } if ($rrulefreq[$recurrence['pattern']['type']]) { unset ($byweekday); $freq = $rrulefreq[$recurrence['pattern']['type']]; @@ -237,9 +262,20 @@ class CalendarModel $txtcolor = "#000"; $colorCounter++; } + $location = $data['location']; + $eventtype = $data['event_type']; + $description = $data['description']; if ($calenderRights[$data['calendar_id']]) { $rights = $calenderRights[$data['calendar_id']]; $CalendarUsers[$data['calendar_id']] = $data['calendar_name']; + if ($data['private'] == 1 && $calendar[0]->go_calendar_id != $data['calendar_id']) { + $name = "Privat"; + $attachment = 0; + $attachmentLinks = ""; + $location = ""; + $eventtype = "1"; + $description = ""; + } $rows[] = array( 'id' => array('id' => $data['id']), 'cstart' => array('cstart' => $starttime), @@ -250,14 +286,15 @@ class CalendarModel 'bgColor' => array('bgColor' => $bgcolor), 'txtColor' => array('txtColor' => $txtcolor), 'rights' => array('rights' => $rights, 'order' => $rights), - 'location' => array('location' => $data['location']), + 'location' => array('location' => $location), 'busy' => array('busy' => $data['busy']), + 'privateflag' => array('privateflag' => $data['private']), 'allDay' => array('allDay' => $data['all_day_event']), 'rrule' => array('rrule' => $rrule), 'rrule_events' => array('rrule_events' => $rrule_events), 'duration' => array('duration' => $duration), - 'event_type' => array('event_type' => $data['event_type']), - 'description' => array('description' => ($data['description'])), + 'event_type' => array('event_type' => $eventtype), + 'description' => array('description' => ($description)), 'attachment' => array('attachment' => $attachment), 'attachments' => array('attachments' => $attachmentLinks), 'calendar_name' => array('calendar_name' => $data['calendar_name']), @@ -466,6 +503,7 @@ WHERE `TimerecordingCategory`.`hourday`!='1' AND `TimerecordingCategory`.`hourda 'customer_info' => array('customer_info' => $data['customer_info']), 'customer_info_send' => array('customer_info_send' => $data['customer_info_send']), 'customer_info_reminder' => array('customer_info_reminder' => $data['customer_info_reminder']), + 'privateflag' => array('privateflag' => $data['private'], 'order' => $data['private']), 'isorganizer' => array('isorganizer' => $data['is_organizer']), 'attendees' => array('attendees' => json_encode($AttendeeArray)), 'organizer' => array('organizer' => $data['organizer']), @@ -539,6 +577,7 @@ WHERE `TimerecordingCategory`.`hourday`!='1' AND `TimerecordingCategory`.`hourda $busy = ($r->busy); $users = ($r->users); $attendees = ($r->attendees); + $privateflag = ($r->privateflag); foreach ($users as $key => $value) { $user_id = $value; } @@ -573,6 +612,9 @@ WHERE `TimerecordingCategory`.`hourday`!='1' AND `TimerecordingCategory`.`hourda if (isset($allday)) $updateArray['all_day_event'] = $allday; + if (isset($privateflag)) + $updateArray['private'] = $privateflag; + if (isset($reminder)) { if ($reminder == 'NULL') $updateArray['reminder'] = NULL; @@ -733,6 +775,7 @@ WHERE `TimerecordingCategory`.`hourday`!='1' AND `TimerecordingCategory`.`hourda $users = ($r->users); $customer_info_reminder_check = 0; $attendees = ($r->attendees); + $privateflag = ($r->privateflag); date_default_timezone_set('Europe/Berlin'); header('Content-Type: application/json'); foreach ($users as $key => $value) { @@ -771,7 +814,7 @@ WHERE `TimerecordingCategory`.`hourday`!='1' AND `TimerecordingCategory`.`hourda $customer_info_send = NULL; } - $dataarray = array("start_time" => $start, 'end_time' => $end, 'name' => $title, 'description' => $description, 'location' => $location, 'calendar_id' => $user_id, 'uuid' => "a5eb79b3-fca7-5378-a09e-" . rand(100000000000, 999999999999), 'user_id' => 1, 'timezone' => 'Europe/Amsterdam', 'all_day_event' => 0, 'repeat_end_time' => 0, 'reminder' => $reminder, 'ctime' => time(), 'cname' => $me->name, 'mtime' => time(), 'mname' => $me->name, 'user_id' => 1, 'busy' => $busy, 'status' => 'CONFIRMED', 'resource_event_id' => 0, 'private' => 0, 'rrule' => '', 'background' => 'EBF1E2', 'files_folder_id' => 0, 'read_only' => 0, 'exception_for_event_id' => 0, 'recurrence_id' => 0, 'is_organizer' => 1, 'event_type' => $type, 'customer' => $customer, 'customer_info' => $customer_info, 'customer_info_send' => $customer_info_send, 'customer_info_reminder' => $customer_info_reminder_check); + $dataarray = array("start_time" => $start, 'end_time' => $end, 'name' => $title, 'description' => $description, 'location' => $location, 'calendar_id' => $user_id, 'uuid' => "a5eb79b3-fca7-5378-a09e-" . rand(100000000000, 999999999999), 'user_id' => 1, 'timezone' => 'Europe/Amsterdam', 'all_day_event' => 0, 'repeat_end_time' => 0, 'reminder' => $reminder, 'ctime' => time(), 'cname' => $me->name, 'mtime' => time(), 'mname' => $me->name, 'user_id' => 1, 'busy' => $busy, 'status' => 'CONFIRMED', 'resource_event_id' => 0, 'private' => $privateflag, 'rrule' => '', 'background' => 'EBF1E2', 'files_folder_id' => 0, 'read_only' => 0, 'exception_for_event_id' => 0, 'recurrence_id' => 0, 'is_organizer' => 1, 'event_type' => $type, 'customer' => $customer, 'customer_info' => $customer_info, 'customer_info_send' => $customer_info_send, 'customer_info_reminder' => $customer_info_reminder_check); $db->insert("cal_events", $dataarray); $event_id = $dataarray['uuid']; diff --git a/application/Preorder/PreorderController.php b/application/Preorder/PreorderController.php index 8811d567e..4339e2078 100644 --- a/application/Preorder/PreorderController.php +++ b/application/Preorder/PreorderController.php @@ -231,6 +231,12 @@ class PreorderController extends mfBaseController { $new_filter['addon_services'] = true; } + if(array_key_exists("borderpoint", $filter) && $filter['borderpoint'] === 'with') { + $new_filter['add-where'] .= " AND (adb_hausnummer.borderpoint_lat IS NOT NULL AND adb_hausnummer.borderpoint_long IS NOT NULL)"; + } elseif(array_key_exists("borderpoint", $filter) && $filter['borderpoint'] === 'without') { + $new_filter['add-where'] .= " AND (adb_hausnummer.borderpoint_lat IS NULL OR adb_hausnummer.borderpoint_long IS NULL)"; + } + if(array_key_exists("address_source", $filter)) { if($filter['address_source'] == "manual") { $new_filter['address_created'] = true; @@ -293,10 +299,6 @@ class PreorderController extends mfBaseController { } } - /*if(array_key_exists("attributes", $filter) && count($filter['attributes'])) { - - }*/ - if(is_array($filter) && count($filter)) { foreach($filter as $name => $value) { $new_filter[$name] = $value; diff --git a/application/WarehouseArticle/WarehouseArticleController.php b/application/WarehouseArticle/WarehouseArticleController.php index af64a5dbc..77c80a59e 100644 --- a/application/WarehouseArticle/WarehouseArticleController.php +++ b/application/WarehouseArticle/WarehouseArticleController.php @@ -7,6 +7,7 @@ class WarehouseArticleController extends TTCrud { // @formatter:off protected array $columns = [ ['key' => 'title', 'text' => 'Titel', 'required' => true, 'table' => ['priority' => 9]], + ['key' => 'articleNumber', 'text' => 'Nr.', 'required' => true], ['key' => 'description', 'text' => 'Beschreibung', 'required' => true], ['key' => 'category', 'text' => 'Kategorie', 'required' => true], ['key' => 'unit', 'text' => 'Einheit', 'required' => true,'table' => false], // Boolean value @@ -253,6 +254,48 @@ class WarehouseArticleController extends TTCrud { } } + protected function provArticleNumberImportAction() { + // if method is post and file is set read the csv and var dump json and die + // if method is get return basic html with a form to upload a file and a submit button + + if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['file'])) { + $file = fopen($_FILES['file']['tmp_name'], 'r'); + $data = []; + // parse csv as object with first row as keys as header and use key => value + $firstRow = true; + while (($row = fgetcsv($file)) !== false) { + if ($firstRow) { + $header = $row; + $firstRow = false; + continue; + } + $data[] = array_combine($header, $row); + } + + // loop through all the data and if PRODUKT 1.ZEILE is set and articleNumber is not set push the last 4 numbers of "EAN 13 Code" to articleNumber of the found article + + foreach ($data as $item) { + if (isset($item['PRODUKT 1.ZEILE'])) { + $articles = WarehouseArticleModel::getAll(['title' => $item['PRODUKT 1.ZEILE']]); + if (!empty($articles)) { + $article = (array) WarehouseArticleModel::get($articles[0]->id); + + $article['articleNumber'] = substr($item['EAN 13 Code'], -4); + WarehouseArticleModel::update($article); + } + } + } + + fclose($file); + die(json_encode(['success' => true])); + } + + $html = ''; + echo $html; + die(); + + } + protected function prepareOrderAction() { // inside post json it will look like // [ diff --git a/application/WarehouseArticle/WarehouseArticleModel.php b/application/WarehouseArticle/WarehouseArticleModel.php index 2a6a14cf3..cb2c6da23 100644 --- a/application/WarehouseArticle/WarehouseArticleModel.php +++ b/application/WarehouseArticle/WarehouseArticleModel.php @@ -3,6 +3,7 @@ class WarehouseArticleModel extends TTCrudBaseModel { public int $id; public string $title; + public string $articleNumber; public string $description; public string $category; public ?float $cheapestPurchasePrice; diff --git a/application/WarehouseEShop/WarehouseEShopController.php b/application/WarehouseEShop/WarehouseEShopController.php index f49ba7d0e..af598a276 100644 --- a/application/WarehouseEShop/WarehouseEShopController.php +++ b/application/WarehouseEShop/WarehouseEShopController.php @@ -28,6 +28,13 @@ class WarehouseEShopController extends TTCrud { return $this->user->can(["WarehouseEShop"]); } + protected function prepareCrudConfig() { + if (!$this->user->can('WarehouseAdmin')) { + $this->columns[2]['table'] = false; + } + } + + public function getAction() { $filter = $this->postData['filters'] ?? []; $order = $this->postData['order'] ?? ['key' => null, 'order' => 'ASC']; diff --git a/application/WarehouseEShopOrder/WarehouseEShopOrderController.php b/application/WarehouseEShopOrder/WarehouseEShopOrderController.php index f8c26b18a..e5701ae97 100644 --- a/application/WarehouseEShopOrder/WarehouseEShopOrderController.php +++ b/application/WarehouseEShopOrder/WarehouseEShopOrderController.php @@ -4,62 +4,70 @@ class WarehouseEShopOrderController extends TTCrud { protected string $headerTitle = 'Energie Steiermark Bestellungen'; protected bool $createText = false; - protected array $columns = [['key' => 'id', 'text' => 'ID', 'modal' => false], - ['key' => 'extRef', 'text' => 'Externe Referenz', 'required' => true], - ['key' => 'status', - 'text' => 'Status', - 'required' => true, - 'modal' => ['type' => 'select', - 'items' => [['value' => 'new', 'text' => 'Neu'], - ['value' => 'accepted', 'text' => 'An Lieferant übergeben'], - ['value' => 'acceptedInternally', 'text' => 'Interne verarbeitung'], - ['value' => 'sent', 'text' => 'Gesendet'], - ['value' => 'done', 'text' => 'Erledigt'],]], - 'table' => ['filter' => 'select']], - ['key' => 'deliveryMode', - 'text' => 'Liefermodus', - 'required' => true, - 'modal' => ['type' => 'select', - 'items' => [['value' => 'singleAddress', 'text' => 'Einzelne Adresse'], - // ['value' => 'multipleAddresses', 'text' => 'Mehrere Adressen'], - ]]], - ['key' => 'deliveryAddressName', 'text' => 'Name', 'required' => true], - ['key' => 'deliveryAddressLine', 'text' => 'Adresse', 'required' => true, 'required_length' => 4], - ['key' => 'deliveryAddressPLZ', 'text' => 'PLZ', 'required' => true, 'regex' => '/^\d{4}$/'], - ['key' => 'deliveryAddressCity', 'text' => 'Stadt', 'required' => true, 'required_length' => 3], - ['key' => 'trackingNumber', 'text' => 'Trackingnummer', 'required' => false, 'modal' => false], - ['key' => 'create', 'text' => 'Erstellt', 'required' => true, 'modal' => false, 'filter' => 'datetime'], - ['key' => 'createBy', - 'text' => 'Erstellt von', - 'required' => true, - 'table' => ['filter' => 'select'], - 'modal' => ['type' => 'select', 'items' => []]], - ['key' => 'actions', - 'text' => 'Aktionen', - 'required' => false, - 'modal' => false, - 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']],]; + //@formatter:off + protected array $columns = [ + ['key' => 'id', 'text' => 'ID', 'modal' => false], + ['key' => 'extRef', 'text' => 'Externe Referenz', 'required' => true], + ['key' => 'status', 'text' => 'Status', 'required' => true, 'modal' => ['type' => 'select', 'items' => [['value' => 'new', 'text' => 'Neu'], ['value' => 'accepted', 'text' => 'An Lieferant übergeben'], ['value' => 'acceptedInternally', 'text' => 'Interne verarbeitung'], ['value' => 'sent', 'text' => 'Gesendet'], ['value' => 'done', 'text' => 'Erledigt'],]], 'table' => ['filter' => 'select']], + ['key' => 'shippingNoteStatus', 'text' => 'LS-Status', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'order' => false]], + ['key' => 'deliveryMode', 'text' => 'Liefermodus', 'required' => true, 'modal' => ['type' => 'select', 'items' => [['value' => 'singleAddress', 'text' => 'Einzelne Adresse']]]], + ['key' => 'deliveryAddressName', 'text' => 'Name', 'required' => true], + ['key' => 'deliveryAddressLine', 'text' => 'Adresse', 'required' => true, 'required_length' => 4], + ['key' => 'deliveryAddressPLZ', 'text' => 'PLZ', 'required' => true, 'regex' => '/^\d{4}$/'], + ['key' => 'deliveryAddressCity', 'text' => 'Stadt', 'required' => true, 'required_length' => 3], + ['key' => 'trackingNumber', 'text' => 'Trackingnummer', 'required' => false, 'modal' => false], + ['key' => 'positions', 'text' => 'Positionen', 'required' => false, 'table' => false], + ['key' => 'create', 'text' => 'Erstellt', 'required' => true, 'modal' => false, 'filter' => 'datetime'], + ['key' => 'createBy', 'text' => 'Erstellt von', 'required' => true, 'table' => ['filter' => 'select'], 'modal' => ['type' => 'select', 'items' => []]], + ['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']] + ]; - protected array $additionalActions = [['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary'], - ['key' => 'showTrackingHistory', 'title' => 'Tracking Historie', 'class' => 'fas fa-truck text-primary'], - ['key' => 'createShippingNote', 'title' => 'Lieferschein erstellen', 'class' => 'fas fa-file-invoice text-primary'], - ['key' => 'openSingleOrderEmail', 'title' => 'Bestellbestätigung', 'class' => 'fas fa-envelope text-primary'],]; + protected array $additionalActions = [ + ['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary'], + ['key' => 'showTrackingHistory', 'title' => 'Tracking Historie', 'class' => 'fas fa-truck text-primary'], + ['key' => 'createShippingNote', 'title' => 'Lieferschein erstellen', 'class' => 'fas fa-file-invoice text-primary'], + ['key' => 'openSingleOrderEmail', 'title' => 'Bestellbestätigung', 'class' => 'fas fa-envelope text-primary']# + ]; - protected array $infoMessages = ['create' => 'Bestellung wurde erfolgreich erstellt, sie erhalten in Kürze eine Bestätigungsmail', - 'update' => 'Bestellung wurde aktualisiert', - 'delete' => 'Bestellung wurde gelöscht', - 'noChanges' => 'Keine Änderungen',]; + protected array $infoMessages = [ + 'create' => 'Bestellung wurde erfolgreich erstellt, sie erhalten in Kürze eine Bestätigungsmail', + 'update' => 'Bestellung wurde aktualisiert', + 'delete' => 'Bestellung wurde gelöscht', + 'noChanges' => 'Keine Änderungen' + ]; + //@formatter:on public function permissionCheck(): bool { return $this->user->can(["WarehouseEShop"]); } + protected function customRowsHandler($rows): array { + $statusToText = [ + 'new' => 'Neu', + 'accepted' => 'Akzeptiert', + 'invoiced' => 'Verrechnet', + 'in_progress' => 'In Bearbeitung', + ]; + + foreach ($rows as $row) { + $shippingNote = WarehouseShippingNoteModel::getAll(['eShopOrderId' => $row->id]); + if (empty($shippingNote)) { + $row->shippingNoteStatus = 'Kein LS'; + } else { + $row->shippingNoteStatus = $statusToText[$shippingNote[0]->status]; + } + } + + return $rows; + } + protected function prepareCrudConfig() { $users = array_map(function ($user) { return ['value' => intval($user->id), 'text' => $user->name]; }, UserModel::search()); - $this->columns[10]['modal']['items'] = $users; + $createByIndex = array_search('createBy', array_column($this->columns, 'key')); + $this->columns[$createByIndex]['modal']['items'] = $users; } protected function createShippingNote() { @@ -71,7 +79,9 @@ class WarehouseEShopOrderController extends TTCrud { $existingShippingNote = WarehouseShippingNoteModel::getAll(['eShopOrderId' => $id]); if (!empty($existingShippingNote)) { - self::returnJson(['success' => false, 'message' => 'Für diese Bestellung existiert bereits ein Lieferschein', 'shippingNoteId' => $existingShippingNote[0]->id]); + self::returnJson(['success' => false, + 'message' => 'Für diese Bestellung existiert bereits ein Lieferschein', + 'shippingNoteId' => $existingShippingNote[0]->id]); die(); } @@ -120,9 +130,12 @@ class WarehouseEShopOrderController extends TTCrud { 'deliveryAddressLine' => $order->deliveryAddressLine, 'deliveryAddressPLZ' => $order->deliveryAddressPLZ, 'deliveryAddressCity' => $order->deliveryAddressCity, + 'deliveryAddressEMail' => '', + 'note' => 'Erstellung aus Energie Steiermark Shop Bestellung #' . $id, 'status' => 'new', 'positions' => $positions, 'textElements' => '[]', + 'hoursEntries' => '[]', 'eShopOrderId' => $id, 'create' => time(), 'createBy' => $this->user->id]); @@ -277,7 +290,8 @@ class WarehouseEShopOrderController extends TTCrud { } protected function getAllOrderItemsPerOrder(): array { - $items = WarehouseEShopOrderItemModel::getAll(); + if (isset($_GET['orderId'])) return WarehouseEShopOrderItemModel::getAll(['orderId' => $_GET['orderId']]); + else $items = WarehouseEShopOrderItemModel::getAll(); $articles = WarehouseArticleModel::getAll(); $articlePackets = WarehouseArticlePacketModel::getAll(); @@ -384,7 +398,13 @@ class WarehouseEShopOrderController extends TTCrud { die(json_encode($json)); } + protected function beforeCreate(): bool { + unset($this->postData['shippingNoteStatus']); + return true; + } + protected function beforeUpdate($postData): bool { + unset($this->postData['shippingNoteStatus']); (new WarehouseHistoryController)->create($postData, $this->mod); return true; } @@ -430,17 +450,17 @@ class WarehouseEShopOrderController extends TTCrud { } protected function readGLSEmailAction() { - function decode_utf8($str){ + function decode_utf8($str) { # paterns - $err="(=\?.{10,13}q\?_?|\?\=)"; + $err = "(=\?.{10,13}q\?_?|\?\=)"; $pat = "/=([0-9A-F]{2})/"; - $cha="'.chr(hexdec("; + $cha = "'.chr(hexdec("; # erase null signs in string $str = str_replace("\x00", "", $str); # to decode with eval and replace - eval("\$str='". - preg_replace($pat,$cha."'$1')).'",$str) - ."';"); + eval("\$str='" . + preg_replace($pat, $cha . "'$1')).'", $str) + . "';"); # return return $str; } @@ -571,4 +591,71 @@ class WarehouseEShopOrderController extends TTCrud { $result = []; } + + protected function updatePositionAction() { + $json = json_decode(file_get_contents('php://input'), true); + $id = intval($json['id']); + $articleId = $json['articleId'] ? intval($json['articleId']) : null; + $articlePacketId = $json['articlePacketId'] ? intval($json['articlePacketId']) : null; + $quantity = intval($json['quantity']); + + if (!$id || !$quantity) { + self::returnJson(['success' => false, 'message' => 'Ungültige Daten']); + die(); + } + + $position = (array) WarehouseEShopOrderItemModel::get($id); + if (!$position) { + self::returnJson(['success' => false, 'message' => 'Position nicht gefunden']); + die(); + } + + $position['articleId'] = $articleId; + $position['articlePacketId'] = $articlePacketId; + $position['quantity'] = $quantity; + WarehouseEShopOrderItemModel::update($position); + + self::returnJson(['success' => true, 'position' => $position]); + } + + protected function deletePositionAction() { + $json = json_decode(file_get_contents('php://input'), true); + $id = intval($json['id']); + + if (!$id) { + self::returnJson(['success' => false, 'message' => 'Keine ID angegeben']); + die(); + } + + $position = WarehouseEShopOrderItemModel::get($id); + if (!$position) { + self::returnJson(['success' => false, 'message' => 'Position nicht gefunden']); + die(); + } + + WarehouseEShopOrderItemModel::delete($id); + self::returnJson(['success' => true, 'message' => 'Position gelöscht']); + } + + protected function addPositionAction() { + $json = json_decode(file_get_contents('php://input'), true); + $orderId = intval($json['orderId']); + $articleId = $json['articleId'] ? intval($json['articleId']) : null; + $articlePacketId = $json['articlePacketId'] ? intval($json['articlePacketId']) : null; + $quantity = intval($json['quantity']); + + if (!$orderId || !$quantity) { + self::returnJson(['success' => false, 'message' => 'Ungültige Daten']); + die(); + } + + $position = WarehouseEShopOrderItemModel::create(['orderId' => $orderId, + 'articleId' => $articleId, + 'articlePacketId' => $articlePacketId, + 'quantity' => $quantity]); + + $position = (array) WarehouseEShopOrderItemModel::get($position); + + self::returnJson(['success' => true, 'position' => $position]); + } } diff --git a/application/WarehouseShippingNote/WarehouseShippingNoteController.php b/application/WarehouseShippingNote/WarehouseShippingNoteController.php index d5a0d9eaf..bc2660555 100644 --- a/application/WarehouseShippingNote/WarehouseShippingNoteController.php +++ b/application/WarehouseShippingNote/WarehouseShippingNoteController.php @@ -13,10 +13,10 @@ class WarehouseShippingNoteController extends TTCrud { ['key' => 'deliveryAddressPLZ', 'text' => 'L.-Adr. PLZ', 'required' => true], ['key' => 'deliveryAddressEMail', 'text' => 'L.-Adr. EMail', 'required' => false, 'table' => false], ['key' => 'note', 'text' => 'Art der Arbeit', 'required' => true, 'table' => false], - ['key' => 'status', 'text' => 'Status', 'required' => true, 'table' => ['filter' => 'select'], 'modal' => ['type' => 'select', 'items' => [['value' => 'new', 'text' => 'Neu'], ['value' => 'inProgress', 'text' => 'In Bearbeitung'], ['value' => 'accepted', 'text' => 'Akzeptiert'], ['value' => 'invoiced', 'text' => 'In Rechnung gestellt'],]]], + ['key' => 'status', 'text' => 'Status', 'required' => true, 'table' => ['filter' => 'select'], 'modal' => ['type' => 'select', 'items' => [['value' => 'new', 'text' => 'Neu'], ['value' => 'in_progress', 'text' => 'In Bearbeitung'], ['value' => 'accepted', 'text' => 'Akzeptiert'], ['value' => 'invoiced', 'text' => 'In Rechnung gestellt'],]]], ['key' => 'positions', 'text' => 'Positionen', 'required' => true, 'table' => false, 'modal' => false], - ['key' => 'create', 'text' => 'Erstellt', 'required' => false, 'modal' => false, 'table' => ['filter' => 'date']], - ['key' => 'createBy', 'text' => 'Erstellt von', 'required' => true, 'type' => 'autocomplete', 'table' => ['class' => 'text-nowrap', 'filter' => 'select'], 'modal' => ['items' => [], 'type' => 'select',]], + ['key' => 'create', 'text' => 'Erstellt', 'required' => false, 'modal' => ['visible' => false], 'table' => ['filter' => 'date']], + ['key' => 'createBy', 'text' => 'Erstellt von', 'required' => false, 'type' => 'autocomplete', 'table' => ['class' => 'text-nowrap', 'filter' => 'select'], 'modal' => ['items' => [], 'type' => 'select',]], ['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']],]; protected array $defaultOrder = ['key' => 'create', 'order' => 'DESC']; @@ -54,6 +54,14 @@ class WarehouseShippingNoteController extends TTCrud { die(); } + foreach ($postData['hoursEntries'] as $hoursEntry) { + if (!preg_match('/^[0-9,.]*$/', $hoursEntry['hourCount'])) { + http_response_code(500); + self::returnJson(['success' => false, 'message' => 'Stundenanzahl darf nur Zahlen, Komma oder Punkt enthalten']); + die(); + } + } + $postData['positions'] = json_encode($postData['positions']); return true; } @@ -77,6 +85,13 @@ class WarehouseShippingNoteController extends TTCrud { die(); } + foreach ($postData['hoursEntries'] as $hoursEntry) { + if (!preg_match('/^[0-9,.]*$/', $hoursEntry['hourCount'])) { + http_response_code(500); + self::returnJson(['success' => false, 'message' => 'Stundenanzahl darf nur Zahlen, Komma oder Punkt enthalten']); + die(); + } + } $postData['positions'] = json_encode($postData['positions']); (new WarehouseHistoryController)->create($postData, $this->mod); @@ -218,7 +233,16 @@ class WarehouseShippingNoteController extends TTCrud { foreach (json_decode($shippingNote->positions, true) as $position) { if (isset($position['article'])) { $article = WarehouseArticleModel::get($position['article']); - $position['articleTitle'] = $article->title; + if (isset($article->articleNumber)) { + $position['articleTitle'] = $article->articleNumber . " | " . $article->title; + } else { + $position['articleTitle'] = $article->title; + } + + if (isset($position['isEnergieMaterial']) && $position['isEnergieMaterial'] == 1) { + $position['articleTitle'] .= " (ESTMK)"; + } + $position['articleDescription'] = $article->description === $article->title ? "" : $article->description; $position['articleUnit'] = $article->unit; $positions[] = $position; @@ -240,18 +264,27 @@ class WarehouseShippingNoteController extends TTCrud { $hoursEntries = json_decode($shippingNote->hoursEntries, true); foreach ($hoursEntries as $hoursEntry) { // die(json_encode($hoursEntry)); - $positions[] = [ - 'articleTitle' => "Arbeitsstunden", - 'articleDescription' => "Datum: ". date("d.m.Y", strtotime($hoursEntry['date'])) . " | Mitarbeiter: " . UserModel::getOne($hoursEntry['userId'])->name, - 'articleUnit' => 'Std.', - 'amount' => $hoursEntry['hourCount'], - 'price' => $hoursEntry['hourlyPrice'] * $hoursEntry['hourCount'] ?? 0, - ]; + $articleTitle = "Arbeitsstunden"; + if (isset($hoursEntry['priceType']) && $hoursEntry['priceType'] == 50) { + $articleTitle = "Arbeitsstunden (50% Zuschlag)"; + } elseif (isset($hoursEntry['priceType']) && $hoursEntry['priceType'] == 100) { + $articleTitle = "Arbeitsstunden (100% Zuschlag)"; + } + + if (floatval(str_replace(",", ".", $hoursEntry['hourCount'])) > 0) { + $positions[] = [ + 'articleTitle' => $articleTitle, + 'articleDescription' => "Datum: ". date("d.m.Y", strtotime($hoursEntry['date'])) . " | Mitarbeiter: " . UserModel::getOne($hoursEntry['userId'])->name, + 'articleUnit' => 'Std.', + 'amount' => $hoursEntry['hourCount'], + 'price' => $hoursEntry['hourlyPrice'] * $hoursEntry['hourCount'] ?? 0, + ]; + } if ($hoursEntry['carId']) { $positions[] = [ - 'articleTitle' => "Fahrkostenpauschale", - 'articleDescription' => "Fahrzeug: " . TimerecordingCarModel::getOne($hoursEntry['carId'])->number_plate, + 'articleTitle' => "Fahrkostenpauschale (hin und retour)", + 'articleDescription' => "Datum: ". date("d.m.Y", strtotime($hoursEntry['date'])) . " | Fahrzeug: " . TimerecordingCarModel::getOne($hoursEntry['carId'])->number_plate, 'articleUnit' => 'Km', 'amount' => $hoursEntry['kilometerCount'], 'price' => 1 * $hoursEntry['kilometerCount'] ?? 0, @@ -261,6 +294,21 @@ class WarehouseShippingNoteController extends TTCrud { } + usort($positions, function ($a, $b) { + $aHasMitarbeiter = str_contains($a['articleDescription'], 'Mitarbeiter'); + $bHasMitarbeiter = str_contains($b['articleDescription'], 'Mitarbeiter'); + $aHasFahrzeug = str_contains($a['articleDescription'], 'Fahrzeug'); + $bHasFahrzeug = str_contains($b['articleDescription'], 'Fahrzeug'); + + if ($aHasMitarbeiter && !$bHasMitarbeiter) return -1; + if (!$aHasMitarbeiter && $bHasMitarbeiter) return 1; + if ($aHasFahrzeug && !$bHasFahrzeug) return -1; + if (!$aHasFahrzeug && $bHasFahrzeug) return 1; + return 0; + }); + + + $textElements = []; // parse shippingNote.textElements ({"1":true,"2":true}) to array, fetch each text element and put content into array $shippingNoteTextElements = json_decode($shippingNote->textElements, true); @@ -349,6 +397,28 @@ class WarehouseShippingNoteController extends TTCrud { self::returnJson(array_values($out)); } + 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']); + } + + $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['status'] = $status; + WarehouseShippingNoteModel::update($shippingNote); + self::returnJson(['success' => true, 'message' => 'Status wurde geändert']); + } + //TODO: either move this to TimerecordingCarController or make it better protected function timerecordingCarAutoCompleteAction() { $timerecordingCars = array_map(function ($timerecordingCar) { @@ -498,4 +568,4 @@ class WarehouseShippingNoteController extends TTCrud { self::returnJson(['success' => true, 'distance' => $roundedDistanceKm]); } -} \ No newline at end of file +} diff --git a/application/WarehouseShippingNote/WarehouseShippingNoteModel.php b/application/WarehouseShippingNote/WarehouseShippingNoteModel.php index 20d989cf1..59aed4ea2 100644 --- a/application/WarehouseShippingNote/WarehouseShippingNoteModel.php +++ b/application/WarehouseShippingNote/WarehouseShippingNoteModel.php @@ -17,8 +17,8 @@ class WarehouseShippingNoteModel extends TTCrudBaseModel { public ?string $signatureName; public ?string $signatureDate; public ?int $eShopOrderId; - public int $create; - public int $createBy; + public ?int $create; + public ?int $createBy; } diff --git a/db/migrations/20241209130000_warehouse_modify_5.php b/db/migrations/20241209130000_warehouse_modify_5.php new file mode 100644 index 000000000..c982af2f5 --- /dev/null +++ b/db/migrations/20241209130000_warehouse_modify_5.php @@ -0,0 +1,33 @@ +getEnvironment() == "thetool") { + $WarehouseHistory = $this->table("WarehouseHistory", ["signed" => true]); + $WarehouseHistory->changeColumn("old_value", "text", ["null" => true]); + $WarehouseHistory->changeColumn("new_value", "text", ["null" => true]); + $WarehouseHistory->save(); + + } + + if ($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $WarehouseHistory = $this->table("WarehouseHistory", ["signed" => true]); + $WarehouseHistory->changeColumn("old_value", "string", ["null" => true, "limit" => 255]); + $WarehouseHistory->changeColumn("new_value", "string", ["null" => true, "limit" => 255]); + $WarehouseHistory->save(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/db/migrations/20241210120000_warehouse_modify_6.php b/db/migrations/20241210120000_warehouse_modify_6.php new file mode 100644 index 000000000..c953bc38d --- /dev/null +++ b/db/migrations/20241210120000_warehouse_modify_6.php @@ -0,0 +1,31 @@ +getEnvironment() == "thetool") { + // add articleNumber varchar 255 to the table WarehouseArticle + $WarehouseArticle = $this->table("WarehouseArticle", ["signed" => true]); + $WarehouseArticle->addColumn("articleNumber", "string", ["null" => false, "limit" => 255]); + $WarehouseArticle->save(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $WarehouseArticle = $this->table("WarehouseArticle", ["signed" => true]); + $WarehouseArticle->removeColumn("articleNumber"); + $WarehouseArticle->save(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/lib/TTCrud/TTCrud.php b/lib/TTCrud/TTCrud.php index 2c9ee22c4..4f101dd10 100644 --- a/lib/TTCrud/TTCrud.php +++ b/lib/TTCrud/TTCrud.php @@ -165,6 +165,10 @@ class TTCrud extends mfBaseController { } } + if (method_exists($this, 'customRowsHandler')) { + $rows = $this->customRowsHandler($rows); + } + self::returnJson(["rows" => $rows, "autoCompleteData" => $autocompleteData, "pagination" => ["page" => $page, @@ -201,12 +205,12 @@ class TTCrud extends mfBaseController { } protected function updateAction() { - if (property_exists($this->model, 'createBy') && !isset($this->postData['createBy'])) { - $this->postData['createBy'] = $this->user->id; - } - if (property_exists($this->model, 'create') && !isset($this->postData['create'])) { - $this->postData['create'] = time(); - } +// if (property_exists($this->model, 'createBy') && !isset($this->postData['createBy'])) { +// $this->postData['createBy'] = $this->user->id; +// } +// if (property_exists($this->model, 'create') && !isset($this->postData['create'])) { +// $this->postData['create'] = time(); +// } Helper::validateArray($this->postData, array_merge($this->checkArray, ['id' => ['required' => true]])); diff --git a/lib/XinonProject/XinonProject.php b/lib/XinonProject/XinonProject.php index 3c115f919..9fdd63394 100644 --- a/lib/XinonProject/XinonProject.php +++ b/lib/XinonProject/XinonProject.php @@ -50,5 +50,42 @@ class XinonProject { return $response; } + + + /** + * Search for support tickets using a global search in Xinon OpenProject. + * @param string $search - The search query. + * @param int $pageSize - The number of results to return. + * @return array - The search results. + */ + public function searchSupportTickets(string $search, int $pageSize = 25): array { + $curl = curl_init(); + + $baseUrl = 'https://project.xinon.at/api/v3/projects/10/work_packages'; + $queryParams = [ + 'pageSize' => 25, + 'filters' => json_encode([['search' => ['operator' => '**', 'values' => [$search]]]]) + ]; + + curl_setopt_array($curl, array( + CURLOPT_URL => $baseUrl . '?' . http_build_query($queryParams), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'GET', + CURLOPT_HTTPHEADER => array('Content-Type: application/json'), + CURLOPT_USERPWD => 'apikey:' . PROJECT_API_KEY + )); + + $response = curl_exec($curl); + curl_close($curl); + + $json = json_decode($response, true); + + return $json['_embedded']['elements']; + } } ?> diff --git a/public/css/pages/Calendar/View.css b/public/css/pages/Calendar/View.css index 90c88e704..86fdc2843 100644 --- a/public/css/pages/Calendar/View.css +++ b/public/css/pages/Calendar/View.css @@ -1,17 +1,19 @@ .fc-event { border-radius: 2px; border: none; - cursor: move; + cursor: no-drop; font-size: 13px; margin: 3px 7px; padding: 1px 5px; text-align: center; } + .fc-timegrid-event-short .fc-event-main-frame { flex-direction: row; overflow: hidden; margin-left: 10px; } + .fc-toolbar { @media (max-width: 767px) { flex-direction: column; @@ -184,6 +186,18 @@ thead .fc-day-today .fc-scrollgrid-sync-inner .fc-col-header-cell-cushion { color: #fff; } +.fc-scroller-harness-liquid { + overflow: visible; +} + +.fc .fc-scroller-harness-liquid { + height: 700px; +} + +.card { + overflow: auto; +} + .card-fullscreen { display: block; z-index: 1040; @@ -311,6 +325,12 @@ thead .fc-day-today .fc-scrollgrid-sync-inner .fc-col-header-cell-cushion { top: 0; } +.fc-event-attachment-mr { + position: absolute; + right: 11px; + top: 0; +} + .fc-event-type { position: absolute; top: 0; @@ -322,6 +342,14 @@ thead .fc-day-today .fc-scrollgrid-sync-inner .fc-col-header-cell-cushion { bottom: -4px; left: -4px; } + +.fc-event-private { + position: absolute; + top: 0px; + right: -2px; +} + + .fc-timegrid-event-short .fc-event-time::after { content: ""; } @@ -498,7 +526,7 @@ thead .fc-day-today .fc-scrollgrid-sync-inner .fc-col-header-cell-cushion { #calendar-side-div { max-height: 850px; - overflow: scroll; + overflow: auto; } /* width */ @@ -611,4 +639,38 @@ thead .fc-day-today .fc-scrollgrid-sync-inner .fc-col-header-cell-cushion { .fa-arrow-right-from-bracket { color: #0600ff; cursor: pointer; +} + +.fa-unlock:after { + color: #000; + opacity: 0.7; +} + +.fa-unlock:before { + color: #cd0909; + +} + +.fa-lock:after { + color: #000; + opacity: 0.7; +} + +.modal-body .fa-lock:before { + color: #0ab900; +} + +.cal-group-name { + display: inline-block; + max-width: 170px; + margin-left: 10px; + +} + +.group-checkbox { + margin-left: -28px; + margin-top: 4px; +} +.cursor-alias{ + cursor: alias; } \ No newline at end of file diff --git a/public/js/pages/Calendar/View.js b/public/js/pages/Calendar/View.js index f700af3c4..d9ccafb29 100644 --- a/public/js/pages/Calendar/View.js +++ b/public/js/pages/Calendar/View.js @@ -63,6 +63,7 @@ function getOffset(unixTimestamp) { document.addEventListener('DOMContentLoaded', function () { let checkbox = $(".form-check-input"); let visibleCalendars = []; + let mycalendar_id = $('#calendar-id').data('calendarid'); visibleCalendars.push(0); checkbox.each(function () { if ($(this).prop('checked')) { @@ -86,6 +87,7 @@ document.addEventListener('DOMContentLoaded', function () { var duration = null; var rruleflag = false; let allDAy; + let cursorclass = ""; $.each($('.calendar-check'), function (index, value) { if ($(this).prop('checked')) { rights = true; @@ -108,7 +110,7 @@ document.addEventListener('DOMContentLoaded', function () { duration = null; rruleflag = false; category = value.ccategory.ccategory; - + cursorclass = ""; if (value.calendar_id.calendar_id in calendarRights) { if (calendarRights[value.calendar_id.calendar_id] == 'all') { @@ -116,8 +118,18 @@ document.addEventListener('DOMContentLoaded', function () { } else { rights = false; } + if (value.privateflag.privateflag == '1' && mycalendar_id != value.calendar_id.calendar_id) { + rights = false; + + } + + if (value.isorganizer.isorganizer == '1' && rights) { movable = true; + + } else if (rights) { + movable = false; + cursorclass = "cursor-alias"; } else { movable = false; } @@ -147,9 +159,10 @@ document.addEventListener('DOMContentLoaded', function () { attachments: value.attachments.attachments, calendar_id: value.calendar_id, event_type: value.event_type.event_type, - classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id], + classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id, cursorclass], textColor: value.txtColor.txtColor, backgroundColor: value.bgColor.bgColor, + privateflag: value.privateflag.privateflag, editable: rights, rruleflag: rruleflag, dates: rrule, @@ -183,9 +196,10 @@ document.addEventListener('DOMContentLoaded', function () { attachments: value.attachments.attachments, calendar_id: value.calendar_id, event_type: value.event_type.event_type, - classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id], + classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id, cursorclass], textColor: value.txtColor.txtColor, backgroundColor: value.bgColor.bgColor, + privateflag: value.privateflag.privateflag, editable: rights, rruleflag: rruleflag, dates: rrule, @@ -276,10 +290,12 @@ document.addEventListener('DOMContentLoaded', function () { schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives', timeZone: 'UTC', locale: 'de', + height: 'auto', resourceAreaWidth: '220px', themeSystem: 'bootstrap4', snapDuration: '00:15:00', selectable: true, + weekNumbers: true, headerToolbar: { left: "prev,today,next", center: 'title', @@ -370,6 +386,13 @@ document.addEventListener('DOMContentLoaded', function () { } else { $('#reminder').val('NULL'); } + if (data.data.privateflag.privateflag == 1) { + $('.privacy-click').removeClass('fa-unlock'); + $('.privacy-click').removeClass('fa-lock'); + $('.privacy-click').addClass('fa-lock'); + } + + $('#type').val(data.data.type.type); $('#busy').val(data.data.busy.busy); isOrganizer = data.data.isorganizer.isorganizer; @@ -388,6 +411,7 @@ document.addEventListener('DOMContentLoaded', function () { $('#customer').select2({ placeholder: "Kunden Suche", minimumInputLength: 3, + dropdownParent: jQuery('#relContainer2'), // dropdownParent: $('#EventModal'), language: "de", ajax: { @@ -410,7 +434,7 @@ document.addEventListener('DOMContentLoaded', function () { } if (data.data.customer_info_send.customer_info_send) { const obj = JSON.parse(data.data.customer_info_send.customer_info_send); - $('#customer-info-check-info').html(''); + $('#customer-info-check-info').html(''); const unixTime = obj.sendtime; const date = new Date(unixTime * 1000); const germanDateTime = date.toLocaleString('de-DE', { @@ -434,7 +458,8 @@ document.addEventListener('DOMContentLoaded', function () {
gesendet am: ` + germanDateTime + `
`; - var tooltip = new Tooltip($('.fa-circle-info'), { + console.log(title); + var tooltip = new Tooltip($('.customer-info-point'), { title: title, placement: 'right', trigger: 'hover', @@ -460,7 +485,10 @@ document.addEventListener('DOMContentLoaded', function () { const datetime = new Date(accept.time * 1000); const germanDateTime = datetime.toLocaleString('de-DE'); $('.accepted-status').prop('title', accept.user + ' (' + germanDateTime + ')'); + } else { + $('.accepted-status').prop('title', ''); } + $('.accepted-status').addClass('fa-circle-check'); $('.event-accepted').text('Akzeptiert'); } else { @@ -472,6 +500,7 @@ document.addEventListener('DOMContentLoaded', function () { $('.show-attendee').show(); $('.show-attendee').data('id', info.event.id); } + if (data.data.attendees.attendees) { let attendees = JSON.parse(data.data.attendees.attendees); $.each(attendees, function (index, value) { @@ -487,6 +516,12 @@ document.addEventListener('DOMContentLoaded', function () { $('#calendar-attendees').val(attendees).trigger('change'); } + if (info.event.extendedProps.rruleflag == true) { + $('#delete-event').hide(); + $('#update-event').hide(); + $('.show-attendee').hide(); + + } }); if (info.event.extendedProps.clickable) { @@ -611,16 +646,24 @@ document.addEventListener('DOMContentLoaded', function () { title += '
geändert von ' + info.event.extendedProps['mname'] + '
'; } if ($('.fc-button-active').hasClass('fc-timeGridWeek-button') || $('.fc-button-active').hasClass('fc-timeGridDay-button')) { - if (info.event.extendedProps['attachment']) { - info.el.querySelector(".fc-event-title").insertAdjacentHTML("afterend", "
"); - } + if (info.event.extendedProps['event_type'] == '2') { info.el.querySelector(".fc-event-title").insertAdjacentHTML("afterend", "
"); } + if (info.event.extendedProps['privateflag'] == 1) { + info.el.querySelector(".fc-event-title").insertAdjacentHTML("afterend", "
"); + } + if (info.event.extendedProps['attachment'] && info.event.extendedProps['privateflag'] == 1) { + info.el.querySelector(".fc-event-title").insertAdjacentHTML("afterend", "
"); + } else if (info.event.extendedProps['attachment']) { + info.el.querySelector(".fc-event-title").insertAdjacentHTML("afterend", "
"); + } if (info.event.extendedProps['rruleflag']) { info.el.querySelector(".fc-event-title").insertAdjacentHTML("afterend", "
"); } + + } var tooltip = new Tooltip(info.el, { @@ -784,6 +827,7 @@ if (typeof (EventSource) !== 'undefined') { // document.getElementById('result').innerHTML += e.data + '
'; let checkbox = $(".form-check-input"); let visibleCalendars = []; + let mycalendar_id = $('#calendar-id').data('calendarid'); visibleCalendars.push(0); checkbox.each(function () { if ($(this).prop('checked')) { @@ -801,6 +845,7 @@ if (typeof (EventSource) !== 'undefined') { var rrule = null; var duration = null; var rruleflag = false; + let cursorclass = ''; if (event.rrule) { rrule = event.rrule; duration = event.duration; @@ -814,9 +859,17 @@ if (typeof (EventSource) !== 'undefined') { } if (event.isorganizer == '1' && rights) { movable = true; + } else if (rights) { + cursorclass = "cursor-alias" + movable = false; } else { movable = false; } + if (event.privateflag == '1' && mycalendar_id != event.calendar_id_check.calendar_id) { + rights = false; + movable = false; + + } } if (event.change_type == '2' && cevent) { @@ -834,10 +887,11 @@ if (typeof (EventSource) !== 'undefined') { backgroundColor: event.bgColor, location: event.location, event_type: event.event_type, - classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id], + classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id, cursorclass], attachment: event.attachment, attachments: event.attachments, editable: movable, + privateflag: event.privateflag, rruleflag: rruleflag, rrule: rrule, duration: duration, @@ -863,11 +917,12 @@ if (typeof (EventSource) !== 'undefined') { editable: false, location: event.location, event_type: event.event_type, - classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id], + classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id, cursorclass], attachment: event.attachment, attachments: event.attachments, calendar_id: event.calendar_id_check, resourceId: event.calendar_id, + privateflag: event.privateflag, calendar_name: event.calendar_name, clickable: rights, mtime: event.mtime, @@ -892,8 +947,9 @@ if (typeof (EventSource) !== 'undefined') { textColor: event.txtColor, backgroundColor: event.bgColor, location: event.location, + privateflag: event.privateflag, event_type: event.event_type, - classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id], + classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id, cursorclass], attachment: event.attachment, attachments: event.attachments, editable: movable, @@ -918,8 +974,9 @@ if (typeof (EventSource) !== 'undefined') { color: '#ab0000', editable: false, location: event.location, + privateflag: event.privateflag, event_type: event.event_type, - classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id], + classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id, cursorclass], attachment: event.attachment, attachments: event.attachments, calendar_id: event.calendar_id_check, @@ -986,6 +1043,9 @@ $(document).ready(function () { $('.attachment-div').empty(); $('#reminder').val('NULL'); $('#type').val('1'); + $('.privacy-click').removeClass('fa-lock'); + $('.privacy-click').removeClass('fa-unlock'); + $('.privacy-click').addClass('fa-unlock'); $('#customer-info-check-info').empty(); $('#customer-info-type').val('1'); $('#customer').val(''); @@ -1061,6 +1121,11 @@ $(document).ready(function () { var customer_info_type; var customer_info_type_text; var customer_info_reminder_check = 0; + var private = $('.privacy-click'); + var privateflag = 0; + if (private.hasClass('fa-lock')) { + privateflag = 1; + } var users = []; if ($('#allday').is(':checked')) { @@ -1095,6 +1160,7 @@ $(document).ready(function () { description: description, attachments: attachments, users: users, + privateflag: privateflag, attendees: $('#calendar-attendees').val(), customer: customer, customer_info_check: customer_info_check, @@ -1149,6 +1215,11 @@ $(document).ready(function () { var customer_info_type; var customer_info_type_text; var customer_info_reminder_check = 0; + var private = $('.privacy-click'); + var privateflag = 0; + if (private.hasClass('fa-lock')) { + privateflag = 1; + } var users = []; if ($('#allday').is(':checked')) { @@ -1175,7 +1246,6 @@ $(document).ready(function () { users.push($(this).val()); }); - $.post(requestUpdateUrl, { id: id, start: start, @@ -1189,6 +1259,7 @@ $(document).ready(function () { description: description, attachments: attachments, users: users, + privateflag: privateflag, attendees: $('#calendar-attendees').val(), customer: customer, customer_info_check: customer_info_check, @@ -1276,17 +1347,6 @@ $(document).ready(function () { var txtcolors = []; var calendar_id = []; var thisis = $(this); - if (init === 0) { - var resourceA = calendar.getResourceById(thisis.data('calendar_id')); - if (resourceA) { - var events = resourceA.getEvents(); - events.forEach(function (event) { - event.setProp('backgroundColor', thisis.closest('div').find('.color-input').val()); - event.setProp('textColor', thisis.closest('div').find('.color-text-input').val()); - }); - } - calendar.render(); - } $.each($('.color-input'), function (index, value) { if ($(this).data('calendar_id')) { bgcolors.push($(this).closest('div').find('.color-input').val()); @@ -1308,6 +1368,10 @@ $(document).ready(function () { groups: groups }, function (data) { + }).done(function (data) { + if (init === 0) { + refreshCalendarEvents(); + } }) }); $('body').on('change', '.calendar-check', function (event, init = 0) { @@ -1440,6 +1504,7 @@ $(document).ready(function () { placeholder: "Kunden Suche", minimumInputLength: 3, // dropdownParent: $('#EventModal'), + dropdownParent: jQuery('#relContainer2'), language: "de", ajax: { url: requestAddressUrl, @@ -1487,7 +1552,8 @@ $(document).ready(function () { return { q: params.term, // Der Suchbegriff term: params.term, // Der Suchbegriff - calendars: visibleCalendars // Die dynamische Variable, die du hinzufügen möchtest + calendars: visibleCalendars, // Die dynamische Variable, die du hinzufügen möchtest + cal_id: $('#calendar-id').data('calendarid') }; }, dataType: 'json', @@ -1591,6 +1657,11 @@ Xinon GMbH`; let groupname = $.trim($(this).text()); $(this).html(''); + var strLength = $(this).find('.cal-group-name-input').val().length * 2; + + + $(this).find('.cal-group-name-input')[0].setSelectionRange(strLength, strLength); + $(this).find('.cal-group-name-input').focus(); }); $("body").on("click", ".group-checkbox", function () { @@ -1642,14 +1713,28 @@ Xinon GMbH`; $(this).removeClass('fa-square-arrow-up'); $(this).addClass('fa-square-arrow-down'); $(this).closest('.calendar-side-borders-sub').find('.calendar-side-borders-sub-inner').hide(); + $(".color-input").eq(0).trigger("change", 1); } else { $(this).removeClass('fa-square-arrow-down'); $(this).addClass('fa-square-arrow-up'); $(this).closest('.calendar-side-borders-sub').find('.calendar-side-borders-sub-inner').show(); + $(".color-input").eq(0).trigger("change", 1); } }); + $("body").on("click", ".privacy-click", function (e) { + if ($(this).hasClass('fa-unlock')) { + $(this).removeClass('fa-unlock'); + $(this).addClass('fa-lock'); + $(this).prop('title', 'Privat'); + } else { + $(this).removeClass('fa-lock'); + $(this).addClass('fa-unlock'); + $(this).prop('title', 'Normal'); + } + }); + $("body").on("keyup", ".cal-group-name-input", function (e) { if (e.keyCode === 13) { let groupname = $.trim($(this).val()); @@ -1672,11 +1757,26 @@ Xinon GMbH`; $(this).closest('div').find('.move-group-div').show(); $(this).closest('div').find('.group-checkbox-div').show(); $(this).closest('.cal-group-name').text($(this).data('oldname')); - } } }); + $("body").on("blur", ".cal-group-name-input", function (e) { + let groupname = $.trim($(this).val()); + if (groupname.length > 3) { + + $(this).closest('div').find('.dropdown-group-div').show(); + $(this).closest('div').find('.move-group-div').show(); + $(this).closest('div').find('.group-checkbox-div').show(); + $(this).closest('.cal-group-name').text(groupname); + $(".color-input").eq(0).trigger("change", 1); + } else { + $(this).closest('div').find('.dropdown-group-div').show(); + $(this).closest('div').find('.move-group-div').show(); + $(this).closest('div').find('.group-checkbox-div').show(); + $(this).closest('.cal-group-name').text($(this).data('oldname')); + } + }); function getGroups() { const groups = []; @@ -1794,6 +1894,7 @@ Xinon GMbH`; calendar.removeAllEvents(); let checkbox = $(".calendar-check"); let visibleCalendars = []; + let mycalendar_id = $('#calendar-id').data('calendarid'); visibleCalendars.push(0); checkbox.each(function () { if ($(this).prop('checked')) { @@ -1817,6 +1918,7 @@ Xinon GMbH`; var duration = null; var rruleflag = false; let allDAy = false; + let cursorclass = ""; $.each($('.calendar-check'), function (index, value) { if ($(this).prop('checked')) { rights = true; @@ -1838,6 +1940,7 @@ Xinon GMbH`; duration = null; rruleflag = false; allDAy = false; + cursorclass = ""; category = value.ccategory.ccategory; if (value.rrule.rrule) { rrule = value.rrule.rrule; @@ -1853,9 +1956,19 @@ Xinon GMbH`; } if (value.isorganizer.isorganizer == '1' && rights) { movable = true; + } else if (rights) { + movable = false; + cursorclass = "cursor-alias"; } else { movable = false; } + + if (value.privateflag.privateflag == '1' && mycalendar_id != value.calendar_id.calendar_id) { + rights = false; + movable = false; + + } + if (value.allDay.allDay == "1") { allDAy = true; } @@ -1882,10 +1995,11 @@ Xinon GMbH`; attachments: value.attachments.attachments, calendar_id: value.calendar_id, event_type: value.event_type.event_type, - classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id], + classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id, cursorclass], textColor: value.txtColor.txtColor, backgroundColor: value.bgColor.bgColor, editable: rights, + privateflag: value.privateflag.privateflag, rruleflag: rruleflag, dates: rrule, duration: duration, @@ -1918,10 +2032,11 @@ Xinon GMbH`; attachments: value.attachments.attachments, calendar_id: value.calendar_id, event_type: value.event_type.event_type, - classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id], + classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id, cursorclass], textColor: value.txtColor.txtColor, backgroundColor: value.bgColor.bgColor, editable: rights, + privateflag: value.privateflag.privateflag, rruleflag: rruleflag, dates: rrule, duration: duration, diff --git a/public/js/pages/WarehouseEShopOrder/WarehouseEShopOrder.js b/public/js/pages/WarehouseEShopOrder/WarehouseEShopOrder.js index b8ae92fcd..d6cd8c89e 100644 --- a/public/js/pages/WarehouseEShopOrder/WarehouseEShopOrder.js +++ b/public/js/pages/WarehouseEShopOrder/WarehouseEShopOrder.js @@ -1,74 +1,235 @@ // noinspection JSUnusedLocalSymbols + +const articleAPIUrl = `${window['TT_CONFIG']['BASE_PATH']}/WarehouseArticle/autocomplete`; +const articlePacketAPIUrl = `${window['TT_CONFIG']['BASE_PATH']}/WarehouseArticlePacket/autocomplete`; + +Vue.component('warehouse-e-shop-order-modal-positions-mgmt', { + props: { + id: {type: [String, Number], required: true}, + }, data() { + return { + window: window, + positions: [], + articleAPIUrl: articleAPIUrl, + articlePacketAPIUrl: articlePacketAPIUrl, + articleNames: {}, + articlePacketNames: {}, + articleId: null, + articlePacketId: null, + amount: null, + editIndex: null, + } + }, async mounted() { + // get all positions by /WarehouseEShopOrder/getAllItemsPerOrder?orderId=ID + const response = await axios.get(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/getAllItemsPerOrder?orderId=${this.id}`); + this.positions = response.data; + }, methods: { + async fetchNames() { + console.log("hallohallo"); + // TODO: there must be a better way to do this + for (const position of this.positions) { + if (position.articleId) this.$set(this.articleNames, position.articleId, 'Loading...'); + if (position.articlePacketId) this.$set(this.articlePacketNames, position.articlePacketId, 'Loading...'); + } + + const articlePromises = this.positions.filter(position => position.articleId) + .map(position => axios.get(window.TT_CONFIG["BASE_PATH"] + '/WarehouseArticle/autoComplete?searchedID=' + position.articleId)); + const articlePacketPromises = this.positions.filter(position => position.articlePacketId) + .map(position => axios.get(window.TT_CONFIG["BASE_PATH"] + '/WarehouseArticlePacket/autoComplete?searchedID=' + position.articlePacketId)); + + const articleResponses = await Promise.all(articlePromises); + const articlePacketResponses = await Promise.all(articlePacketPromises); + + for (const response of articleResponses) { + this.$set(this.articleNames, response.data[0].value, response.data[0].text); + } + + for (const response of articlePacketResponses) { + this.$set(this.articlePacketNames, response.data[0].value, response.data[0].text); + } + + }, + async addPosition() { + if (!this.articleId && !this.articlePacketId) return window.notify('error', 'Bitte wählen Sie einen Artikel oder ein Artikel Packet aus.'); + if (this.editIndex !== null) return this.updatePosition(); + + const response = await axios.post(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/addPosition`, { + orderId: this.id, + articleId: this.articleId, + articlePacketId: this.articlePacketId, + quantity: this.amount, + }); + + if (response.data.success) { + this.positions.push(response.data.position); + this.articleId = null; + this.articlePacketId = null; + this.amount = null; + window.notify('success', 'Position hinzugefügt'); + } else { + window.notify('error', response.data.message); + } + }, + async updatePosition() { + const position = this.positions[this.editIndex]; + const response = await axios.post(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/updatePosition`, { + id: position.id, + articleId: this.articleId, + articlePacketId: this.articlePacketId, + quantity: this.amount, + }); + + if (response.data.success) { + this.positions[this.editIndex] = response.data.position; + this.articleId = null; + this.articlePacketId = null; + this.amount = null; + this.editIndex = null; + window.notify('success', response.data.message); + } else { + window.notify('error', response.data.message); + } + }, + async deletePosition(id) { + const response = await axios.post(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/deletePosition`, {id}); + + if (response.data.success) { + this.positions = this.positions.filter(position => position.id !== id); + window.notify('success', response.data.message); + } else { + window.notify('error', response.data.message); + } + }, + async editPosition(id) { + const position = this.positions.find(position => position.id === id); + this.articleId = position.articleId; + this.articlePacketId = position.articlePacketId; + this.amount = position.quantity; + this.editIndex = this.positions.indexOf(position); + }, + }, watch: {positions: {handler: 'fetchNames', immediate: true}}, //language=Vue + template: ` +
+ +
+ + + +
+ +
+
+ +
+
PositionMengeEinheitArtikelPositionMengeEinheitArtikel Preis
+ + + + + + + + + + + + + + + + + +
ArtikelMengeAktionen
Keine Einträge
{{ position.articleId ? articleNames[position.articleId] : position.articlePacketId ? articlePacketNames[position.articlePacketId] : + 'Loading...' }} + {{ position.quantity }} + + +
+
+ + +
+ `, + + +}) + Vue.component('warehouse-e-shop-order', { //language=Vue - template: ` - - + template: ` + + - + - + - - - - - - -
-

-
- -
- -
-
- - -
-
    -
  • - {{ entry.date }} {{ entry.time }} - {{ entry.evtDscr }} -
  • -
-
- -
+ -
- `, data() { +
+ `, data() { return { window: window, historyModal: false, @@ -79,7 +240,10 @@ Vue.component('warehouse-e-shop-order', { singleOrderEmailModalText: null, openTrackingHistoryModal: false, trackingHistoryModalId: null, - trackingHistoryModalData: null, + trackingHistoryModalData: null, // modal + positionsEntryArticleId: null, + positionsEntryArticlePacketId: null, + positionsEntryAmount: null, } }, async mounted() { const response = await axios.get(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/getAllItemsPerOrder`); @@ -92,8 +256,7 @@ Vue.component('warehouse-e-shop-order', { if (response.data.shippingNoteId) { window.open(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseShippingNote/createPDF?id=${response.data.shippingNoteId}&price=true`, '_blank'); } - }, - async sendSingleOrderEmail() { + }, async sendSingleOrderEmail() { const response = await axios.get(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/singleOrderEmail?id=${this.singleOrderEmailModalId}`); if (response.data.message) { window.notify(response.data.success === true ? 'success' : 'error', response.data.message); @@ -148,8 +311,7 @@ Vue.component('warehouse-e-shop-order', { .then(response => this.singleOrderEmailModalText = response.data) .catch(error => window.notify('error', error.response?.data?.message || 'Ein Fehler ist aufgetreten')); } - }, - async trackingHistoryModalId() { + }, async trackingHistoryModalId() { this.openTrackingHistoryModal = !!this.trackingHistoryModalId; this.trackingHistoryModalData = null; if (this.trackingHistoryModalId) { diff --git a/public/js/pages/WarehouseShippingNote/WarehouseShippingNote.css b/public/js/pages/WarehouseShippingNote/WarehouseShippingNote.css index c4baf9c04..be92707e7 100644 --- a/public/js/pages/WarehouseShippingNote/WarehouseShippingNote.css +++ b/public/js/pages/WarehouseShippingNote/WarehouseShippingNote.css @@ -1,9 +1,13 @@ .warehouse-shipping-note-modal-positions-entry-container { display: grid; - grid-template-columns: 2fr 1fr 1fr 1fr; + grid-template-columns: 2fr 1fr 0.5fr 1fr 1fr; grid-gap: 10px; } +.warehouse-shipping-note-modal-positions-entry-container.hidePrice { + grid-template-columns: 2fr 1fr 0.5fr 1fr; +} + .warehouse-shipping-note-modal-positions-entry-actions, .warehouse-shipping-note-modal-hours-entry-actions { display: flex; flex-direction: column; @@ -13,12 +17,16 @@ .warehouse-shipping-note-modal-hours-entry-container { display: grid; - grid-template-columns: 2fr 1fr 1fr 2fr 1fr 1fr 1fr; + grid-template-columns: 2fr 1fr 1fr 1fr 2fr 1fr 1fr 1fr; grid-gap: 10px; } .warehouse-shipping-note-modal-hours-entry-container.hideHourlyPrice { - grid-template-columns: 2fr 1fr 1fr 2fr 1fr 1fr; + grid-template-columns: 2fr 1fr 1fr 1fr 2fr 1fr 1fr; +} + +.warehouse-shipping-note-modal-hours-entry-container.hideHourlyPrice.hideKilometer { + grid-template-columns: 2fr 1fr 1fr 1fr 2fr 1fr; } @media (min-width: 992px) { @@ -36,10 +44,19 @@ grid-gap: 10px; } - .warehouse-shipping-note-modal-positions-entry-actions, .warehouse-shipping-note-modal-hours-entry-actions { + .warehouse-shipping-note-modal-positions-entry-actions { grid-column: 2; } + .warehouse-shipping-note-modal-hours-entry-actions { + grid-column: 1 / span 2; + margin-bottom: 8px; + } + + .modal .table.table-striped.table-sm button{ + margin-bottom: 4px; + } + .signModal > div { margin: 0; width: 100vw; diff --git a/public/js/pages/WarehouseShippingNote/WarehouseShippingNote.js b/public/js/pages/WarehouseShippingNote/WarehouseShippingNote.js index a81c70e4f..25f6e2309 100644 --- a/public/js/pages/WarehouseShippingNote/WarehouseShippingNote.js +++ b/public/js/pages/WarehouseShippingNote/WarehouseShippingNote.js @@ -80,7 +80,10 @@ Vue.component('warehouse-shipping-note', { signingShippingNoteId: null } }, - methods: { - + mounted() { + // check if get parameter doAction = createNew is set, if so open the modal with 'create' as id + if (window.location.search.includes('doAction=createNew')) { + this.shippingNoteModalId = 'create'; + } } }) diff --git a/public/js/pages/WarehouseShippingNote/WarehouseShippingNoteModal.js b/public/js/pages/WarehouseShippingNote/WarehouseShippingNoteModal.js index ebc20857c..5eed3fbfc 100644 --- a/public/js/pages/WarehouseShippingNote/WarehouseShippingNoteModal.js +++ b/public/js/pages/WarehouseShippingNote/WarehouseShippingNoteModal.js @@ -47,17 +47,19 @@ Vue.component('warehouse-shipping-note-modal-hours-entry', { hourCount: '', kilometerCount: '', hourlyPrice: '', + priceType: 'normal', } }, //language=Vue template: ` -
+
+ - +
@@ -74,6 +76,7 @@ Vue.component('warehouse-shipping-note-modal-hours-entry', { userId: this.userId, date: this.date, hourCount: this.hourCount, + priceType: this.priceType, hourlyPrice: this.hourlyPrice || null, carId: this.carId ? this.carId : null, kilometerCount: this.carId ? this.kilometerCount : null @@ -103,7 +106,7 @@ Vue.component('warehouse-shipping-note-modal-hours-entry', { if (!this.userId || this.carId) return; const response = await axios.get(window.TT_CONFIG["BASE_PATH"] + '/WarehouseShippingNote/timerecordingCarForUser?userId=' + this.userId); if (response.data.status === 'USER_NO_CAR') { - this.window.notify('info', 'Kein zugewiesenes Fahrzeug gefunden'); + // this.window.notify('info', 'Kein zugewiesenes Fahrzeug gefunden'); this.carId = ''; return; } @@ -165,7 +168,7 @@ Vue.component('warehouse-shipping-note-modal-hours-view', { {{ userNames[entry.userId] }} {{ window.moment(entry.date).format('DD.MM.YYYY') }} {{ entry.hourCount }} - {{ entry.kilometerCount }} + {{ entry.kilometerCount }} {{ entry.hourlyPrice }} @@ -254,21 +257,24 @@ Vue.component('warehouse-shipping-note-modal-positions-entry', { data() { return { window: window, + isAdmin: false, articleApiUrl: window.TT_CONFIG['BASE_PATH'] + '/WarehouseArticle/autoComplete', articlePacketApiUrl: window.TT_CONFIG['BASE_PATH'] + '/WarehouseArticlePacket/autoComplete', articleId: '', articlePacketId: '', amount: '', price: '', + isEnergieMaterial: false, } }, //language=Vue template: ` -
+
- + +
@@ -280,8 +286,10 @@ Vue.component('warehouse-shipping-note-modal-positions-entry', { if (!this.amount) return this.window.notify('error', 'Bitte füllen sie die Menge aus'); const data = { amount: this.amount, + isEnergieMaterial: this.isEnergieMaterial, price: parseFloat(this.price) ?? '' } + if (isNaN(data.price)) data.price = ''; if (!this.articleId && this.$refs.article.displayValue) { data.articleText = this.$refs.article.displayValue; } else if (this.articleId) { @@ -317,6 +325,7 @@ Vue.component('warehouse-shipping-note-modal-positions-view', { data() { return { window: window, + isAdmin: false, articleNames: {}, articlePacketNames: {}, } @@ -329,7 +338,8 @@ Vue.component('warehouse-shipping-note-modal-positions-view', { Artikel Menge - Preis + Energie Material + Preis Aktionen @@ -342,7 +352,8 @@ Vue.component('warehouse-shipping-note-modal-positions-view', { position.articleText }} {{ position.amount }} - {{ (position.price?.toFixed(2)) }} € + {{ position?.isEnergieMaterial ? 'Ja' : 'Nein' }} + {{ (position.price?.toFixed(2)) }} € @@ -497,13 +508,13 @@ Vue.component('warehouse-shipping-note-modal', {