Zum 2024-01-01 hat One-DC Teile ihrer Dropshipping-Services abgeschaltet. Man kann immer noch Bestellungen dort per API aufgeben und diese direkt an seine Shopkunden senden, aber es gibt keine Feeds mit Produkten, Beständen und Preisen mehr. Der Sinne erschließt sich mir überhaupt nicht, da Dropshipping ja doch irgendwie weiterhin möglich ist und elektronische Katalogdaten auch für PIMs und Kassensysteme der Kunden wichtig ist. Hätte man den Versand an die Endkunden eingestellt würde ich es ja noch verstehen, aber so macht es für mich keinen Sinn. Falls jemand mehr Weiß oder eine Möglichkeit kennt Katalogdaten weiterhin zu erhalten, bitte sich per Email bei mir melden.
Import2Shop stellt deren Anbindung zu EDC auch ein und die Shops sitzen jetzt und versuchen möglichst schnell zu einem anderen Anbieter zu wechseln. Meine Plugins bleiben weiter online, erhalten aber keine Weiterentwicklung mehr und gelten ab sofort als EOL, wenn nicht sich doch noch was neues ergeben sollte.
Es gibt manchmal CustomFields in denen man Daten wie externe Ids, ein Import- oder Export-Datum oder ein einfaches Bool-Flag speichern möchte. Der normale Admin-Benutzer darf diese Daten gerne sehen sollte sie aber nicht ändern, weil er oder sie nicht das nötige Wissen über die internen Abläufe des Plugins hat, um genau zu wissen, welche Auswirkungen so eine Änderung hat.
Deswegen ist es gut so ein CustomField readonly zu machen und am Besten komplett zu disablen. Das ist über die config des CustomFields sehr einfach möglich. In der Manifest einer App kann dass leider schon wieder ganz anders sein, weil dort sowas nicht vorgesehen ist.
Nach einigen Hin und noch mehr Her, hat die Interspark Inc bestätigt, dass sie keine IPs der Interspark GmbH übernommen hat und somit auch nicht die IPs an den beiden Plugins besitzt. War am Ende sehr schnell feste gestellt und ich übernehme die Plugins nun wieder, da es ja sonst niemanden gibt, der Ansprüche erhebt. Die Lizenz wird auf die MIT/BSD Lizenz geändert und die GitLab Projekte werden öffentlich.
Während die Shopware 5 Version schon in mehreren Shops bewiesen hat, das sie funktioniert, steht bei der Shopware 6 Version noch aus, diese als production-ready zu deklarieren.
Sie hat die meisten Test gut gemeistert und sollte nun auch mit Shopware 6.5 funktionieren. Trotzdem steht noch aus diese in einer produktiven Umgebung über einige Tage laufen zulassen.
Builds und Releases wird es ab jetzt hier geben. Jeder der Interesse oder Bedarf hat kann sich die Plugins installieren oder auch gerne mit weiter entwickeln.
Eine App-Version des Plugins, um damit auch die Shopware 6 Cloud Version (SaaS) abzudecken ist bis jetzt nicht von mir geplant, außer jemand würde mir dafür 5000 EUR geben, weil der Aufwand wirklich groß ist. Es wäre eine vollständig eigenständige Software, die außerhalb von Shopware läuft und dort wo die DAL verwendet wird dann die Shopware API (mit Multi-Tenant usw) aufrufen würde.
die Art und Weise erinnert mich etwas wie ich damals bei meinen cJSv2-Framework die Controller an Elemente gebunden und initialisiert habe.. der default-Name der Init-Methode war da auch init.
Der DomAccess-Helper ist super und sollte man so verwenden. Über den kann man auch den QuerySelector nutzen und dass schützt hoffentlich davor, dass ein Haufen klassischer Webdesigner versuchen JQuery wieder da rein zu bringen. Der HttpClient ist auch nett aber man kann genau so gut direkt mit fetch() arbeiten, wenn man nicht unbedingt irgendwelche Steinzeit Browser supporten möchte. Aber besonder mag ich von den Helpern DeviceDetection.isTouchDevice() weil man damit einfach unterschieden kann ob man gerade ein Touch oder ein MouseEnter
Event nutzen muss.
Wenn man in der Storefront an einem eignem JavaScript-Plugin arbeitet ist es beim Debuggen, oft nervig, dass der JavaScript Code nicht direkt lesbar ist. Oft weiß man beim eigenen Code direkt was los ist, aber gerade wenn 3rd Party Plugins auch mit rein spielen, kommt man nicht drum herum sich Exceptions mit lesbaren Stacktrace anzeigen zu lassen.
Das ist zum Glück extrem einfach:
* Port 9998 aus dem Docker-Container durchleiten
* Dem SalesChannel in dem man entwickelt die Domain "localhost" zu ordnen
* das Script bin/watch-storefront.sh starten
Nun kann man localhost:9998 im Browser aufrufen. Der JavaScript Code ist lesbar und Änderungen werden sofort übernommen ohne dass man die Storefront neu bauen muss.
Etwas was bei Shopware 6 so komplett fehlt und wo ich schon mehrmals gehört habe, dass es Kunden/Benutzern Probleme macht, ist die Hauptvariante bei Shopware 6. Die Hauptvariante ist immer die Variante, die im Dialog beim Erzeugen der Varianten zuerst gewählt wurde. Es gibt danach keine Möglichkeit mehr es zu ändern.
An sich ist die Hauptvariante aber auch nur ein FK am Product. Man kann dort einfach eine andere Variante eintragen und schon hat man seine neue Hauptvariante. Also alles auf DB-Ebene sehr einfach.
Auch das in die Administration einbauen war dann relativ einfach. Man brauchte nur zusätzlich ein Repository und eine Criteria für Varianten (WHERE parent_id = ... ). Die Id kann man direkt per v-model setzen am Product.
Einfach mal die Meta-Description mit einem Prefix versehen, um kleinere SEO-Probleme zu beheben. Klingt einfach und führt schnell zur Verzweiflung. frontend/detail/header.tpl angepasst und es funktioniert nicht. Keywords ändern ist kein Problem nur die Meta-Description des Artikels will sich nicht ändern.
Lösung Wie man schnell vermutet wird die eigene Änderung überschrieben. Der Schuldige ist das SEO-Plugin und da muss man die index.tpl anpassen. Die Änderung kann z.B. so aussehen:
Gerade bei den Shopware Plugins war es wichtig, dass sich die Funktionsweise eines Plugins nicht einfach ändert. Ich hab erlebt was passieren kann, wenn sich bei einen Newsletter-Plugin in einer Minor-Version plötzlich das Verhalten änderte. Es wurden plötzlich alle Kunden mit Gruppe übertragen und nicht mehr nur die einer bestimmten Gruppe und weil niemand sich die Änderungen groß angesehen hat, bekamen plötzlich alle den Newsletter. Das war doof.
Kaum jemand liest den Changelog oder nur selektiv nach bestimmten Fixes. Wenn ich als Shopware-Betreiber einen Fix für ein Plugin brauche, habe ich meistens keine Zeit jedes Verhalten und jede Funktion des Plugins nochmal durch zu testen. Ich will nur mein Problem beheben und keine neuen bekommen. Jedes neue Feature muss also in den default Einstellungen erst einmal deaktiviert sein. Nur Fixes dürfen ungefragt greifen.
Funktionen im Beta-Stadium dürfen auch nicht aktivierbar sein, wenn sie nicht stable sind. Unfertiger-Code darf mit ausgeliefert werden, wenn es nicht anders geht! ABER er muss auch hart im Code deaktiviert sein. Oder auch im Build-Prozess aus der Config-XML auskommentiert werden. Da muss dann aber sichergestellt sein, dass geprüft wird, ob das Config-Value überhaupt gesetzt ist und wenn nicht, dass es als deaktiviert gilt.
Aber wenn es nicht zwingend nötig ist, sollte man unfertige Features nie mit ausliefern und per Feature-Flag deaktivieren. Am Ende wird es sicher noch mal überarbeitet und es funktioniert dann anders. Weglassen minimiert das Risiko auf Fehler und dass irgendwer es doch aktiviert und nutzt.
Fazit: Feature-Flags sind wichtig, aber nicht dafür da um unfertige Features mit ausliefern zu können (ein Feature pro Feature-Branch!!!!)
Jeder der ein Plugin verwendet, das viele Daten hin und her schaufelt und dieses auch immer protokolliert, kennt das Problem von zu großen Log-Files. Gerne hätte man schon immer Log-Files für bestimmte Anwendungsfälle geschrieben. Mit 5.6 ist es jetzt möglich wenigstens pro Plugin ein eigenes Log-File zu nutzen.
Was ich zur Plugin-Entwicklung mit Shopware 6 nach dem ersten Kennen lernen bei der Shopware AG am 1.7. zu sagen habe:
- Varianten sind nun Produkte mit Parent
- Ids in der Datenbank sind nun UUUIDs (ramsey/uuid) die binär in der DB gespeichert werden
- Ein Plugin definiert sich allein durch eine composer.json und den darin enthaltenen Typ shopware-platform-plugin (ersetzt die plugin.xml) und PSR-4 Namespace und Plugin-Class werden darin definiert
- die Metadaten zum Plugin sind in der composer.json unter extra - Changelog ist jetzte die CHANGELOG.md Datei und mit ISO-Lang Postfixes erhält man die verschiedenen Sprachen (soll wohl mal durch den Store ausgelesen werden können)
- ./bin/console plugin:create --create-config MySW6Plugin erstellt einen ein komplettes Plugin Skeleton mit Config-XML und passender composer.json
- src/Resources/views/ wird automatisch registriert (wenn man seine Views wo anders liegen hat kann man getViewPath überschreiben)
- in der Plugin-Config kann man card-Tags verwenden, um Blöcke zu bilden und alles besser strukturieren zu können
- man kann eigene Felder und View in die Plugin-Config einbringen, in dem man vor eine Vue-Component registriert hat und diese dort als <component name="MyComponent"/> angibt
- Plugin installieren: ./bin/console plugin:install --activate --clear-cache MySW6Plugin öfters ist ein refresh der Liste nötig und cache:clear sichert den liebgewonnen Workflow bei der Entwicklung mit Shopware :-)
- Es gibt kein Doctrine-ORM mehr sondern die eigene DAL die noch DBAL verwendet
- DAL ist so etwas wie ein halb fertiges ORM wo noch die Abstraktion wie Annotations fehlt und man deswegen die Beschreibung und Umwandlungen selbst per Hand vornehmen muss, so wie auch das Anlegen der DB-Tables
- Es gibt dort noch viel zu verbessern, aber das Grundgerüst funktioniert da schon sehr gut. Zu verbessern wäre z.B.: new IdField('id', 'id') auch als new IdField('id') schreiben zu können wenn DB-Column und Class-Field gleich bezeichnet sind
- die Field-Definition-Methode wird nur selten aufgerufen, deswegen kann man hier sonst auch eigene Lösungen wie CamelCase-Converter oder Annotion-Parser selbst integrieren
- Es gibt momentan immer 3 Klassen: Definition, Plain Old PHP Object und Collection (über @Method der eigenen Collection wird so etwas wie Generics versucht abzubilden... in Java wäre es nur List<MyEntity> list = ....)
- Es wir automatisch ein Repository für jede Entity erzeugt, das man mit Hilfe der service.xml injecten kann
- CLI, Subscriber, etc werden weiterhin über die service.xml verwaltet und implementieren nur andere Interfaces (sonst hat sich dort kaum was verändert)
- Es gibt keine Hooks mehr sondern nur noch Service-Decoration (wie die meisten wohl schon jetzt lieber verwendet haben) und eben die Events
- Es gibt mit der DAL ein Versions-Feld
- Änderungen an der Datenbank sollten über das Migration-System (Timestamp basiert) erledigt werden und nicht über die Lifecycle-Methoden des Plugins
- Es gibt Updates und destructive Update, die die Kompatibilität der DB zu älteren Plugin-Versionen zerstören. Beides kann getrennt ausgeführt werden (2 Phasen Update für Cluster-nodes)
- Die DAL unterstützt native Translated-Fields
- Extensions von Entities werden serialisiert in der DB gespeichert (ALTER TABLE, Extension, Serializer-Klasse, etc). Es gibt keine Attributes mehr.
- Gespeichert wird immer per Array (von Entity-Arrays) und es wird nicht das Object zum Speichern übergeben
- upsert (update or insert) ist da das neue merge - Der Cart hat nun LineItems, die wiederum Children haben können
- LineItems sind nun vollkommen unabhängig von Produkten, es gibt nur noch ein Type und Enrichment-Handler, die Namen und Preise für diesen Type an das Item ran dekorieren
- ... damit kann man verschiedene Bestell-Modi wie "kaufen" und "ausleihen" pro Produkt zusammen in einem Warenkorb abbilden
- Die API stellt automatisch generierte Swagger-Beschreibungen bereit
- Es gibt mehrere APIs so dass nicht nur Datenspflege bestrieben werden kann, sondern auch komplette Bestellprozesse damit abgebildet werden können (damit kann man Shopware als Backend-Lösung für In-App-Käufe oder POS-Systeme verwenden)
- Dadurch kann man Shopware auch headless verwenden (ohne Storefron und Admin, oder nur mit einem davon)
- ein Product aht ein SalesChannelProduct... man kann dort bestimmt auch eine Stock-Quantity hinzufügen und so einen Sales-Channel abhängigen Lagerbestand implementieren (Jeder POS auf einen Event oder in Disco könnte ein eigener Sales-Channel werden und dann kann man genau
monitoren wo Getränke oder Verbrauchsmaterial zu neige geht und reagieren bevor die Mitarbeiter überhaupt merkten, dass in 15min wohl die Strohhalme ausgehen werden)
Insgesamt macht Shopware 6 einen wirklich sauberen und durch dachten Eindruck. Nur die Migrations brauchen noch etwas und die DAL könnte gut einen weiteren Layer drum herum gebrauchen (ich wäre für Annotations an der Entity-Klasse)
Subscriber bei Shopware-Plugins sind immer so ein Problem. Sie nehmen Daten manipulieren diese und reichen sie an den nächsten Subscriber weiter. Wenn ein Subscriber in einen Fehler läuft und z.B. leere Daten in die Arguments zurück schreibt, ist am Ende alles kaputt und die Daten sind verloren gegangen. Das ist mir jetzt einmal passiert und deswegen, bin ich darauf umgeschrieben, dass Subscriber nur noch auf einer Kopie arbeiten
dürfen.
Sollte nun etwas schief gehen und die Daten verloren gehen, werden einfach die Ursprungsdaten weiter verwendet. Wenn nun zusätzliche Daten nicht dazu dekoriert werden, ist es zwar doof und man muss in das Log-File gucken, ob Fehler auftraten, aber der Ablauf funktioniert weiter und es kommen immer hin die Grunddaten weiter dort an wo sie hin sollen.
Gerade bei Exports oder Imports mit kritischen und unkritischen Daten zusammen, ist es immer besser wenigstens die kritischen Daten sicher zu haben als gar nichts zu haben. Unkritische Daten kann man meistens dann sogar per Hand nachpflegen.
Die Windeit-Software GmbH wird in der nächsten Zeit eine neue Version des Automatic XML-Export Shopware-Plugins veröffentlichen. Es hat nun die Version 2.0.0 erreicht und kann jetzt selbstständig per SCP XML-Dateien auf einen anderen Server laden.
Dafür muss die php-ssh2 Extension installiert sein, was unter Ubuntu sehr einfach geht:
sudo apt-get install php7.2-ssh2
Auf dem Ziel Server muss der Openssh-Server installiert sein.
Danach müssen nur noch die Verbindungsdaten eingegeben werden und der SCP-Upload aktiviert werden.
Ich habe ein älteres (letztes Jahr September) angefangenes aber nie fertig gewordenes Shopware Plugin nun bei GitHub hochgeladen, in der Hoffnung, dass noch jemand was damit anfangen kann. Es fügt z.B. ein zusätzliches Feld zum Product-Slider Emotion-Element hinzu und ändert das Template für bestimmte Artikel im Slider.
Da es zu dem Thema "Einkaufswelten Elemente selber bauen mit ExtJS" relativ wenig Hilfe bei Shopware gibt, habe ich mich mal wirklich mit [url=https://developers.shopware.com/developers-guide/custom-shopping-world-elements/#advanced:-adding-a-custom-emotion-component-in-extjs]Hilfe von dem Shopware eigenen Tutorial zu Einkaufswelten Elementen[/ur]) und vielen einzelnen Formus-Beiträgen da durch gekämpft. Ich mag ExtJS immer noch nicht, aber so langsam komme ich wenigstens mit den Components klar. Ist am Ende nicht so viel anders wie Swing oder SWT, nur wird in den Constructoren der Componenten die man erweitert sehr viel "Magic" gemacht auf die man angewiesen ist. Allein die Frage: wie bekomme ich ein einfaches kleines Text-Feld in das richtige FieldSet?
Elemente von Einkaufswelten sind ein wirklich nicht so einfaches Thema, wenn man die reine PHP-Schiene verlässt und mit ExtJS arbeitet. Aber diese Mischung im Vimoe-Element Beispiel finde ich jetzt auch nicht so wirklich toll. Felder hier, Stores da.. man sollte alles auf einen Blick haben und wenn man mit JavaScript arbeitet muss man das Plugin auch nicht öfters neu installieren sondern nur den Cache löschen und das Shopware-Backend neu laden.
Init-Methode einer einfachen kleinen GUI mit einem Feld zur Artikel-Auswahl:
initComponent: function() {
var me = this;
me.callParent(arguments);
Darin sieht man wie man einen eigenen Store mit AJAX-Backend definiert und diesen in der ComboBox verwendet, die man wiederum in den Element-Einstellungen anzeigt. Wenn man schon mal soweit ist, steht einen auf dem Weg zu Einkaufswelten mit eigenen Elementen in Shopware nicht mehr viel im Weg.
Einfach mal zwischen durch ein Proof-Of-Life des Shopware Plugin für Cashless-Payment und irgendwann geht es mit dem Shopware Plugin und dem Ganzen auch ganz sicher weiter!
Die RFID-Reader liegen zur Weiterentwicklung bereit.
In den letzten Wochen hat sich doch einiges beim meinem XML-Export Plugin getan. Langsam aber zielstrebig geht es in die Bereiche Dropshipping und Bestellung-Konsolidierung. Dadurch wird es zu einem wichtigen B2B-Baustein.
Mit der Version 0.4.1 ist nun viel mehr in dem Bereich möglich (Veröffentlichung folgt in den nächsten Tagen)
Als erstes Beispiel wie man das Plugin nicht nur dafür verwenden kann für das eigene ERP Bestellungen zu exportieren, habe ich hier erotikgrosshandel.de . Deren Schnittstellen-Doku ist ziemlich gut und sie haben ein sehr minimalistisches Format, so dass man relativ schnell zum Ziel kommt. Die Voraussetzung waren:
- Ein eigenes passendes XSLT-Template (nach deren Doku)
- Der ApiClient muss FORM-Data per Post senden können (nicht nur wie bisher JSON)
- CronJob und CLI-Command müssen den Push an eine API auslösen
- Das Model muss die Lieferanten spezifischen Bestellnummern der Artikel enthalten (Puchase-Preise kamen gleich mit dazu...)
Das ganze war dann eigentlich nur viel Kleinkram und der POST als FORM-Data. War also an sich relativ schnell umgesetzt und lies sich gut testen.
Eingestellt muss sein:
- Format: eigene XSLT-Transformation
- Den Pfad zur eigenen XSLT angeben (absoluter Pfad vom /-Root aus!)
- Export-Pfad ist nicht nötig, aber sollte man doch setzen, falls man als Kontrolle die XML-Daten doch selbst noch mal vorhalten möchte (auch hier der absolute Pfad)
- nie automatisch exportieren (nur per CLI, CronJob oder API), man sollte den CronJob verwenden
- CronJob soll nur Bestellungen mit dem Status 0 und 12 (offen und vollständig bezahlt) verarbeiten: "0,!1,!2,!3,!4,!5,!6,!7,!8,!9,!10,!11,12,!13,!14"
- nach dem Export auf Status 1 (in Bearbeitung) setzen
- Host und URL setzen für erotikgrosshandel.de
- Content-Feldname auf "data" ändern
- Post-Format auf "FORM" setzen, damit in "data" die XML-Daten zu finden sind
Damit sendet er per CLI oder CronJob alle 0+12 Bestellungen im Lieferanten eigenen XML-Format an deren Schnittstelle und setzt danach die Bestellung auf 1+12, damit sie beim nächsten Durchlauf kein weiteres mal übertragen wird.
Den CronJob auf 10min stellen und dann sollten alle 10 Minuten alle "offenen" Bestellungen an den Server übertragen.
Über XSLT-Dateien kann man in anderen Fällen natürlich dann auch andere Formate wie GS1 oder OCI implementieren. Um die Daten zu den anderen Systemen übertragen zu können stehen der API-Client, Emails, Abruf über die Shopware-API oder der Export als Datei (und dann Übertragung per FTP oder SCP) zur Verfügung.
In den nächsten Wochen steht bei mir auf dem Plan, Bestellungen konsolidieren zu können, so dass bei einem CronJob-Lauf alle 2h nicht alle Bestellungen einzeln übertragen werden müssen, sondern auch zusammen gefasst werden können, wenn die Bestellungen für den selben Empfänger vorgesehen sind.
Eines meiner Plugins hat jetzt eine Bronze-Zertifizierung. Das ist toll, dass besagt, das das Plugin öfters runter geladen und schon bewertet wurde. Wenn man das geschafft hat man die Zertifizierung aktivieren. Es soll viele Vorteile bringen und helfen das Plugin besser zu verkaufen.
Ich bin gespannt!
In der Zwischenzeit wird mehr Zeit in ein andere Projekt und das XML-Export Plugin investiert bzw. so viel Zeit wie der Garten einen gerade übrig lässt.
Die neue Version vom automatischen XML Order-Export, nutzt für openTrans2.1 XSLT und keinen PHP-Code mehr. Der Vorteil davon ist, dass so für jeden Anpassungen an der Ausgabe sehr viel einfacher werden. Man kopiert sich die vorhandene XSLT-Datei und kann die Kopie so anpassen wie man will. Im Plugin kann man die Datei dann angeben und diese anstelle der originalen XSLT-Datei verwenden.
Wenn man z.B. ein Attribute-Field zusätzlich als offiziellen openTRANS2.1 XML-Tag einbinden:
Auch wenn ich eigentlich gar keine Zeit dafür habe, habe ich doch noch mal ein paar Kleinigkeiten an dem Plugin gemacht.
Nun kann man auch nicht-nummerische Werte als Slider darstellen. Die Reihenfolge entspricht dann der der Werte im Backend.
Die checkLicence()-Methode prüft, ob ein Plugin eine gültige Lizenz hat oder nicht. Dafür wird wiederum das Licence-Manager Plugin verwendet. Shopware selbst rät eher davon ab dieses zu verwenden. Sie meinen, dass ein Kunde schon keine Raubkopie verwenden möchte und ungern von Updates abgeschnitten wird.
Bei einigen Plugins sind die Updates nun wirklich minimal umgesetzt. Mal ein paar kleine Schönheitsfixes.
Warum gehe ich lieber das Risiko ein, dass man eine Test-Version länger als gedacht verwendet als zu viel Sicherheit einzubauen?
- Weil ich selbst weiß, dass Test-Zeiträume oft zu gering sind.
- Weil ich die Sicherheitsmaßnahmen von Shopware für ausreichend halten
- Weil meine Plugins im Namespace abzuändern. von der Arbeitszeit oft teurer wäre als es zu kaufen
- Weil ich nicht nur Fixes in Updates habe, sondern Updates bei mir oft auch Features nachliefern oder verbessern (erste Versionen waren oft nicht ansatzweise so umfangreich wie die momentanen Versionen)
Es ist wie mit dem Wasserzeichen auf mp4togif.com. Es nervt und man kann es relativ einfach und ohne viel Einschränkungen entfernen. Meine Plugins sind relativ günstig. Bekommen oft neue Features und ich versuche möglichst guten Support zu leisten.
Sollte sich nichts mehr verkaufen, würde ich auch nicht mehr weiter entwickeln.
Da das Preis/Leistung Verhältnis bei meinen Plugins, glaube ich, stimmt, bin ich auch relativ sicher, dass die Shopbetreiber bereit sind das Geld zu zahlen und weiterhin von der Weiterentwicklung partizipieren zu können. Besonders auch weil ich für jeden Verbesserungsvorschlag dankbar bin und diese auch gerne für Kunden umsetze.
PS: bald veröffentliche ich mal wieder eine aoop-Version, da dort in den letzten Tagen nach langer Zeit wieder mal was passiert ist und ein neues Projekt damit ansteht.. und nicht mit WordPress.. weil das zu unflexibel ist für den Zweck :-)
Es hat doch ein paar Tage länger gedauert, als gedacht und ich habe am Ende doch mehr geändert als ich zu Anfang wollte, aber ich habe bei dem Plugin jetzt ein besseres Gefühl als vorher. Es ist moderner und flexibler als die alte Version. Änderungen gehen auch viel schneller.
An openTRANS 1.0 hat sich garnichts geändert und wird wohl demnächst mal auf XSLT umgestellt. Bei openTRANS 2.1 hat sich mehr geändert. Zuvor fehlende Felder sind hinzu gekommen. Datum und Zeit der Bestellung ist nun getrennt vom Datum der Erzeugung des Dokuments.
Und das Wichtigste, was hinzu kam, ist, dass nun auch Updates auf Bestellungen exportiert werden. Der UDX.EDI-Block enthält dann die Information, ob es sich um ein CREATE UPDATE handelt. Wer den Export in eine Datei schreibt oder den Push-Client verwendet bekommt jetzt diese Informationen geliefert. Dateien haben nun einen Timestamp im Namen, so dass alle Änderungen linear exportiert werden können.
Wer eine alte Version verwendet sollte nicht einfach updaten, sondern erst einmal ausgiebig Testen!
Wie schon gesagt, habe ich bei dem Plugin jetzt ein wirklich gutes Gefühl.
Version 0.3.1 sollte demnächst im Store verfügbar sein.
Ich wollte ja das Order-Export in Richtung XSLT bearbeiten... nun wird alle sehr vollständige Überarbeitung daraus. Besseres Export verhalten nach Änderungen an Bestellungen.. auf über das Backend. Insgesamt soll alles etwas flexibler werden und für mehr B2B-Anwendungsfälle passend gemacht werden.
Andere Projekte gehen auch nicht so wirklich weiter. Das Cashless-Paymentsystem ist erst einmal auf HOLD. Ich habe zwar schon fertige Pläne, um es auch als ganz normale Kasse (mit Barcode-Scanner) nutzen zu können und auch die Bons dokumenten-echt als signierte PDF parallel zum Druck speichern zu können.
Auch wollte ich mal eine wirkliche Präsentation (vielleicht mit Video) dafür basteln. Am Ende könnte ich mit wenig Zeit noch ein gutes und fertiges Produkt daraus machen. Leider fehlt die Zeit oder das Geld um bei der Zeit das Projekt neu zu priorisieren.
Aber erst einmal steht auch wieder Bremen am 30.6. an. Diesmal bewaffnet mit unter anderen 2 ThinkPad T500 für echt wenig Geld (Die sind für mich da auch Verbrauchsmaterial.. bei höheren Stückzahlen einfach mal wegen dem Preis direkt anfragen. Auch wegen den passenden Akkus und WLAN-Karten dazu).
Im Hintergrund bei der Artikelseite läuft mein "Eigenschaften im Listing" Plugin als Dataprovider ohne eigene Ausgabe.
Bis jetzt konnte das Plugin neben dem Shopware-Model als XML auch openTRANS 1.0 und 2.1 exportieren. Das war aber rein in PHP implementiert. Zusätzlich konnte man eigene XML-Formate über XSLT ausgeben.
Nun werde ich nach und nach den PHP Anteil reduzieren und auch openTRANS in XSLT implementieren. Erste Schritte sind getan.
Ich rechne damit dass ich so in 2 Wochen, dann alles so weit auf XSLT migriert haben werde.
Landingpages und Hersteller in der Suche: Man kann die beiden Resultsets anhand der Sortierung gemischt darstellen und nicht mehr nur Hersteller hinter oder vor den Landingpages. Auch funktionieren die keyup und keydown JavaScript-Events wieder, wie sie sollen.
Eigenschaften im Listing: Hat nun auch eine Sortiernug bekommen und befindet sich momentan in den letzten Tests.
Globale Kundendaten: "{$customer_is_newsletter_receiver}" ist dazu bekommen. Damit kann gezielter den Newsletter bewerben und man schlägt ihm nicht jemanden vor, der ihn schon abonniert hat.
Prozentzahlen im Discout-Badge: Hat verschiedene Rundungsmethoden und die Ausgabe das Dezimalzahl erhalten.
Automatischer XML Order-Export: Prüfung ob das Zielverzeichnis überhaupt für Shopware schreibbar ist. Befindet sich noch im Test.
Eigenschaften im Listing: Version 1.8 wurde released. Fixes für Sprachshops und eine hübschere Tabellen-Darstellung ist nun enthalten. Sieht im Listing gerade bei der 1-spaltigen Darstellung ganz gut aus.
Rabatt in echten Zahlen: Das Plugin habe ich einfach dazwischen geschoben, weil ich wissen wollte ob es einfach zu realisieren ist und mir die Idee gefiel. Im Store wohl dann ab morgen oder übermorgen.
- Die Suche nach Herstellern (Banner oder Logo)
- Darstellung in einem Grid, um mehrere Banner noch übersichtlicher darstellen zu können (CSS3-Grid)
- Sortierung der Banner kann beeinflusst werden
Mit Videos ganz oben und der Grid-Ansicht, kann man echt hübsche Dinge damit bauen.
Von einer Integration einer Suche für statischen Seiten, Blog-Artikel und Kategorien sehe ich momentan ab, da ich die Suche eher als Marketing-Werkzeug sehe als allgemeine Suche für Kunden-Angelegenheiten. Mit Produkten, Landingpages (kann man ja wie eine Kategorie verwenden) und Herstellern kann man verkaufen. Mit Blog.. naja.. irgendwie auch. Statische Seiten sind Hilfen und Informationen, die man braucht, wenn schon das Kaufinteresse da ist und da hilft dann auch ein strukturiertes Menü und ein guter Footer ( mit Strg + F).
So langsam wird aus dem Prototypen ein fertiges Plugin, dass für den Einsatz in der realen Welt genutzt werden kann. Aber wofür kann man selbst ein Cashless Payment System, also ein System wo man nicht direkt mit Geld bezahlt sondern mit einem vorhanden oder später auszugleichenden Guthaben bezahlen kann, nutzen. Für wenn ist es interessant?
Events (Wegwerfkarten aus Pappe + 13,56 kHz RFID-Tag): Wer events organisiert kennt sicher schon Verzehrkarten und ähnliche Systeme. Man kauft sich am Eingang beim Bezahlen des Eintritts eine Karte für den Erwerb von Getränken. Jedes mal wenn man etwas Kauft wird der Preis vom vorhanden Guthaben abgezogen. Wenn man dann kein Guthaben mehr hat bekommt man nichts mehr und muss neu aufladen. Wer das Event verlässt und nicht alles ausgegeben hat, lässt das Guthaben verfallen.
Der Vorteil mit so einem System ist, dass die Mitarbeiter an der Bar nicht rechnen oder mit Bargeld rumhantieren müssen. Es kommt zu weniger Fehlern und es geht alles etwas schneller. Das Bargeld wird an zentraler Stelle behalten und es gibt keine Wechselgeldprobleme.
Wenn es um einzelne Events geht, wäre es sehr aufwendig und teuer für jedes Event ausreichend (also lieber immer zu viele) RFID-Karten bedrucken zu lassen. Hier gibt es als einfache Lösung RFID-Tags.
Also einfache Aufkleber, die auf eine Papier-Karte geklebt werden können. Man lässt sich also nur einfache Karten drucken und klebt die Tags beim Kauf rauf. Spart viele Kosten und die Karten und Tags halten einen Tag ohne Probleme durch.
RFID-Tags zum Aufkleben
Eine einfache Papier-Karte *...
... jetzt mit RFID-Tag kompatibel zu unserem System
Unser Cashless Payment System in Stichworten:
- keine lokalen Server da alles in der Cloud laufen kann
- kostengünstiges Mieten oder selber bauen von Kassen-Terminals
- erspart das Handtieren mit Bargeld und EC-Karten an den POS's
- Prepaid- und Nachträglich-Bezahlen Verfahren werden unterstützt
- Bedienung rein über Touchscreen (aber auch Maus und Tastatur wenn es vorzieht)
- Unterstützt 13,56kHz/125mHz RFID Technik und Barcodes (Code128/ QR) mit den jeweiligen USB-Readern
- Bon-Druck auf Thermo-, Tintenstrahl- oder Laserdrucker
- Unterschiedliche Kundengruppen mit entsprechenden Auswertungen von Verkäufen
- eine einfache Bestandsführung und automatische Sperrung von Produkten ohne Bestand
- Vereinfachte Bedienung durch Topseller und selbst gestaltbarer Seiten
- Professionelles und bewertes Shopware-System als Kern unserer Anwendung
Ich bin ja nur Entwickler und kenne mich mit Marketing an sich gar nicht aus. Es würde meinen Projekten und Shopware-Plugins sicher gut tun, wenn ich mich mal etwas mehr damit beschäftigen wurde.. was ich mir gerade auch mal wieder mehr vorgenommen.. gerade jetzt! :-)
Ich hab ein paar für mich relativ interessante Artikel gefunden, die ich einfach mal hier teilen will.
Das hier ist wohl der für mich wichtigste Artikel. Gebe deinen Kunden immer einen Grund, warum das Produkt/Plugin zu ihnen passt. Das fehlt wirklich oft genug. Ich habe teilweise schon kleine Anwendungsbeispiele geliefert, aber etwas ausführlichere Use-Cases könnten da wirklich helfen.
Auch ganz gut um eine allgemeine Übersicht zu bekommen (und mit leichten Erinnerungen an Simple Programmer Blog-Artikel) fand ich diesen Artikel ganz gut. Der Hauptton darin ist grob: Das Hauptproblem ist nicht einen Uplift zu erreichen sondern die Mittel dafür zubekommen. Und das im SEO-Bereich hoch geachtete Bauchgefühl wird hier als nett aber nicht-ziel-bringend in einem realistischen Kontext dargestellt. Schaf dir deine Werkzeuge, mach Big Data und liefer belegbare Zahlen aus validierten Test-Szenarien.
Am Ende soll man sein eigenes Team und ein besseres Gehalt haben.. ach ja .. das die Firma mehr verkauft fällt nebenbei auch noch ab.
Das klassische Problem, dass man sich selber anders sieht als andere einen sehen.. Zielgruppen.. Ich glaube eine Zielgruppe gefunden zu haben, aber sieht sich die Gruppe selbst als Zielgruppe oder passt eine andere besser?
Der nächste Artikel erinnert mich an die Neuauflage der 80er Jahre Turtles Actionfiguren.. sie waren sofort weg.. wohl nicht weil die jetzt besonders hochwertig waren oder eine große Zielgruppe angesprochen haben.. es gab einfach nur wenige und deswegen wurde geglaubt sie wären wertvoll und eine gut Investition.
Da hab ich sogar ein Plugin, dass in die Richtung geht und die erzählt dass "nur noch" so und so viele Artikel vorhanden sind und es danach entweder keine mehr oder nur mit sehr langen Lieferzeiten gibt. Also besser jetzt kaufen, weil wenig da ist, deswegen ist es wertvoll und genau deswegen werden alle anderen es dir weg kaufen.
Hier wird einmal angesprochen, dass man Daten vor der Analyse immer prüfen sollte. Wenn man nicht weiß, dass die Daten richtig sind, lohnt sich eine Analyse damit eh nicht.
Hier auch einmal das Beispiel, das Menschen bei einer Frage nach ihrer Meinung oft nur das antworten, von dem sie glauben, dass der Fragende dieses hören will. Klassisch: "Was halten Sie von der politischen Entscheidung XXXXXXXXX?" - "Ich bin total dagegen. Sowas kann man einfach nicht so machen... " *Pause* ".. war die Antwort richtig?". In dem Artikel am Beispiel von Coca Cola und Pepsi und der glaube, dass man Coca Cola besser finden müsse.
Mich nervt es immer, wenn ich in einem beliebigen Shop bin und bei "NEW IN" gucke und merke, dass immer noch nichts neues da ist. Eine einfache Anzahl der Artikel in der Kategorie würde mir da schon sehr helfen, da ich direkt sehen kann ob sich da was getan hat.
Shopware bietet zwar ein Beispiel an, aber dieses Beispiel hat mich doch zu viel Zeit gekostet, bis es lief und die dort verlinkte ZIP-Datei ist leider auch nicht fehlerfrei. Deswegen habe ich mich mal daran gemacht eine eigene einfachere Beispiel Implementierung zu bauen, die als Vorlage mit viel Copy&Paste dienen kann.
public function onRiskManagementBackend(\Enlight_Controller_ActionEventArgs $args){
$args->getSubject()->View()->addTemplateDir($this->getPath() . '/Resources/views');
An sich macht man nichts anderes als eine JSON Key-Value Liste zu erweitern und dort ein Event einzutragen, das eine Methode auslöst, die true (is a risk) oder false (is not a risk) zurück gibt. Diese Methode sollte nur als Facade für einen Service dienen, damit man die Logik schnell und einfach austauschen kann.
Das Plugin kann man dann eben noch um alles mögliche erweitern, wie Freitextfedler für Kunden und weitere Templates. Dann den Serive vollständig implementieren, nochmal was mit dem Snippet machen und man sollte seine RiskManagement-Rule haben.
Nachdem ich schon mal einen RangeSlider für Artikel-Eigenschaften implementiert hatte, habe ich für mich noch mal neu angefangen. Meine Version ist einfacher, hat weniger Funktionen und weniger für integrative Szenarien gedacht. Dafür einfach zu bedienen und unterstützt eine "linear" und eine "log" Darstellung.
Hier sieht man die Unterschiede, wenn man mehr Werte im 1-2 stelligen Bereich hat und nur wenige im 4 stelligen Bereich.
linear
log
Die Config auf Option-Ebene zu bekommen, steht jetzt als nächstes an. Options hätten als Auswahl "global","linear" und "log". Die Einstellung direkt im Plugin wäre die globale Einstellung.
Mit etwas Glück ist das Plugin am Ende der Woche dann bei Shopware im Store.
Es war ein kalter und nasser November morgen. Ich saß zu der Zeit in einem ehemaligen Fabrikgebäude im tiefsten Osten Deutschlands mehrere Fahrtminuten hinter Lübeck.
Meine Aufgabe sollte es da sein ein Konzept für das Beschaffungsmodul eines ERP-Systems zu konzeptionieren. Ich stand gerade vor dem Problem, dass z.B. bei Wareneingängen, die über das Modul verbucht werden sollten, auch das Lager-Modul und das Inventur-Modul diesen Eingang verarbeiten mussten. Ich überlegte und entschied mich am Ende für ein auf MDB basierten Event-Model. Wenn etwas passierte sollte ein Event/eine Message los laufen und andere Module sollten, dieses bei Interesse nehmen, zur Kenntnis nehmen oder auch Daten anpassen können. Man war felxibel, hatte keine Abhängigkeiten und alles war erweiterbar und austauschbar. Ich war schon halb dabei was konkretes zu entwickeln... wie man sich sicher jetzt schon denken kann, kam es nie dazu. EJBs wurden direkt aufgerufen mit allen Problemen, die ich mit den Events umgehen wollte.
Ob es nun Fire-And-Forget, synchron oder asynchron, MDB-basiert oder was auch immer gewesen wäre, es wäre besser gewesen als alle benötigten fremden Services per Hand direkt aufzurufen und denen die Daten in deren Formaten aufbereitet zu übergeben. Jede Änderung an den fremden Services, die es zuhauf gab, konnte wieder alles kaputt machen und das passierte natürlich häufig, besonders weil Service-Interfaces beliebig geändert wurden und nie stabile Schnittstellen zwischen den Modulen waren.
Es war ein Fehler es nicht so zu machen, deswegen liebe ich alles was genau so arbeitet. Jetzt habe ich auch angefangen bei einigen meiner Shopware-Plugins Events einzubauen, so dass diese auch teilweise erweitert werden können. Das Preis-Warnung-Plugin ist das erste, das Events erhalten wird. Bei Shopware ist es an sich sehr einfach mit Events zu arbeiten. Als Beispiel nehmen wir uns einen einfachen Service.
namespace HPrEventTest\Components;
class EventService{
/** @var \Enlight_Event_EventManager */
private $eventManager;
public function __construct(\Enlight_Event_EventManager $eventManager = null){
$this->eventManager = $eventManager;
}
public function fireExample(){
$val = 0;
$result = $this->eventManager->filter('HPrEventTest_example', $val, ['subject' => $this]);
return $result;
}
}
Wir müssen nur noch den Event-Manager per Injection zum Service hinzufügen.
Wie man auf Events reagiert, weiß eigentlich jeder, der schon mal ein Shopware-Plugin geschrieben. Allein der Klassiker zum hinzufügen von Template-Dirs erklärt schon fast alles.
namespace HPrEventTest;
use Shopware\Components\Plugin;
class HPrEventTest extends Plugin{
public static function getSubscribedEvents(){
return [
'HPrEventTest_example' => 'processEvent',
];
}
public function processEvent(\Enlight_Event_EventArgs $args){
$args->setReturn($args->getReturn() + 1);
}
}
Wir feuern also ein Event mit 0, das wird in unseren Plugin verarbeitet und 0 wird zu 1 und diese 1 wird von der ursprünglichen Service-Methode auch dann wieder zurück gegeben.
Es gibt natürlich noch ein paar mehr Event-Strategien als filter(), aber an sich sind alle sehr ähnlich. Nicht bei jedem wird der Return-Wert verwendet.
Das Subject, das wir hier verwenden, eignet sich super dafür Controller und Services zu übergeben, die das Event ausgelöst haben.
So langsam wird aus dem Prototypen, ein echtes und brauchbares Produkt. Auch wenn der Realworld-Test heute leider ausgefallen ist, hat das Plugin wichtige neue Funktionen bekommen:
- Direktes Anlegen eines Kunden beim ersten Login-Versuch (dann muss man bei 4000 Karten nicht 4000 Kunden anlegen sondern, kann direkt loslegen)
- Vorgegebene Freitext-Felder, dadurch muss man weniger konfigurieren und weniger Fehlerquellen
Zusätzlich:
- viele Fixes
- Drucken von Kassenbons ist zu 50% fertig. Ein Thermodrucker zum testen ist bestellt.. und hilft vielleicht bei der Kassenschubladen-Problematik
- 13,6mHz Tags zum Aufkleben und ein passendes Lesegerät sind auch bestellt... damit kann man einfache Eintrittskarten zu Bezahlkarten machen
Es geht also alles in schnellen Schritten voran und ich hoffe, dass es dann schon bald als Cloud-Service für alle verfügbar sein wird.
Blog-entries by search-pattern/Tags:
Möchtest Du AdSense-Werbung erlauben und mir damit helfen die laufenden Kosten des Blogs tragen zu können?