6 private $ddBind =
'dbxWorkflow|workflowModuleBind';
8 private function db() {
9 return dbx()->get_system_obj(
'dbxDB');
12 private function tpl() {
13 return dbx()->get_system_obj(
'dbxTPL');
16 private function h(
$value) {
17 return htmlspecialchars((
string)
$value, ENT_QUOTES,
'UTF-8');
20 private function read_json(
$value, $default = array()) {
25 $data = json_decode(
$value,
true);
26 return is_array($data) ? $data : $default;
30 $bindRef = trim((
string)$bindRef);
31 if ($bindRef ===
'' || strpos($bindRef,
'|') ===
false) {
35 $parts = explode(
'|', $bindRef, 2);
36 return array(trim((
string)$parts[0]), trim((
string)$parts[1]));
41 if ($modul ===
'' || $bindKey ===
'') {
45 $rows = $this->db()->select(
47 array(
'modul' => $modul,
'bind_key' => $bindKey,
'active' => 1,
'trash' => 0),
61 $bindRef = trim((
string)(
$definition[
'bind_ref'] ??
''));
62 if ($bindRef ===
'') {
71 $bind = $this->read_json($row[
'bind_json'] ??
'', array());
84 return (array)($this->bindConfig(
$definition)[
'record'] ?? array());
89 $idNeed = trim((
string)($record[
'id_need'] ??
''));
90 if ($idNeed ===
'' || !array_key_exists($idNeed, $values)) {
94 return (
int)preg_replace(
'/\D+/',
'', (
string)$values[$idNeed]);
99 $dd = trim((
string)($recordCfg[
'dd'] ??
''));
101 if (
$dd ===
'' || $rid <= 0) {
105 $row = $this->db()->select1(
$dd, $rid);
106 return (is_array($row) && $row) ? $row : array();
109 private function labelFromTemplate(
$template, array $row) {
111 foreach ($row as $key =>
$value) {
113 $label = str_replace(
'{' . $key .
'}', (
string)
$value, $label);
120 private function optionsFromDdSelect(array $bindNeed, array
$definition, array $values) {
122 $dd = trim((
string)($record[
'dd'] ??
''));
128 array(
'dd' =>
$dd,
'include_from' => (
string)($record[
'id_need'] ??
'')),
141 $where = (array)(
$source[
'where'] ?? array());
143 $valueField = trim((
string)(
$source[
'value'] ??
'id'));
144 $labelTpl = trim((
string)(
$source[
'label'] ?? (
'{' . $valueField .
'}')));
146 if ($valueField !==
'' && !in_array($valueField,
$fields,
true)) {
150 $rows = $this->db()->select(
154 (
string)(
$source[
'order_field'] ??
'id'),
155 (
string)(
$source[
'order_dir'] ??
'DESC'),
157 (
int)(
$source[
'limit'] ?? 200),
165 foreach ((array)
$rows as $row) {
166 $id = (string)($row[$valueField] ??
'');
173 'label' => $this->labelFromTemplate($labelTpl, $row),
177 $includeId = (string)(
int)$includeId;
178 if ((
int)$includeId > 0 && empty($seen[$includeId])) {
179 $record = $this->db()->select1(
$dd, (
int)$includeId,
$fields);
180 if (is_array($record) && $record) {
182 'value' => $includeId,
183 'label' => $this->labelFromTemplate($labelTpl, $record),
191 private function optionsFromFdField(array
$definition, $fieldName) {
193 $dd = trim((
string)($record[
'dd'] ??
''));
194 $fieldName = trim((
string)$fieldName);
195 if (
$dd ===
'' || $fieldName ===
'') {
199 $oDD =
dbx()->get_system_obj(
'dbxDD');
200 $model =
$oDD->get_dd_model(
$dd);
203 foreach ((array)($model[
'fields'] ?? array()) as
$field) {
204 if ((
string)(
$field[
'name'] ??
'') === $fieldName) {
205 $optionsRaw = (string)(
$field[
'options'] ??
'');
210 if ($optionsRaw ===
'') {
215 foreach (explode(
'&', $optionsRaw) as $pair) {
217 if ($pair ===
'' || strpos($pair,
'=') ===
false) {
220 list(
$value, $label) = explode(
'=', $pair, 2);
223 'label' => trim($label),
230 private function configHasPart($modul, $key, $part) {
231 if ($part !==
'mail') {
235 if ($modul ===
'dbxContact' && !class_exists(
'\\dbx\\dbxContact\\dbxContactConfig',
false)) {
236 $path =
dbx()->get_base_dir() .
'dbx/modules/dbxContact/include/dbxContactConfig.class.php';
237 if (is_file($path)) {
242 if (class_exists(
'\\dbx\\dbxContact\\dbxContactConfig',
false)) {
243 return \dbx\dbxContact\dbxContactConfig::modulMailEnabled((
string) $modul, (
string) $key);
246 $mode = strtolower(trim((
string)
dbx()->get_config($modul, $key)));
247 return (
$mode ===
'both' ||
$mode ===
'mail' || strpos(
$mode,
'mail') !==
false);
250 private function needBind(array
$definition, $needKey) {
251 return (array)($this->bindConfig(
$definition)[
'needs'][$needKey] ?? array());
254 private function needVisible(array
$definition, $needKey, array $bindNeed) {
255 $showIf = (array)($bindNeed[
'show_if_config'] ?? array());
260 $modul = trim((
string)($showIf[
'modul'] ??
''));
261 $key = trim((
string)($showIf[
'key'] ??
''));
262 $has = trim((
string)($showIf[
'has'] ??
''));
264 if ($modul ===
'' || $key ===
'' || $has ===
'') {
268 return $this->configHasPart($modul, $key, $has);
273 $bindNeeds = (array)($this->bindConfig(
$definition)[
'needs'] ?? array());
277 if (!is_array(
$need)) {
281 $key = (string)(
$need[
'key'] ??
'');
282 $bindNeed = (array)($bindNeeds[$key] ?? array());
284 if ($bindNeed && !$this->needVisible(
$definition, $key, $bindNeed)) {
288 if (!empty(
$need[
'source']) && is_array(
$need[
'source'])) {
294 } elseif ($bindNeed) {
295 $type = (string)($bindNeed[
'type'] ??
'');
296 if ($type ===
'dd_select') {
297 $need[
'options'] = $this->optionsFromDdSelect($bindNeed,
$definition, $values);
298 } elseif ($type ===
'dd_field_options') {
299 $need[
'options'] = $this->optionsFromFdField(
$definition, (
string)($bindNeed[
'field'] ??
''));
300 } elseif ($type ===
'static_select') {
301 $need[
'options'] = array_values((array)($bindNeed[
'options'] ?? array()));
313 private function enrichShopEbayPublishDefinition(array
$definition, array $values): array {
314 if ((string)(
$definition[
'workflow_key'] ??
'') !==
'shop_ebay_publish') {
318 $productId = (int)($values[
'product'] ?? 0);
319 if ($productId <= 0) {
323 $rows = $this->db()->select(
324 'dbxShop|shopProductChannel',
325 array(
'product_id' => $productId,
'channel_key' =>
'ebay'),
326 array(
'external_listing_id',
'external_offer_id',
'export_status',
'export_message'),
335 $listingId = trim((
string)($row[
'external_listing_id'] ??
''));
336 $offerId = trim((
string)($row[
'external_offer_id'] ??
''));
337 $status = trim((
string)($row[
'export_status'] ??
''));
338 $message = trim((
string)($row[
'export_message'] ??
''));
341 if ((
string)(
$need[
'key'] ??
'') !==
'ebay_view') {
345 if ($listingId !==
'') {
346 $need[
'hint'] =
'Optionaler Kontrollschritt: Das eBay-Angebot wurde mit Listing-ID ' . $listingId .
' gespeichert. Oeffne das Angebot und pruefe Darstellung, Preis, Versand und Bilder.';
347 $need[
'module_links'] = array(
349 'label' =>
'Bei eBay ansehen',
350 'icon' =>
'bi-box-arrow-up-right',
351 'url' =>
'https://www.ebay.de/itm/' . rawurlencode($listingId),
352 'title' =>
'eBay-Angebot ansehen',
357 'label' =>
'eBay-Mapping',
358 'icon' =>
'bi-sliders2',
359 'url' =>
'?dbx_modul=dbxShop_admin&dbx_run1=product_channel_mapping&id={product}&channel=ebay',
360 'title' =>
'Channel-Mapping: eBay',
367 if ($offerId !==
'') {
368 $extra[] =
'Offer-ID: ' . $offerId;
370 if ($status !==
'') {
371 $extra[] =
'Status: ' . $status;
373 if ($message !==
'') {
376 $need[
'hint'] =
'Optionaler Kontrollschritt: Es ist noch keine eBay Listing-ID gespeichert. Pruefe zuerst Exportstatus und Mapping.'
377 . ($extra ?
' ' . implode(
' | ', $extra) :
'');
389 if (empty($recordCfg[
'prefill_rid']) || $rid <= 0) {
399 $idNeed = trim((
string)($recordCfg[
'id_need'] ??
''));
400 if ($idNeed !==
'') {
401 $values[$idNeed] = (string)$rid;
404 foreach ((array)($this->bindConfig(
$definition)[
'needs'] ?? array()) as $needKey => $bindNeed) {
405 $type = (string)($bindNeed[
'type'] ??
'');
406 if ($type ===
'dd_field_options' && isset($record[(
string)($bindNeed[
'field'] ??
'')])) {
407 $values[$needKey] = (string)$record[(
string)$bindNeed[
'field']];
409 if ($type ===
'dd_field_value' && isset($record[(
string)($bindNeed[
'field'] ??
'')])) {
410 $text = trim((
string)$record[(
string)$bindNeed[
'field']]);
412 $values[$needKey] = $text;
420 private function shopEbayReadinessAutomation(array $values): ?array {
421 $productId = (int)($values[
'product'] ?? 0);
422 if ($productId <= 0)
return null;
424 $repo =
dbx()->get_include_obj(
'dbxShopRepository',
'dbxShop');
425 if (!is_object(
$repo) || !method_exists(
$repo,
'productChannelMapping')) {
429 $data =
$repo->productChannelMapping($productId,
'ebay');
430 if (!is_array($data)) {
431 return array(
'value' =>
'needs_work',
'message' =>
'Artikel oder eBay-Channel wurde nicht gefunden.');
434 $product = (array)($data[
'product'] ?? array());
435 $channel = (array)($data[
'channel'] ?? array());
436 $productChannel = (array)($data[
'product_channel'] ?? array());
437 $mapping = (array)($data[
'mapping'] ?? array());
440 if ((
int)($channel[
'active'] ?? 0) !== 1)
$missing[] =
'eBay-Channel aktiv';
441 if ((
int)($channel[
'export_enabled'] ?? 0) !== 1)
$missing[] =
'Channel-Export freigeben';
442 if ((
int)($productChannel[
'active'] ?? 0) !== 1)
$missing[] =
'Artikel dem eBay-Channel zuordnen';
445 'api_client_id' =>
'Client-ID/App-ID',
446 'api_client_secret' =>
'Client-Secret/Cert-ID',
447 'marketplace_id' =>
'Marketplace-ID',
448 'location_key' =>
'Location-Key',
451 if (trim((
string)($channel[$key] ??
'')) ===
'')
$missing[] = $label;
453 if (trim((
string)($channel[
'api_refresh_token'] ??
'')) ===
'' && trim((
string)($channel[
'api_access_token'] ??
'')) ===
'') {
454 $missing[] =
'Refresh-Token oder Access-Token';
458 'category_id' =>
'Kategorie-ID',
459 'payment_policy_id' =>
'Payment-Policy',
460 'fulfillment_policy_id' =>
'Fulfillment-Policy',
461 'return_policy_id' =>
'Return-Policy',
463 foreach ($mapped as $key => $label) {
464 $resolved = trim((
string)($mapping[$key] ?? $channel[$key] ??
''));
468 $sku = trim((
string)($productChannel[
'channel_sku'] ?? $product[
'sku'] ??
''));
469 if ($sku ===
'')
$missing[] =
'Channel-SKU/Artikelnummer';
470 if (trim((
string)($product[
'title'] ??
'')) ===
'')
$missing[] =
'Artikeltitel';
475 'value' =>
'needs_work',
476 'message' =>
'Automatische Bereitschaftsprüfung: Bitte ergänzen: ' . implode(
', ',
$missing) .
'.',
482 'message' =>
'Automatische Bereitschaftsprüfung: eBay-Grunddaten, Zuordnung und Policies sind vollständig.',
486 private function shopEbayStatusAutomation(array $values): ?array {
487 $productId = (int)($values[
'product'] ?? 0);
488 if ($productId <= 0)
return null;
490 $rows = $this->db()->select(
491 'dbxShop|shopProductChannel',
492 array(
'product_id' => $productId,
'channel_key' =>
'ebay'),
493 array(
'external_listing_id',
'export_status',
'export_message',
'last_export_date'),
502 $lastExport = trim((
string)($row[
'last_export_date'] ??
''));
503 if ($lastExport ===
'')
return null;
505 $status = strtolower(trim((
string)($row[
'export_status'] ??
'')));
506 $listingId = trim((
string)($row[
'external_listing_id'] ??
''));
507 $connectorMessage = trim((
string)($row[
'export_message'] ??
''));
509 if (in_array($status, array(
'failed',
'error'),
true)) {
511 } elseif ($listingId !==
'' && in_array($status, array(
'published',
'exported',
'ready'),
true)) {
515 $message =
'Connector-Status automatisch ausgewertet: ' . ($status !==
'' ? $status :
'offen') .
'.';
516 if ($listingId !==
'') $message .=
' Listing-ID: ' . $listingId .
'.';
517 if ($connectorMessage !==
'') $message .=
' ' . $connectorMessage;
518 return array(
'value' =>
$value,
'message' => $message);
522 if ((string)(
$need[
'automation'] ??
'manual') !==
'observe') return null;
523 if ((
string)(
$definition[
'workflow_key'] ??
'') !==
'shop_ebay_publish')
return null;
525 $key = (string)(
$need[
'key'] ??
'');
526 if ($key ===
'readiness_check')
return $this->shopEbayReadinessAutomation($values);
527 if ($key ===
'status_check')
return $this->shopEbayStatusAutomation($values);
531 private function contextData(array
$definition, array $record) {
532 $context = (array)($this->bindConfig(
$definition)[
'context'] ?? array());
533 $fields = (array)($context[
'fields'] ?? array());
536 foreach (
$fields as $tplKey => $recordKey) {
537 $value = $record[(string)$recordKey] ??
'';
538 if ($tplKey ===
'phone' && trim((
string)
$value) ===
'') {
541 $data[$tplKey] = $this->h(
$value);
549 $context = (array)($this->bindConfig(
$definition)[
'context'] ?? array());
554 $hideOn = trim((
string)($context[
'hide_on_need'] ??
''));
557 if ($rid > 0 && $hideOn !==
'' &&
$need[
'key'] !== $hideOn) {
560 $tpl = trim((
string)($context[
'tpl'] ??
''));
562 return $this->tpl()->get_tpl(
$tpl, $this->contextData(
$definition, $record));
567 if ($hideOn !==
'' &&
$need[
'key'] === $hideOn && $rid <= 0) {
570 if (($bindNeed[
'type'] ??
'') ===
'dd_select') {
573 return $this->tpl()->get_tpl(
'dbx|alert-info', array(
574 'msg' =>
'Keine passenden Datensaetze gefunden. Bitte zuerst im Modul erfassen.',
586 if ((
string)($bindNeed[
'type'] ??
'') !==
'dd_field_value') {
590 if (array_key_exists(
$need[
'key'], $values)) {
591 return $this->h($values[
$need[
'key']]);
597 $field = (string)($bindNeed[
'field'] ??
'');
598 if ($record &&
$field !==
'') {
599 return $this->h(trim((
string)($record[
$field] ??
'')));
608 $needKey = (string)(
$need[
'key'] ??
'');
609 $bindNeed = $this->needBind(
$definition, $needKey);
612 return '<em>Uebersprungen</em>';
615 if ((
string)($bindNeed[
'type'] ??
'') ===
'dd_select') {
618 return $this->h($this->labelFromTemplate((
string)($bindNeed[
'label'] ??
'#{id}'), $record));
622 if ((
string)($bindNeed[
'type'] ??
'') ===
'dd_field_options') {
623 foreach ($this->optionsFromFdField(
$definition, (
string)($bindNeed[
'field'] ??
'')) as $opt) {
624 if ((
string)($opt[
'value'] ??
'') === (
string)
$value) {
625 return $this->h($opt[
'label']);
630 if ((
string)($bindNeed[
'type'] ??
'') ===
'static_select') {
631 foreach ((array)($bindNeed[
'options'] ?? array()) as $opt) {
632 if (is_array($opt) && (
string)($opt[
'value'] ??
'') === (
string)
$value) {
633 return $this->h($opt[
'label']);
641 private function finalStatusBox(
string $type,
string $title,
string $body,
string $extra =
''): string {
642 $icon =
'bi-info-circle';
643 if ($type ===
'success') $icon =
'bi-check2-circle';
644 if ($type ===
'warning') $icon =
'bi-exclamation-triangle';
645 if ($type ===
'danger') $icon =
'bi-x-circle';
646 return '<div class="alert alert-' . $this->h($type) .
' mb-3">'
647 .
'<div class="fw-semibold"><i class="bi ' . $icon .
'"></i> ' . $this->h($title) .
'</div>'
648 .
'<div>' . $this->h(
$body) .
'</div>'
653 private function genericFinalStatus(array
$definition,
string $instanceStatus,
int $completed,
int $total, array $missingLabels): string {
654 if ($missingLabels !== array()) {
655 return $this->finalStatusBox(
657 'Workflow noch nicht vollstaendig',
658 'Es fehlen noch Pflichtschritte: ' . implode(
', ', $missingLabels) .
'.'
662 if ($instanceStatus ===
'finished') {
663 return $this->finalStatusBox(
665 'Workflow komplett abgeschlossen',
666 'Alle notwendigen Schritte sind erledigt. Ergebnis: ' . (
string)(
$definition[
'result'] ??
$definition[
'title'] ??
'Workflow') .
'.'
670 return $this->finalStatusBox(
672 'Workflow bereit zum Abschluss',
673 'Alle notwendigen Schritte sind erledigt (' . $completed .
' von ' . $total .
'). Pruefe die Zusammenfassung und schliesse den Workflow ab.'
677 private function ebayFinalStatus(array $values,
string $instanceStatus,
int $completed,
int $total, array $missingLabels): string {
678 if ($missingLabels !== array()) {
679 return $this->finalStatusBox(
681 'eBay-Workflow noch nicht vollstaendig',
682 'Es fehlen noch Pflichtschritte: ' . implode(
', ', $missingLabels) .
'.'
686 $productId = (int)($values[
'product'] ?? 0);
687 if ($productId <= 0) {
688 return $this->finalStatusBox(
'warning',
'eBay-Status unklar',
'Es ist kein Artikel ausgewaehlt.');
691 $rows = $this->db()->select(
692 'dbxShop|shopProductChannel',
693 array(
'product_id' => $productId,
'channel_key' =>
'ebay'),
694 array(
'external_listing_id',
'external_offer_id',
'export_status',
'export_message',
'last_export_date'),
703 $listingId = trim((
string)($row[
'external_listing_id'] ??
''));
704 $offerId = trim((
string)($row[
'external_offer_id'] ??
''));
705 $status = strtolower(trim((
string)($row[
'export_status'] ??
'')));
706 $message = trim((
string)($row[
'export_message'] ??
''));
707 $lastExport = trim((
string)($row[
'last_export_date'] ??
''));
708 $manualCheck = (string)($values[
'status_check'] ??
'');
711 if ($status !==
'') $meta[] =
'Status: ' . $status;
712 if ($lastExport !==
'') $meta[] =
'Letzter Export: ' . $lastExport;
713 if ($offerId !==
'') $meta[] =
'Offer-ID: ' . $offerId;
714 if ($listingId !==
'') $meta[] =
'Listing-ID: ' . $listingId;
715 $extra = $meta ?
'<div class="small mt-2 text-muted">' . $this->h(implode(
' | ', $meta)) .
'</div>' :
'';
716 if ($message !==
'') {
717 $extra .=
'<div class="small mt-1">' . $this->h($message) .
'</div>';
719 if ($listingId !==
'') {
720 $url =
'https://www.ebay.de/itm/' . rawurlencode($listingId);
721 $extra .=
'<div class="mt-2"><a class="btn btn-outline-primary btn-sm dbx-win" href="' . $this->h(
$url) .
'" data-url="' . $this->h(
$url) .
'" data-title="eBay-Angebot ansehen" data-width="92%" data-height="90%"><i class="bi bi-box-arrow-up-right"></i> Bei eBay ansehen</a></div>';
724 if (in_array($status, array(
'failed',
'error'),
true)) {
725 return $this->finalStatusBox(
'danger',
'eBay-Veroeffentlichung fehlgeschlagen',
'Der Connector hat einen Fehler gemeldet. Bitte Mapping, Zugangsdaten und eBay-Rueckmeldung pruefen.', $extra);
728 if ($listingId !==
'' && in_array($status, array(
'published',
'exported',
'ready'),
true)) {
729 return $this->finalStatusBox(
'success',
'Artikel ist auf eBay veroeffentlicht',
'Der Export hat eine eBay Listing-ID geliefert. Der Workflow ist fachlich erfolgreich.', $extra);
732 if ($lastExport ===
'') {
733 return $this->finalStatusBox(
'warning',
'eBay-Export noch nicht ausgefuehrt',
'Der Workflow ist inhaltlich vorbereitet, aber es gibt noch keinen gespeicherten Exportlauf.', $extra);
736 if ($listingId ===
'') {
737 $text =
'Der Export wurde ausgefuehrt, aber es ist noch keine eBay Listing-ID gespeichert. Das kann bedeuten, dass die Plattform asynchron prueft oder die Rueckmeldung fehlt.';
738 if ($manualCheck ===
'error') {
739 $text =
'Der Workflow wurde mit Fehlerstatus geprueft. Bitte die Connector-Meldung und eBay-Daten korrigieren.';
741 return $this->finalStatusBox(
'warning',
'eBay-Rueckmeldung fehlt oder ist offen', $text, $extra);
744 return $this->finalStatusBox(
'info',
'eBay-Status pruefen',
'Alle Workflow-Schritte sind erledigt, der technische Status ist aber nicht eindeutig als veroeffentlicht markiert.', $extra);
747 public function renderFinalStatus(array
$definition, array $values,
string $instanceStatus,
int $completed,
int $total, array $missingLabels): string {
749 if ((
string)(
$definition[
'workflow_key'] ??
'') ===
'shop_ebay_publish') {
750 return $this->ebayFinalStatus($values, $instanceStatus, $completed, $total, $missingLabels);
752 return $this->genericFinalStatus(
$definition, $instanceStatus, $completed, $total, $missingLabels);
755 private function resolveToken(
$token, array
$definition, array $values, array $record) {
758 return date(
'Y-m-d H:i:s');
761 return (
int)
dbx()->user();
763 if (strpos(
$token,
'@need:') === 0) {
764 $needKey = substr(
$token, 6);
765 return $values[$needKey] ??
'';
767 if (array_key_exists(
$token, $values)) {
770 if (array_key_exists(
$token, $record)) {
777 private function resolveMap(array $map, array
$definition, array $values, array $record) {
779 foreach ($map as $dbField =>
$source) {
785 private function shopWorkflowFinish(array
$definition, array $values) {
786 $workflowKey = (string)(
$definition[
'workflow_key'] ??
'');
787 if ($workflowKey !==
'shop_article_publish' && $workflowKey !==
'shop_ebay_publish') {
791 $productId = (int)($values[
'product'] ?? 0);
792 if ($productId <= 0) {
793 return array(
'ok' => 0,
'message' =>
'Kein Artikel ausgewaehlt.');
796 if ($workflowKey ===
'shop_article_publish') {
797 $release = (string)($values[
'final_check'] ??
'');
798 if ($release ===
'draft') {
799 return array(
'ok' => 1,
'message' =>
'Artikel bleibt als Entwurf vorbereitet.');
802 $ok = $this->db()->update(
803 'dbxShop|shopProduct',
804 array(
'active' => 1,
'update_date' => date(
'Y-m-d H:i:s'),
'update_uid' => (
int)
dbx()->
user()),
805 array(
'id' => $productId,
'trash' => 0),
812 return array(
'ok' => 0,
'message' =>
'Artikel konnte nicht freigegeben werden.');
814 return array(
'ok' => 1,
'message' =>
'Artikel wurde im Shop freigegeben.');
817 $channelRows = $this->db()->select(
818 'dbxShop|shopProductChannel',
819 array(
'product_id' => $productId,
'channel_key' =>
'ebay'),
828 if (!is_array($channelRows)) {
829 return array(
'ok' => 0,
'message' =>
'Channel-Daten konnten nicht gelesen werden.');
831 $channelRow = (is_array($channelRows) && isset($channelRows[0])) ? $channelRows[0] : array();
832 if (trim((
string)($channelRow[
'last_export_date'] ??
'')) !==
'') {
833 $status = strtolower(trim((
string)($channelRow[
'export_status'] ??
'')));
834 $message = trim((
string)($channelRow[
'export_message'] ??
''));
835 $listingId = trim((
string)($channelRow[
'external_listing_id'] ??
''));
836 if (in_array($status, array(
'failed',
'error'),
true)) {
837 return array(
'ok' => 0,
'message' =>
'Der eBay-Export ist fehlgeschlagen' . ($message !==
'' ?
': ' . $message :
'.') );
839 if ($listingId ===
'' || !in_array($status, array(
'published',
'exported',
'ready'),
true)) {
840 return array(
'ok' => 0,
'message' =>
'Die eBay-Rückmeldung ist noch nicht eindeutig erfolgreich. Bitte Status und Listing-ID prüfen' . ($message !==
'' ?
': ' . $message :
'.') );
844 'message' =>
'eBay-Veröffentlichung bestätigt: ' . $status .
', Listing-ID ' . $listingId . ($message !==
'' ?
' - ' . $message :
'') .
'.'
850 'message' =>
'Der eBay-Export wurde noch nicht ausgeführt. Bitte im Schritt „Export durchführen“ bewusst veröffentlichen und anschließend die Connector-Rückmeldung prüfen.'
856 $shopResult = $this->shopWorkflowFinish(
$definition, $values);
857 if (is_array($shopResult)) {
861 $finish = (array)($this->bindConfig(
$definition)[
'finish'] ?? array());
862 if (!$finish || (
string)($finish[
'type'] ??
'') !==
'dd_update') {
867 $dd = trim((
string)($recordCfg[
'dd'] ??
''));
869 if (
$dd ===
'' || $rid <= 0) {
870 return array(
'ok' => 0,
'message' =>
'Kein Datensatz fuer den Abschluss ausgewaehlt.');
875 return array(
'ok' => 0,
'message' =>
'Datensatz #' . $rid .
' wurde nicht gefunden.');
878 $update = $this->resolveMap((array)($finish[
'map'] ?? array()),
$definition, $values, $record);
880 if (array_key_exists(
'reply_text', (array)($finish[
'map'] ?? array()))) {
881 $replyText = trim((
string)($update[
'reply_text'] ??
''));
882 if (strlen($replyText) < 2) {
883 return array(
'ok' => 0,
'message' =>
'Bitte eine Rueckmeldung mit mindestens 2 Zeichen erfassen.');
887 $ok = $this->db()->update(
$dd, $update, $rid);
889 return array(
'ok' => 0,
'message' =>
'Datensatz konnte nicht gespeichert werden.');
892 $message =
'Datensatz #' . $rid .
' wurde gespeichert.';
893 $mail = (array)($finish[
'mail'] ?? array());
896 $whenNeed = trim((
string)(
$mail[
'when_need'] ??
''));
897 $whenValue = (string)(
$mail[
'when_value'] ??
'1');
898 $send = ($whenNeed ===
'') || ((
string)($values[$whenNeed] ??
'') === $whenValue);
900 $configModul = trim((
string)(
$mail[
'config_modul'] ?? (
$definition[
'bind'][
'modul'] ??
'')));
901 $modeKey = trim((
string)(
$mail[
'mode_key'] ??
'reply_mode'));
902 if ($configModul !==
'' && $modeKey !==
'' && !$this->configHasPart($configModul, $modeKey,
'mail')) {
907 $toField = trim((
string)(
$mail[
'to_field'] ??
'email'));
908 $to = trim((
string)($record[$toField] ??
''));
910 $message .=
' E-Mail-Versand nicht moeglich (keine Adresse).';
912 $subjectTpl = (string)(
$mail[
'subject_tpl'] ??
'Antwort');
913 $subject = $this->labelFromTemplate($subjectTpl, array_merge($record, $update));
914 $bodyTpl = trim((
string)(
$mail[
'body_tpl'] ??
''));
916 foreach ((array)(
$mail[
'body_vars'] ?? array()) as $tplKey =>
$source) {
917 $bodyVars[$tplKey] = $this->h($this->resolveToken(
$source,
$definition, $values, $record));
919 $html = $bodyTpl !==
'' ? $this->tpl()->get_tpl($bodyTpl, $bodyVars) : nl2br($this->h((
string)($update[
'reply_text'] ??
'')));
921 $from = trim((
string)
dbx()->get_config($configModul,
'mail_from'));
922 $fromName = trim((
string)
dbx()->get_config($configModul,
'mail_from_name'));
923 $fromParam = ($from !==
'') ? array(
'email' => $from,
'name' => $fromName) :
'';
924 $options = array(
'text' => strip_tags(str_replace(
'<br />',
"\n",
$html)));
925 $profile = trim((
string)
dbx()->get_config($configModul,
'mail_profile'));
930 $mailOk =
dbx()->send_mail($fromParam, $to, $subject,
$html,
'html', array(),
$options);
932 $track = $this->resolveMap((array)(
$mail[
'track_fields'] ?? array()),
$definition, $values, $record);
934 $this->db()->update(
$dd, $track, $rid);
936 $message .=
' E-Mail wurde versendet.';
938 $message .=
' E-Mail-Versand fehlgeschlagen.';
944 return array(
'ok' => 1,
'message' => $message);