Mitgliederverwaltung - Hilfe bei der Erstellung sauberen Codes

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 244 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    ErfinderDesRades schrieb:

    Neues Konzept: Aufschläge jeder Art sind besondere Artikel, und werden beim Einkauf als Extra-Einkauf-Positionen zugefügt.
    So wie im Supermarkt der FlaschenPfand eine Extra-Position auffm Bon ist.

    D.h.
    Es gibt den Artikel Angelmarke DAV Erwachsen 1 Jahr - 73 Euro
    und den Artikel Verzug - 5 Euro
    Ich muss ja aber trotzdem (beim Artikel) irgendwo speichern, ab wann der Verzug hinzukommt).
    Also wenn der Verein nächstes Jahr sagt, der Verzug entfällt, oder wird fällig bereits ab dem 01.03. muss das ja änderbar sein.
    Wie stelle ich das mit deiner Version an? Würdest du dann auch eine Datumsspalte machen?
    Hmm - man könnte auch die DatumSpalte weglassen.
    Stattdessen baut man eine Mittler-Tabelle, die einen Artikel mit einem VerzugsWert verbinden kann.
    Bischen unschön daran, dass dadurch datenmodell-theoretisch ein Artikel mehrere Verzüge haben kann - in Wirklichkeit aber nur einen oder keinen.
    Vorteil so einer Konstruktion ist, dass du später Logik schreiben kannst, die einem Einkauf automatish einen Verzug zufügen kann, wenn der Artikel mit einem Verzug verknüpft ist, und dessen Datum überschritten.

    Eben wie mittm FlaschenPfand: Der Kassierer tippt nur das Bier ein, und die Logik packt den richtigen Pfand dazu auffn Bon.

    ErfinderDesRades schrieb:

    Eben wie mittm FlaschenPfand: Der Kassierer tippt nur das Bier ein, und die Logik packt den richtigen Pfand dazu auffn Bon.

    Hmm, so hatte ich das mit meinem DataSet Vorschlag vor.

    DerSmurf schrieb:

    Eine AllowNull Spalte "Verzugsdatum" - um zu speichern ab wann Verzug fällig ist. Mit IsMarke.VerzugsdatumNull kann ich abfragen ob überhaupt Verzug anfällt.
    Decimal Spalte Verzugsgebühren - um zu speichern wie hoch der Verzug ist

    Ich prüfe die Spalte auf IstNull, wenn sie null ist gibts kein Verzug (kein Pfand).
    Wenn ein Datum drin steht, wird geprüft, ob das in der Zukunft, oder Vergangenheit liegt und der Wert aus der Row Verzugsgebühren hinzugefügt, oder eben nicht. Das kann ich ja mithilfe der Logik als eigene Position anzeigen.
    Für die Abrechnung speichere ich ja "Verzug" (boolean) in der Table Einkaufsposition (wobei ich hier ja dann auch eine Row für die Höhe der Verzugsgebühren einfügen sollte.

    Ich kann also mit meiner DBNull Row drei Werte speichern (kein Verzug, kein Verzug wegen rechtzeitig gekauft, und Verzug.

    Warum funktioniert das nicht / Warum ist das schlecht?

    DerSmurf schrieb:

    Warum funktioniert das nicht / Warum ist das schlecht?
    Die Preise ergeben sich in einer EinkaufPositionRow als berechnete Spalte:
    (EinkaufPositionRow.Preis = ) (parent(FK_Marke_EinkaufPosition).Preis * Anzahl
    Das geht Dataset-Intern - BusinessLogic bekommt keinen Fuss dazwischen.

    Übrigens zeigt sich da doch ein deutlicher Mangel in deim Modell. Also die Relationen ergeben mir Sinn, aber so einige der Spalten:
    EinkaufPosition muss die Spalten haben: ID, MarkeID, EinkaufID, Anzahl - nicht mehr oder weniger.
    Verzug ist ja ein eigener Artikel - mehrere sogar: Je nach Marke scheints da ja unterschiedliche Kosten zu geben.
    Datum gehört auch nicht in jede Einkaufposition, sondern ist Eigenschaft des Einkaufs.
    string Markennummer - was hast du damit vor?
    Ja, OK. Mir leuchtet ein, dass

    ErfinderDesRades schrieb:

    Also die Relationen ergeben mir Sinn, aber so einige der Spalten:
    EinkaufPosition muss die Spalten haben: ID, MarkeID, EinkaufID, Anzahl - nicht mehr oder weniger.

    Eine Einkaufsposition nur über Relationen verfügen sollte. Alle weiteren zu speichernden Felder sollten sich dann in den entsprechenden Tables befinden, aber nicht in der Einnkaufsposition.
    string Markennummer sollte eine Vereinfachung sein. (Erklärung am Ende des Posts)
    Aber ich Liste mal auf, was ich überhaupt speichern möchte, damit wir eine Lösung für die Marke DataTable finden (welche dann im übrigen wohl doch in Artikel umbenannt werden sollte - weil sie ja nicht nur Marken speichert).

    Ich teile die Marken mal in drei Gruppen - jede Gruppe hat eigene "Spezialanforderungen"
    Gruppe1 Fischereiabgabemarken
    • Fischereiabgabe Erwachsen 1 Jahr - 12 Euro
    • Fischereiabgabe Erwachsen 5 Jahre - 40 Euro
    • Fischereiabgabe Jugen (bis 18) - 2,50€
    • Ausweis zum einkleben der Marken - 0 Euro (hier passen mehr als 1 Marke rein, beim Markenkauf also nicht erforderlich, wenn Kunde bereits einen hat)
    hier gibt es keinerlei Besonderheiten

    Gruppe 2 DAV Marken
    • DAV Erwachsen - 73 Euro
    • DAV Jugend - 20 Euro
    • Asuweis zum einkleben der Marke - 1 Euro (wie oben nicht immer erforderlich)
    Besonderheit 1: ab dem 01.04. zahlt jeder Markenkäufer 5 Euro on Top (Verzug)
    Besonderheit 2: neue Mitglieder (im letzten Jahr keine Marke gekauft) zahlen 5 Euro on Top (unabhängig vom Kaufdatum) (Neuanmeldung)
    Besonderheit 3: Es wird nur einmal 5 Euro Zuschlag fällig, Ein Neumitglied zahlt also NICHT Neuanmeldung + Verzug
    Besonderheit 2.1: vom Neumitglied muss eine Datenschutzerklärung unterschrieben werden, hier muss das Programm dran erinnern.

    Gruppe 3 Sachsen Anhalt und Mecklenburg
    • Mecklenburg Karte - 10,50 Euro
    • Sachsen Anhalt Karte - 10,50 Euro
    Besonderheit 1: alle Marken sind mit einer eindeutigen Nummer versehen, welche beim Verkauf gespeichert werden muss.
    Also ich muss wissen, dass Karl Heinz Sachsen Anhalt Karte Nummer 2021095 gekauft hat.
    Hierfür war Einkaufsposition.Markennummer gedacht.
    Besonderheit 2: Beide Marken dürfen nur ausgegeben werden, wenn der Kunde einen Fischereischein hat.
    (Person.Fischereischeinnummer). Fischereischeine verkaufe ich nicht. Also wenn der Kunde keinen hat, gibts diese Marke nicht.

    Für Gruppe 1 ist alles klar - da gibts ja nix weiter zu beachten.
    Für Gruppe 2 ergeben sich dann die Artikel
    • Erwachsenen Marken
    • Jugend Marke
    • Ausweis
    • Verzug
    • Neuanmeldung
    Die Posten Verzug und Neuanmeldung müssten dann von der BusinessLogic hinzugefügt werden, wenn die entsprechenden Bedingungen erfült sind.
    Im groben ist mir klar, wie das funktionieren soll. Also wenn ich eine Marke verkauft rattert meine Logik die alten Käufe der Person durch.
    Gibt es keinen im letzten Jahr, isser neu.
    Ebenso beim Verzug. Wenn beim Verkauf DatumVonHeute > Verzugsdatum, muss er Verzug bezahlen.
    Aber wie stelle ich es an, dass die BusinessLogik das eben nur bei DAV Marken macht und eben nicht bei Fischereiabgabemarken?
    Hier brauche ich doch dann noch extra boolean Spalten - Verzug und Neuanmeldung, oder nicht?
    Und wie halt ich das ganze dynamisch? Wenn ich in 3 Jahren DAV Marken für zwei Vereine verkaufe und Verein 1 nimmt 5 Euro Verzug, Verein 2 nimmt 3 Euro Verzug und keine Aufnahmegebühr?

    In Gruppe 3 ist eben das Problem, dass jede Karte eine eigene Nummer hat. Also eigentlich ist damit jede Karte ein eigener Artikel.
    Aber das wäre ja mega lästig, wenn ich jede Karte aufgrund ihrer individuellen Nummer als eigene Artikel Position einpflegen müsste.
    (Deswegen die Row in Einkaufsposition).

    Und noch am Rande zur Anzahl:
    Eine Anzahl würde ich gänzlich ignorieren, denn diese ist immer 1.
    Zwar kann Gustav für sich selbst 2 Fischereiabgabemarken kaufen. Aber das macht keinen Sinn.
    Denn was er dieses Jahr bei mir kaufen kann, ist eine Marke die für 2021 (1 Jahr), oder für die Jahre 2021 bis 2025 (5 Jahre) gültig ist.
    Kauft er zwei mal die Jahresmarke, darf er damit auch nur in 2021 angeln, nicht in 2021 und 2022.
    In der Regel will Gustav, wenn er 2 gleiche Marken kauft, eine für sich und eine für seine Frau.
    Dann muss ich ja aber speichern, dass Gustav eine kauft und Sieglinde kauft eine.
    Denn es sind immer die Adressdaten des Anglers zu speichern (nicht des Käufers)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DerSmurf“ ()

    Find ich gut.
    Aber reicht das, oder brauche ich eine Tabelle besonderheit?
    Denn im Falle von Besonderheit = 1 - also DAV, muss ich ja in der BL hinterlegen was zu tun ist und könnte das nicht dynamisch ändern.
    Oder kann ich das wohl?

    Edit: Also im Moment sind keine Änderungen geplant, aber es wäre schön, wenn ich nicht in den code muss, wenn Verein 2 über mich seine Marken mit anderen Bedingungen verkauft.


    und wo ist die nummer der SA und MV Marken zu speichern?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DerSmurf“ ()

    DerSmurf schrieb:

    und wo ist die nummer der SA und MV Marken zu speichern?
    achmist - das hatte ich vergessen.
    Also kommando zurück, Besonderheit-Spalte wieder raus, und für jede Art Besonderheit eine eigene Tabelle, mit FK->Artikel.
    Wenn die Besonderheit der Art ist, dass eine Mitgliedsnr zu speichern ist, kann sie da gespeichert werden.
    Andere Besonderheiten - etwa der DAV-Aufpreis - das muss die Businesslogik wissen, dass dann der Aufpreis-Artikel mit in die EinkaufPositionen muss - es scheint ja nur einen einzigen zu geben.
    Auch die Erinnerung an die Erklärung: Das muss BL wissen: Aha - dem Artikel ist eine DAV-Besonderheit zugeordnet - also gucken, ob Aufpreis und oder Erklärung
    Im DataSet habe ich die Table Einkaufsposition entsprechend geändert.
    Außerdem eine Table Artikelbesonderheit hinzugefügt, diese verweist auf die Artikeltable.
    Aber ich verstehe das Konzept dahinter nicht.
    Also ich verstehe, dass ich mit meinem Dts jetzt für jeden Artikel beliebig viele Besonderheiten speichern kann.
    (So wie ich für jede Person beliebige viele Einkäufe mit beliebig vielen Einkaufspositionen speichern kann.)
    Aber mir ist nicht klar, wie ich jetzt in der Ausführung des Programmes einpflege, dass eben ab dem 01.04. bei DAV Marken 5 Euro dazu kommen.
    Kannst du mir sagen, ob das Dts so korrekt ist?

    Außerdem wäre es schön, wenn das hier gegen ist:

    DerSmurf schrieb:

    Edit: Also im Moment sind keine Änderungen geplant, aber es wäre schön, wenn ich nicht in den code muss, wenn Verein 2 über mich seine Marken mit anderen Bedingungen verkauft.
    Bilder
    • Dataset.png

      161,84 kB, 1.322×786, 48 mal angesehen
    Ja, sorry, war falsch gedacht.
    Artikelbesonderheit wieder löschen, und nun will ichs doch wieder haben wie in post#87:

    ErfinderDesRades schrieb:

    Hmm - nun würde ich eine Spalte Besonderheit an Artikel machen, die die Besonderheit codiert (0=Nix, 1=DAV, 2=SAM (SachsenAnhaltMeckelnburg))
    Programmlogik guckt dann beim Verkauf eines Artikels nach, ob und welche Besonderheit vorliegt und weiss dann, was zu tun ist.

    Und die MarkenNummern müssen in eine weitere Tabelle MarkenNr, mit FK auf EinkaufPosition.
    Programmlogik guckt also in Spalte Besonderheit, und schmeisst zB bei DAV ab April immer einen Verzugs-Aufpreis in den Einkauf.
    Bei SAM verlangt die Programmlogik die MarkeNummer, und legt entsprechend den Datensatz an.

    Und entsprechend mit dem anderen Kram: Fisch-schein-Kontrolle, Datenschutz, und was den Behörden sonst noch einfallen mag - wie wärs mit einer Einverständniserklärung für personalisierte Werbung?
    Aber wenn ich die BEsonderheit codiere und die Programmlogik weiß was zu tun ist, ist dies ja nur im Code änderbar.
    Wenn also der Verzug nächstes Jahr statt 5 Euro, 7 Euro kostet, müsste ich das in meiner BL ändern. Kommt der Verzug erst ab 01.05. zum tragen, muss ich in den Code.
    Wäre es nicht denkbar eine unverknüpfte DataTable zu erstellen, aus der die BL dann ausliest was zu tun ist?
    Also z.B. mit dem Rows ID, Code, Name, Datum, Kosten.
    Dann könnte meine BL den enstprechenden "Besonderheit Code" in dieser Table suchen. So wären ein eventuelles Datum, oder eben die Kosten dieser Besonderheit einstellbar.
    Außerdem könnte es dann einen Verzug1 und einen Verzug2 geben. Ggf. mit einem anderem Datum, oder anderen Kosten.

    ErfinderDesRades schrieb:

    Und die MarkenNummern müssen in eine weitere Tabelle MarkenNr, mit FK auf EinkaufPosition.

    Warum eine neue Table, mit nur einer Row? Und nicht direkt in die Einkaufsposition?
    Es kann ja eh nur eine Markennummer pro Einkaufsposition geben.

    ErfinderDesRades schrieb:

    wie wärs mit einer Einverständniserklärung für personalisierte Werbung?

    Ginge übrigens problemlos. Da aber eh nur jeder zehnte liest, was er da unterschreibt, kann ich auch direkt meine Bankverbindung, mit entsprechender Kostenaufstellung unterschreiben lassen.
    Irgendwie hab ich den Eindruck, dass ihr euch hier viel zu viel unnötige Gedanken macht.
    Kannst du nicht einfach den Normalpreis der Marken in Artikel wegspeichern und machst beim "Kassiervorgang" eine Prüfung, wann das Mitglied zum letzten mal
    gekauft hat und machst ggf. nen Aufschlag auf den Gesamtbetrag und den Aufschlag speicherste wegen mir weg in ne Aufschlagtabelle? Dabei diverse Aufschlagtypen "verzug, neu..." und was es da sonst
    noch an Besonderheiten gibt. Somit hättest du die Marken als saubere Artikel und alles Andere passiert an anderer Stelle.

    Ich hoff' ich hab hier bei dem Wust an Beiträgen nix falsch verstanden :D
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    DerSmurf schrieb:

    Aber wenn ich die BEsonderheit codiere und die Programmlogik weiß was zu tun ist, ist dies ja nur im Code änderbar.
    Wenn also der Verzug nächstes Jahr statt 5 Euro, 7 Euro kostet, müsste ich das in meiner BL ändern.
    Na, das geht noch, weil Verzug ja ein Artikel ist, von dem du den Preis ändern kannst.
    Mehr Probleme macht das Stich-Datum.
    Naja - soo problematisch auch wieder nicht - das ist ja nur ein einziges Datum und gilt für die ganze Welt. Das kriegt man zur Not noch in die Settings gepackt.
    Oder man macht eine Tabelle für Sonderlocken aller Art.
    Ja, und Programmlogik weiss dann eben, wie welche Sonderlocke da auszuparsen ist, wenn beim Artikel eine bestimmte Besonderheit-Nummer angegeben ist.
    Nicht schön, aber dafür hässlich.



    @Tragl: Eine AufschlagTabelle und eine AufschlagTyp-Tabelle - das wird auch nicht einfacher. Man muss die Aufschlagerei ja auch noch einer EinkaufPosition zuordnen.
    Und da hast du noch nicht das Stichdatum berücksichtigt, ab wann der Aufschlag gilt, und für die andere Besonderheit die MarkenNummer muss ja auch noch festgehalten werden.

    Das mit der Prüfungen (es sind ja mehrere, verschiedener Art) stimmt schon - dassis nicht kriegsentscheidend.
    Wenn das Proggi das in erster Version noch nicht kann, da stirbt der Verkäufer auch nicht dran.
    Das DataSet habe ich soweit bearbeitet.

    Aber das hier verstehe ich nicht:

    ErfinderDesRades schrieb:

    Und die MarkenNummern müssen in eine weitere Tabelle MarkenNr, mit FK auf EinkaufPosition.

    Es gitb ja pro Einkaufsposition maximal eine Markennummer.
    Warum dann in eine separate Tabelle mit FK auf die Einkaufsposition und nicht einfach direkt als Row in die Einkaufsposition? Wenns keine Nummer gibt, lass ich halt leer.

    Edit: Artikel.BesonderheitCode hat als DefalutValue die 0
    Edit2: Die Tabelle Besonderheit habe ich ein Einstellungen umbenannt. Hier kann ich ja noch andere Dinge wie z.B. DGV Spaltenbreiten und Gedöns speichern.
    Bilder
    • DataSet.png

      294,91 kB, 1.920×1.080, 37 mal angesehen

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „DerSmurf“ ()

    Das heißt, es ist unschön, wenn ich eine Row habe, in der in 95% der Fälle nichts steht.
    Mit der extra Tabelle erzeuge ich nur einen Eintrag, wenn es auch einen gibt.
    Das leuchtet mir ein.

    Dann mache ich mich jetzt mal an ein bisschen Code und melde mich, wenns ich mit den Einstellungen (Artikel hinzufügen, Lieferanten hinzufügen, usw.) fertig bin.
    Hey Leute. Ich scheitere irgendwie gerade an den Einstellungen.
    Ich möchte in den Settings die "eigenenDaten" änderbar machen.
    Also dtsAngelmarken.eigeneDaten

    Dazu prüfe ich beim Start des Programmes erst einmal, ob es überhaupt eine entsprechende Row gibt und lege ggf. eine an.

    VB.NET-Quellcode

    1. If BSeigeneDaten.Count = 0 Then
    2. dtsAngelmarken.eigeneDaten.AddeigeneDatenRow("", "", "")
    3. End If

    Dann habe ich auf meiner Form drei gebundene Textboxen für die DataTable (Firmenname, Straße, Ort) und einen speichern Button mit folgendem Code:

    VB.NET-Quellcode

    1. Private Sub BTNSaveOwnData_Click(sender As Object, e As EventArgs) Handles BTNSaveOwnData.Click
    2. If FirmennameTextBox.Text <> "" AndAlso StrasseTextBox.Text <> "" AndAlso OrtTextBox.Text <> "" Then
    3. Dim ownaddress = DirectCast(DirectCast(BSeigeneDaten.Current, DataRowView).Row, eigeneDatenRow)
    4. With ownaddress
    5. .Firmenname = FirmennameTextBox.Text
    6. .Strasse = StrasseTextBox.Text
    7. .Ort = OrtTextBox.Text
    8. End With
    9. Else
    10. MessageBox.Show("Ändern der Adresse nicht möglich." & Environment.NewLine & "Es fehlt ein Eintrag.")
    11. End If
    12. End Sub

    Wenn ich aber eine Änderung an einer der drei Rows vornehme, und speichern klicke, habe ich beim nächsten Start, wieder die alten Werte.
    Wenn ich das ganze Schrittweise durch gehe, sieht alles gut aus. Wo ist hier mein Denkfehler?
    Dateien
    ist die XML-Datei in's Projekt eingebunden?
    oder sieht das so aus wie auf dem Bild?


    wenn die mit eingebunden ist, kann es sein dass die änderungen nicht gespeichert werden - ist gut für's testen, wenn man nix zerstören will
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Nein, leider nicht.
    Die xml ist eingebunden (wobei das doch egal sein müsste, die Datei wird ja beim verlassen des Programmes geschrieben.)
    Es funktioniert aber auch das hinzufügen / ändern von Personen.
    Also wenn ich hier Personen hinzufüge, oder bearbeite, sind diese beim nächsten Programmstart noch da. Das speichern ansich funktioniert also.
    Ich glaube auch nicht, dass mein Code fehlerhaft ist.
    Kann es sein, dass dieses Verhalten (also das nicht speichern), durch die Helpers von @ErfinderDesRades hervorgerufen werden?
    Also dass ich evtl. mehr machen muss, als nur die Row in der Bindingsource zu ändern?