Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bei der Zuweisung von Buchungen zu MK ist ein Bug in der Suche passender MK #178

Open
JPT77 opened this issue Mar 1, 2024 · 5 comments
Open

Comments

@JPT77
Copy link

JPT77 commented Mar 1, 2024

Moin

ich habe bei fast allen Mitgliedern das Problem, dass nur offene SOLL-Buchungen aus 2022 angezeigt werden.
Ich bin nun der Ursache näher gekommen.

In MitgliedskontoControl.getMitgliedskontoIterator() gibt es eine Schleife, welche die Namen von Buchung mit Mitglied matched.

Irgendwie passiert es, dass sich der MaxScore verdoppelt, möglicherweise beim Wechsel der Jahre?
Jedenfalls ist mein MaxScore nun 8, was bei einem Namen bestehend aus zwei Worten nicht passieren sollte, oder?
Jedesmal wenn sich dieser Score verdoppelt werden alle bisher gefundenen Einträge gelöscht. Das ist die Ursache, warum nicht alle angezeigt werden.

          if (suchname != null && suchname.getValue() != null)
          {
            StringTokenizer tok = new StringTokenizer(
                (String) suchname.getValue(), " ,-");
            Integer score = 0;
            while (tok.hasMoreElements())
            {
              String nextToken = tok.nextToken();
              if (nextToken.length() > 3)
              {
                score += scoreWord(nextToken, mk.getMitglied().getName());
                score += scoreWord(nextToken,
                    mk.getMitglied().getVorname());
                score += scoreWord(nextToken, mk.getZweck1());
              }
            }

            if (maxScore < score)
            {
              maxScore = score;
              // We found a Mitgliedskonto matching with a higher equality
              // score, so we drop all previous matches, because they were
              // less equal.
              ergebnis.clear();
            }
            else if (maxScore > score)
            {
              // This match is worse, so skip it.
              continue;
            }
          }

Leider mismatched mein Source irgendwie mit dem, was der debugger ausführt. Scheinbar zieht die Config den actual programmcode aus dem Pluginverzeichnis, nicht aus Eclipse.

@JPT77
Copy link
Author

JPT77 commented Mar 1, 2024

Ich weiss, woran es liegt:
es wird auch auf den Zweck des MK gematched.
Damit haben manche Matches höhere Werte, obwohl sie zum gleichen Mitglied gehören.
Das ist schlicht falsch. Richtig wäre:
Finde Mitglieder, die matchen. Dann liste alle (offenen) MK dieses Mitglieds.

Als Anfänger in Sachen JVerein traue ich es mir nicht zu diese komplexe Änderung vorzunehmen.
Vielleicht hat ja jemand anders die Nerven?
Bis dahin muss ich wohl die ZWECK Felder patchen.

Vielen Dank

@JPT77 JPT77 changed the title Bei der Zuweisung von Mitgliedskonten zu Buchungen ist ein Bug in der Suche passenden MK Bei der Zuweisung von Mitgliedskonten zu Buchungen ist ein Bug in der Suche passender MK Mar 1, 2024
@JPT77 JPT77 changed the title Bei der Zuweisung von Mitgliedskonten zu Buchungen ist ein Bug in der Suche passender MK Bei der Zuweisung von Buchungen zu MK ist ein Bug in der Suche passender MK Mar 1, 2024
@JohannMaierhofer
Copy link

JohannMaierhofer commented Mar 2, 2024

Ich denke der Match auch auf das Zweck Feld macht wirklich so keinen Sinn machen.
Das müsste eigentlich anders herum sein. Suche nach Mitglieder wo entweder der Name aus der Buchung oder der Zweck aus der Buchung und nicht der aus dem MK mit dem Mitgliedsnamen übereinstimmen. Das könnte Sinn machen wenn z.B. Jemand etwas für einen anderen bezahlt, dann steht im Namen der selektierten Buchung irgend ein Name und im Zweck ist dann eingetragen für wen die Buchung ist. Z.B. zahlt jemand die Miete für jemanden, dann könnte im Zweck stehen "Miete für Hans Mustermann".
Dann sollten aber trotzdem nicht die Matches auf den Namen, falls vorhanden gelöscht werden sondern alle gefundenen angezeigt werden.

Als schnelle Lösung könnte man jetzt den Vergleich mit dem Zweck aus dem MK rausnehmen. Ansonsten muss man das Ganze sowieso verbessern.

@JPT77
Copy link
Author

JPT77 commented Mar 2, 2024

Ich habe mal einen Entwurf erstellt.
Da im alten Code Datumskrams drin ist, der nicht genutzt wird, gehe ich jetzt davon aus die Methode vielleicht wo anders noch verwendet wird und habe eine neue erstellt. (Eclipse findet aber nur diese eine Verwendung)

Der erste Part sollte so einigermaßen passen. den zweiten part hab ich nur mal reinkopiert. Jedenfalls geht das Namensmatching auf das Mitglied und das Differenz-Matching auf das Mitgliedskonto. Datumskram habe ich komplett entfernt, weil irrelevant.

Was man vielleicht noch hinzufügen sollte, ist ein eine Möglichkeit auch andere Buchungen zu finden. Ach so, dafür haben wir das Namen-Eingabefeld. Mh. Oder ein Schieber maximale Abweichung von ScoreMax?

Ich weiss nicht wie ich das testen soll. Werde mal versuchen, die Plugin-binaries aus dem Config-verzeichnis zu löschen, damit er den Code aus Eclipse ziehen muss.

public GenericIterator getMitgliedsSollIterator() throws RemoteException 
{
DBService service = Einstellungen.getDBService();
String sql = "select * from mitglieds order by name, vorname, datum desc";
PseudoIterator mitglieder = (PseudoIterator) service.execute(sql, null, new ResultSetExtractor()
{

  @Override
  public Object extract(ResultSet rs)
    throws RemoteException, SQLException
  {
  ArrayList<Mitglied> mitglieder = new ArrayList<>();

  // In case the text search input is used, we calculate
  // an "equality" score for each Mitgliedskonto (aka
  // Mitgliedskontobuchung) entry. Only the entries with
  // score == maxScore will be shown.
  Integer maxScore = 0;
  while (rs.next())
  {
    Mitglied mitglied = (Mitglied) Einstellungen.getDBService()
      .createObject(Mitglied.class, rs.getString(1));

    if (suchname != null && suchname.getValue() != null)
    {
    StringTokenizer tok = new StringTokenizer(
      (String) suchname.getValue(), " ,-");
    Integer score = 0;
    while (tok.hasMoreElements())
    {
      String nextToken = tok.nextToken();
      if (nextToken.length() > 3)
      {
      score += scoreWord(nextToken, mitglied.getName());
      score += scoreWord(nextToken, mitglied.getVorname());
      }
    }

    if (maxScore < score)
    {
      maxScore = score;
      // We found a Mitgliedskonto matching with a higher equality
      // score, so we drop all previous matches, because they were
      // less equal.
      mitglieder.clear();
    }
    else if (maxScore > score)
    {
      // This match is worse, so skip it.
      continue;
    }
    }

    mitglieder.add(mitglied);
  }
  return PseudoIterator.fromArray(
    mitglieder.toArray(new GenericObject[mitglieder.size()]));
  }
});

ArrayList<Mitgliedskonto> ergebnis = new ArrayList<>();
sql = "select * from mitgliedskonto where id = ?";
while (mitglieder.hasNext()) {
  Mitglied mitglied = (Mitglied) mitglieder.next();
  mitglied.getID();
  String where = "";
  ArrayList<Object> param = new ArrayList<>();
  if (where.length() > 0)
  {
  sql += "WHERE " + where;
  }
  sql += "order datum asc";
  PseudoIterator mitgliedskonten = (PseudoIterator) service.execute(sql,
    param.toArray(), new ResultSetExtractor()
  {

  @Override
  public Object extract(ResultSet rs)
    throws RemoteException, SQLException
  {
    ArrayList<Mitgliedskonto> ergebnis = new ArrayList<>();

    // In case the text search input is used, we calculate
    // an "equality" score for each Mitgliedskonto (aka
    // Mitgliedskontobuchung) entry. Only the entries with
    // score == maxScore will be shown.
    Integer maxScore = 0;
    while (rs.next())
    {
    Mitgliedskonto mk = (Mitgliedskonto) Einstellungen.getDBService()
      .createObject(Mitgliedskonto.class, rs.getString(1));

    DIFFERENZ diff = DIFFERENZ.EGAL;
    if (differenz != null)
    {
      diff = (DIFFERENZ) differenz.getValue();
    }
    BigDecimal ist = BigDecimal.valueOf(mk.getIstSumme());
    ist = ist.setScale(2, RoundingMode.HALF_UP);
    BigDecimal soll = BigDecimal.valueOf(mk.getBetrag());
    soll = soll.setScale(2, RoundingMode.HALF_UP);
    if (DIFFERENZ.FEHLBETRAG == diff && ist.compareTo(soll) >= 0)
    {
      continue;
    }
    if (DIFFERENZ.UEBERZAHLUNG == diff && ist.compareTo(soll) <= 0)
    {
      continue;
    }
    ergebnis.add(mk);
    }
    return PseudoIterator.fromArray(
      ergebnis.toArray(new GenericObject[ergebnis.size()]));
  }
  }
 }

@JPT77
Copy link
Author

JPT77 commented Mar 2, 2024

Ich denke der Match auch auf das Zweck Feld macht wirklich so keinen Sinn machen. Das müsste eigentlich anders herum sein. Suche nach Mitglieder wo entweder der Name aus der Buchung oder der Zweck aus der Buchung und nicht der aus dem MK mit dem Mitgliedsnamen übereinstimmen. Das könnte Sinn machen wenn z.B. Jemand etwas für einen anderen bezahlt, dann steht im Namen der selektierten Buchung irgend ein Name und im Zweck ist dann eingetragen für wen die Buchung ist. Z.B. zahlt jemand die Miete für jemanden, dann könnte im Zweck stehen "Miete für Hans Mustermann". Dann sollten aber trotzdem nicht die Matches auf den Namen, falls vorhanden gelöscht werden sondern alle gefundenen angezeigt werden.

Ja stimmt. Aber ich denke, wenn ich eine Buchung einem anderen Mitglied zuordnen will, kann ich immernoch manuell den Namen in das Feld eintragen. Ich würde insofern nicht zu große Priorität darauf legen.

@JohannMaierhofer
Copy link

Schau dir mal #182 an.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants