View Issue Details

IDProjectCategoryView StatusLast Update
0000686FakturamaKontakte (Contacts)public2019-02-18 20:52
ReporterLastBoyScoutAssigned Torheydenr 
PriorityurgentSeveritymajorReproducibilityalways
Status assignedResolutionopen 
Product Version2.0.1 
Target VersionFixed in Version 
Summary0000686: Datenbankinkonsistenz - Leere Datensätze und mögl. Datensätze mit verlorenem Bezug
Description

Aufgrund der momentanen Datenbankstruktur kommt es leider mindestens bei den Kontakten und Adressen zu Inkonsistenzen und Datenbankleichen... Siehe hierzu den Forenbeitrag unter: https://forum.fakturama.info/read.php?2,11778

Nachfolgend daher nochmal mein detaillierter Vorschlag:

In der Tabelle fkt_contact sollten wirklich nur die einmaligen Daten enthalten sein und es sollte zu jedem Kreditor / Debitor auch nur einen einzigen Eintrag geben. Die Datenfelder zu denen auch mehrere Einträge existieren können, sollten hingegen in fkt_address bzw. fkt_bankaccount abgelegt werden, wo es dann auch jeweils mehrere bzw. sogar beliebig viele Einträge je Kreditor / Debitor geben kann.
Um die Relation zwischen diesen beiden Tabellen herzustellen, sollten die Fremdkeys in Hilfstabellen fkt_contact2address und fkt_contact2bankaccount gepflegt werden. In diesen Hilfstabellen ist dann auch noch die Art der Beziehung (Rechnungsanschrift, Lieferanschrift usw.) zu definiert. Zur Deklaration empfehle ich hierfür ein Bitmuster anstatt eines reinen Zahlenwertes. So kann auf elegante Art etwa eine Adresse auch mehreren Belegarten zugeordnet werden. Damit lässt sich einer einzelne Adresse für alles Nutzen [1111], eine zusätzliche Lieferadresse definieren [0010], oder aber auch Komplexe Strukturen für Firmen mit mehreren Standorten und entsprechend abweichenden Angebots, Auftrags und Lieferadressen abbilden.
Da man einen Brief ja ggf. an jede der hinterlegten Adressen senden können muss, braucht hierfür keinen eigenes Bit berücksichtigt werden. Eine Adresse mit [0000] wäre dann quasi nur zur Korrespondenz bestimmt.

Sofern ein Kontakt oder eine bestimmte Adresse nicht gelöscht sondern nur gesperrt werden soll, kann in den Tabellen ein Bitwert BLOCKED auf 1 gesetzt werden. Dieser Kontakt oder auch nur die betreffende Adresse oder Bankverbindung ist dann ausgegraut und nicht verwendbar.
Um diese danach evtl. Löschen zu können, sollte erst wieder deren Freigabe erfolgen. Dies wäre von Vorteil, um in Hinblick auf zukünftig geplante Nutzerprofile später auch entsprechende Rechte zuweisen zu können.

Innerhalb von Fakturama sollte die Maske dann wie bereits von Ralf Vorgeschlagen (siehe Anhang, jedoch noch erweitert um Telefonnummern, Mailadresse usw.) umgesetzt werden.
Die Auswahl der zuzuordnenden Belegart/en (oder Transaktionsart/en bei den Bankverbindungen) könnte beispielsweise über eine Dropdown-Liste erfolgen, in der eine Mehrfachauswahl möglich ist.
Sofern zu einem Kontakt mehr als eine Adresse für eine Belegart hinterlegt ist, müssten diese im Auswahldialog der Kontakte alle mit aufgelistet werden, oder/und müsste es eine zusätzliche Auswahlmöglichkeit im jeweiligen Adressfenster (z.B. Dropdown-Liste oder Pfeiltasten zum Durchblättern) geben.

Als Anhang (Zusätzliche Informationen) nun nochmal die Umsetzung mit InnoDB als Engine. Hier werden bei einem evtl. Update eines Datensatz die entsprechenden Bezüge in der Hilfstabelle automatisch mit aktualisiert. Wird eine Adresse oder Bankverbindung gelöscht, wird automatisch auch gleich der entsprechende Bezugsdatensatz zum Kontakt entfernt. Und wenn ein Kontakt gelöscht wird, werden neben all seinen Bezügen auch gleich die dazugehörigen Adressen und Bankverbindungen entfernt. So kann es weder zu falschen Beziehungen noch zu Karteileichen kommen. Das ganze erfolgt dann direkt über die DB, Fakturama muss sich nicht darum kümmern.

Steps To Reproduce

Bislang sind in fkt_address ja eigentlich nur Straße, PLZ, Ort und Land hinterlegt, die dazugehörigen Namen werden aber weiterhin in fkt_contact abgelegt. Dies hat dann natürlich unschöner Weise zur folge das zu jeder Lieferanschrift auch ein weiterer Kontakteintrag angelegt werden muss, nur um Namen und Fremdkey der Adresse zu hinterlegen. Eigentlich soll doch aber nur eine abweichende Lieferanschrift gespeichert werden und nicht auch noch ein alternativer Kontakt bei dem zu allem Übel auch noch alle übrigen Felder leer oder ungenutzt (z.B. Telefonnummern usw.) bleiben.

Entfernt man in Fakturama bei einem Kontakt das Häkchen bei "Abweichende Lieferanschrift", geht nur der Bezug FK_ALTERNATECONTACT verloren und in der DB bleiben gleich zwei Karteileichen zurück (zumindest in mySQL).
Auf diese Daten kann dann über Fakturama nicht mehr zugegriffen und auch der Bezug leider nicht wieder hergestellt werden.
Wird das Häkchen erneut gesetzt, wird in jeder der beiden Tabellen wieder ein neuer Datensatz angelegt. In diesem Fall sind es nun also bereits sechs Datensätze für einen Kunden mit abweichender Lieferanschrift (kann aber auch sehr schnell noch mehr werden).

Bei den Bankdaten wird ebenfalls zu jedem Kontakt ein Datenbankeintrag erstellt, auch wenn in den Feldern keine Daten eingetragen werden. Daher kommt es auch hier zu Leeren Datensätzen.

Additional Information
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;

-- Neue Struktur der Tabelle fkt_address
CREATE TABLE IF NOT EXISTS `fkt_address` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `COMPANY` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `GENDER` int(11) DEFAULT NULL,
  `TITLE` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `FIRSTNAME` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `NAME` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `STREET` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `ZIP` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `CITY` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `CITYADDON` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `COUNTRYCODE` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `BIRTHDAY` date DEFAULT NULL,
  `PHONE` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '1. Telefonnummer z.B. Privat oder Telefonzentrale',
  `PHONE2` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Zusätzliche Telefonnummer z.B. Beruflich oder Durchwahl',
  `FAX` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `MOBILE` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `EMAIL` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '1. Mailadresse z.B. info@firma.de oder auch buchhaltung@firma.de',
  `EMAIL2` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Zusätzliche Mailadresse z.B. ansprechpartner@firma.de',
  `WEBSITE` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Verschoben aus fkt_contact',
  `MANUALADDRESS` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
  `DATEADDED` date DEFAULT NULL,
  `MODIFIED` date DEFAULT NULL,
  `MODIFIEDBY` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `BLOCKED` bit(1) DEFAULT b'0' COMMENT 'Anstatt DELETED, wass gem. DSGVO ja dann auch tatsächlich geschehen muss',
  `VALIDFROM` date DEFAULT NULL,
  `VALIDTO` date DEFAULT NULL,
  `FK_CONTACT2ADDRESS` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `FK_CONTACT2ADDRESS` (`FK_CONTACT2ADDRESS`),
  CONSTRAINT `FK_ADDRESS_2_CONTACT` FOREIGN KEY (`FK_CONTACT2ADDRESS`) REFERENCES `fkt_contact2address` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Tabelle mit n Adressen je Kreditor / Debitor';

-- Neue Struktur der Tabelle fkt_bankaccount
CREATE TABLE IF NOT EXISTS `fkt_bankaccount` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `ACCOUNTHOLDER` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `ACCOUNT` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Alte Bezeichnung NAME',
  `IBAN` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `BANKNAME` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `BIC` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `BANKCODE` int(11) DEFAULT NULL,
  `MANDATEREFERENCE` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `DATEADDED` date DEFAULT NULL,
  `MODIFIED` date DEFAULT NULL,
  `MODIFIEDBY` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `BLOCKED` bit(1) DEFAULT b'0' COMMENT 'Anstatt DELETED, wass gem. DSGVO ja dann auch tatsächlich geschehen muss',
  `VALIDFROM` date DEFAULT NULL,
  `VALIDTO` date DEFAULT NULL,
  `FK_CONTACT2BANKACCOUNT` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `FK_CONTACT2BANKACCOUNT` (`FK_CONTACT2BANKACCOUNT`),
  CONSTRAINT `FK_BANKACCOUNT_2_CONTACT` FOREIGN KEY (`FK_CONTACT2BANKACCOUNT`) REFERENCES `fkt_contact2bankaccount` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Tabelle mit n Bankdaten je Kreditor / Debitor';

-- Neue Struktur der Tabelle fkt_contact
CREATE TABLE IF NOT EXISTS `fkt_contact` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `DTYPE` varchar(31) COLLATE utf8_unicode_ci DEFAULT NULL,
  `CONTACTTYPE` int(11) DEFAULT NULL,
  `CUSTOMERNUMBER` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `MATCHCODE` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Bezeichnung z.B. 1. Zeile des Firmennamen oder Nachname Vorname',
  `SUPPLIERNUMBER` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `GLN` bigint(20) DEFAULT NULL,
  `NOTE` text COLLATE utf8_unicode_ci,
  `DISCOUNT` double DEFAULT NULL,
  `RELIABILITY` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `VATNUMBER` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `VATNUMBERVALID` bit(1) DEFAULT b'0',
  `USENETGROSS` smallint(6) DEFAULT NULL,
  `USESALESEQUALIZATIONTAX` bit(1) DEFAULT b'0',
  `WEBSHOPNAME` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `DATEADDED` date DEFAULT NULL,
  `MODIFIED` date DEFAULT NULL,
  `MODIFIEDBY` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `BLOCKED` bit(1) DEFAULT b'0' COMMENT 'Anstatt DELETED, wass gem. DSGVO ja dann auch tatsächlich geschehen muss',
  `VALIDFROM` date DEFAULT NULL,
  `VALIDTO` date DEFAULT NULL,
  `FK_CATEGORY` bigint(20) DEFAULT NULL,
  `FK_PAYMENT` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `FK_FKT_CONTACT_FK_CATEGORY` (`FK_CATEGORY`),
  KEY `FK_FKT_CONTACT_FK_PAYMENT` (`FK_PAYMENT`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Tabelle mit 1 Kontakt je Kreditor / Debitor';

-- Neue Tabelle fkt_contact2address
CREATE TABLE IF NOT EXISTS `fkt_contact2address` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `FK_CONTACT` bigint(20) NOT NULL COMMENT 'fkt_contact.ID',
  `FK_ADDRESS` bigint(20) NOT NULL COMMENT 'fkt_address.ID',
  `RELATION` bit(4) NOT NULL DEFAULT b'1111' COMMENT 'Art der Beziehung: A = Angebot, B = Auftrag, C = Lieferung, D = Rechnung',
  PRIMARY KEY (`ID`),
  UNIQUE KEY `FK_CONTACT_FK_ADDRESS` (`FK_CONTACT`,`FK_ADDRESS`),
  KEY `FK_CONTACT` (`FK_CONTACT`),
  KEY `FK_ADDRESS` (`FK_ADDRESS`),
  CONSTRAINT `FK_ADDRESS` FOREIGN KEY (`FK_ADDRESS`) REFERENCES `fkt_address` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_CONTACT_2_ADDRESS` FOREIGN KEY (`FK_CONTACT`) REFERENCES `fkt_contact` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Relation zwischen den Tabellen fkt_contact und fkt_address';

-- Neue Tabelle fkt_contact2bankaccount
CREATE TABLE IF NOT EXISTS `fkt_contact2bankaccount` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `FK_CONTACT` bigint(20) NOT NULL COMMENT 'fkt_contact.ID',
  `FK_BANKACCOUNT` bigint(20) NOT NULL COMMENT 'fkt_bankaccount.ID',
  `RELATION` bit(2) NOT NULL DEFAULT b'11' COMMENT 'Art der Beziehung: A = Lastschrift, B = Gutschrift',
  PRIMARY KEY (`ID`),
  UNIQUE KEY `FK_CONTACT_FK_BANKACCOUNT` (`FK_CONTACT`,`FK_BANKACCOUNT`),
  KEY `FK_BANKACCOUNT` (`FK_BANKACCOUNT`),
  KEY `FK_CONTACT` (`FK_CONTACT`),
  CONSTRAINT `` FOREIGN KEY (`FK_CONTACT`) REFERENCES `fkt_contact` (`ID`) ON UPDATE CASCADE,
  CONSTRAINT `FK_BANKACCOUNT` FOREIGN KEY (`FK_BANKACCOUNT`) REFERENCES `fkt_bankaccount` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_CONTACT_2_BANKACCOUNT` FOREIGN KEY (`FK_CONTACT`) REFERENCES `fkt_contact` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Relation zwischen den Tabellen fkt_contact und fkt_bankaccou';

/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
Tagsdatabase

Relationships

related to 0000624 assignedrheydenr Adresse zu mehrere Kontakte 

Activities

LastBoyScout

2018-06-01 17:03

reporter  

contacteditor_address.png (100,907 bytes)
contacteditor_address.png (100,907 bytes)

rheydenr

2018-06-25 00:01

administrator   ~0000772

Last edited: 2018-06-25 00:05

View 2 revisions

Der Vorschlag wird als Umsetzungshilfe aufgegriffen. Die Variante mit dem Bitmuster wird allerdings nicht umgesetzt, da der Datenbank-Zugriff über eine ORM-Schicht erfolgt. Da würde das zu erheblichen Komplikationen führen. Die Verknüpfungstabellen werden automatisch erstellt (auch durch den ORM-Mapper). Wichtig wäre hier vor allem eine Migrationsstrategie der bereits erfaßten Daten. Das wird nochmal analysiert.
Die Einstellung für InnoDB ist in der MySQL-Konfigurationsdatei jedes Systems hinterlegt, darauf hat Fakturama keinen Einfluß. Die Tabellen werden über Liquibase angelegt, aber eben mit den Standardwertden, die das DB-System vorgibt.
Für "gelöschte" Einträge gibt es aktuell schon das "DELETED"-Flag. Es dürfen keine Kontakte gelöscht werden, an denen beispielsweise noch eine Rechnung hängt (gesetzl. Vorgaben). Hier wird es später einmal eine Aufräumroutine geben, die die überflüssigen Datensätze entfernt. Das brauchen wir aber frühestens in 10 Jahren ;-)

LastBoyScout

2018-06-25 12:06

reporter   ~0000774

Sofern ein Bitmuster von ORM nicht umgesetzt werden kann, muss in den Verknüpfungstabellen eben für jede Beziehungsart (Beleggruppen und Kontoarten) eine eigene Spalte bit(1) hinterlegt werden.

Da die Primären- Kontaktdaten einen Wert in CUSTOMERNUMBER haben wo bei den Sekundären immer NULL ist, kann man die zusammengehörige Daten ja per JOIN verknüpfen:
SELECT * FROM fkt_contact AS PRI
LEFT JOIN fkt_address AS A ON PRI.FK_ADDRESS = A.ID
LEFT JOIN fkt_contact AS SEC ON PRI.FK_ALTERNATECONTACT = SEC.ID
LEFT JOIN fkt_address AS B ON SEC.FK_ADDRESS = B.ID
LEFT JOIN fkt_bankaccount ON PRI.FK_BANKACCOUNT = fkt_bankaccount.ID
WHERE PRI.CUSTOMERNUMBER IS NOT NULL

Diese Datensätze kann man dann in einer Temporären Tabelle zwischenspeichern um es nach dem Umbau in die neue Tabellenstruktur zu überführen.

Auch wenn MyISAM als Standard angegeben ist, kann man beim erstellen einer Tabelle doch trotzdem InnoDB als Engine auswählen!
Dies kann man auch später noch ändern: ALTER TABLE xy ENGINE = InnoDB;
Und die Grundeinstellung lässt sich wie folgt ändern: SET default_storage_engine=InnoDB;

rheydenr

2018-06-25 20:41

administrator   ~0000777

Mit einem OR-Mapper ist das leider etwas komplizierter, weil man da nicht direkt auf die jeweilige Datenbank geht. Ich mach mir dazu noch ein paar Gedanken.

LastBoyScout

2018-06-29 11:59

reporter   ~0000782

Dachte so ein OR-Mapper soll einen die Arbeit erleichtern? ;-)

Bez. dem Löschen, insbesondere von personenbezogenen Daten, sollte man nochmal in Klausur gehen:
A: Kein bisheriges Vertragsverhältnis (z.B. nur Angebot) -> sofortiges Löschen oder auch Datensperre möglich.
B: Offenes Vertragsverhältnis (z.B. aktueller Auftrag oder auch unbezahlte Rechnung) -> Löschen oder Datensperre nicht möglich.
C: Abgeschlossenes Vertragsverhältnis (Forderung beglichen) -> Datensperre möglich, Löschen nach Ablauf gesetzlicher Fristen... davon nicht betroffene Daten, z.B. Geburtsdatum, Mailadresse usw. sind hingegen sofort zu Löschen.
Es sollten daher beide Flags (DELETED und BLOCKED) umgesetzt werden und auch ein tatsächliches Löschen (wie vor) müsste möglich sein.

P.S. Musste neulich Adressen verifizieren und da wird ein String aus Straße inkl. Hausnummer oftmals zum Knackpunkt. Wenn man bei den Adressdaten daher einmal einen Umbau vornimmt, schlage ich vor dabei auch die Hausnummer in einen extra Spalte zu überführen.
Um für die Zukunft gerüstet zu sein, sollte man dabei evtl. sogar auch gleich noch Felder für Geodaten integrieren (Ideal z.B. für Lieferungen an Außenlager oder Neubauten noch ohne Straße und Hausnummer usw.)

rheydenr

2018-06-30 01:18

administrator   ~0000787

Mir hat bislang eigentlich das DELETED-Flag ausgereicht. Das sorgt ja dafür, daß der Datensatz nirgends mehr auftaucht. Wenn man aber eine Rechnung hat, die diesen Satz referenziert, sollte das ja nicht in einem Fehler enden.

LastBoyScout

2019-02-08 10:39

reporter   ~0000868

Mit der richtigen Strategie muss es ja nicht zwangsläufig in einem Fehler enden. Bei einem entsprechenden Löschantrag gem. DSGVO sind ja nur die Daten mit unmittelbarem Personenbezogenen zu Löschen, sofern keine anderweitige Vorschrift dem entgegensteht (z.B. gesetzl. Archivierugsfrist noch nicht abgelaufen). Alle Übrigen Daten z.B. PLZ, Ort usw. können natürlich weiterhin erhalten bleiben. Die betroffenen Daten müssen dann aber auch wirklich gelöscht werden. Ein DELETED-Flag über welches die Daten nur ausgeblendet werden, ist eben nicht zulässig.

Issue History

Date Modified Username Field Change
2018-06-01 17:03 LastBoyScout New Issue
2018-06-01 17:03 LastBoyScout Tag Attached: database
2018-06-01 17:03 LastBoyScout File Added: contacteditor_address.png
2018-06-01 23:52 rheydenr Additional Information Updated View Revisions
2018-06-01 23:52 rheydenr Assigned To => rheydenr
2018-06-01 23:52 rheydenr Status new => assigned
2018-06-25 00:01 rheydenr Note Added: 0000772
2018-06-25 00:05 rheydenr Note Edited: 0000772 View Revisions
2018-06-25 12:06 LastBoyScout Note Added: 0000774
2018-06-25 20:41 rheydenr Note Added: 0000777
2018-06-29 11:59 LastBoyScout Note Added: 0000782
2018-06-30 01:18 rheydenr Note Added: 0000787
2019-02-08 10:39 LastBoyScout Note Added: 0000868
2019-02-18 20:52 rheydenr Relationship added related to 0000624