200412PX Cronjob bugfixing; added reminder for reduced fee validity (disabled for now), added debt level for payment reminders

This commit is contained in:
phantomix 2020-04-12 13:37:16 +02:00
parent 6ca52cfb83
commit 94ab379681
5 changed files with 162 additions and 76 deletions

View File

@ -44,7 +44,7 @@ namespace dezentrale
{
public class Program
{
public static uint VersionNumber { get; private set; } = 0x20022500;
public static uint VersionNumber { get; private set; } = 0x20041200;
public static string VersionString { get; private set; } = $"{VersionNumber:x}";
public static string AppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

View File

@ -22,6 +22,7 @@ namespace dezentrale.core
Console.WriteLine($"Processing member {m.Number:D3} ({m.Nickname})...");
CheckGreeting(m);
CheckSpawning(m);
// CheckReducedFeeValidity(m);
CheckBalance_PreDegrade(m, sm);
BalanceDegrade(m);
CheckBalance_PostDegrade(m, sm);
@ -185,8 +186,20 @@ namespace dezentrale.core
}
}
private static void CheckReducedFeeValidity(Member m)
{
TimeSpan ts = ProgramStartTime.Subtract(m.ReducedFeeValid);
TimeSpan tsLastMail = ProgramStartTime.Subtract(m.LastCronjobReducedFeeMail);
if (ts.TotalDays > 0 && ts.TotalDays > 6) //remind if late and max. once a week
{
m.StartLogEvent($"Reminder to hand in reduced fee prove", LogEvent.eEventType.EMail, "automatic");
m.CurrentLog.SubEvents.Add(FormMail.GenerateReducedFeeReminder().Send(m));
m.LastCronjobReducedFeeMail = ProgramStartTime;
m.SaveToFile();
}
}
//! \brief This shall degrade the balance by a membership fee per month.
//! \brief This shall degrade the balance by a membership fee per month.
//! Calls to this function within the same month will not degrade
//! balance. Subsequent calls at the end of the month, and then
//! at the start of the next month, will degrade balance.
@ -223,17 +236,6 @@ namespace dezentrale.core
//! \short Necessary actions prior to BalanceDegrade.
private static void CheckBalance_PreDegrade(Member m, Member sm = null)
{
if (m.Status != Member.eStatus.Active || m.PaymentAmount == 0) return;
if (m.AccountBalance <= -2 * (int) m.PaymentAmount)
{
m.StartLogEvent($"Deactivation (insufficient payment)", LogEvent.eEventType.Deactivation, "automatic");
m.CurrentLog.SubEvents.Add(FormMail.GenerateBalanceNegativeMemberDeactivation().ReplaceReflect(Program.config.VS).Send(m));
m.CurrentLog.SubEvents.Add(FormMail.GenerateBalanceNegativeMemberDeactivationVS().ReplaceReflect(Program.config.VS).Send(m));
m.Status = Member.eStatus.Disabled;
m.SaveToFile();
}
}
private static void CheckBalance_PostDegrade(Member m, Member sm = null)
@ -241,41 +243,90 @@ namespace dezentrale.core
if (m.Status != Member.eStatus.Active || m.PaymentAmount == 0) return;
bool skipInsufficientNotify = false;
if (DateTime.Now.Day < 8) skipInsufficientNotify = true;
TimeSpan tsLastMail = ProgramStartTime.Subtract(m.LastCronjobBalanceMail);
if (m.AccountBalance <= -2 * (int)m.PaymentAmount)
int currentDeptLevel = 0; //no payments missed
if (m.AccountBalance < -2 * (int)m.PaymentAmount) currentDeptLevel = -3;
else if (m.AccountBalance == -2 * (int)m.PaymentAmount) currentDeptLevel = -2;
else if (m.AccountBalance < 0) currentDeptLevel = -1;
else if (m.AccountBalance > 200 * 100) currentDeptLevel = 1;
if (tsLastMail.TotalDays < 30)
{
if (!skipInsufficientNotify)
{
m.StartLogEvent($"Insufficient amount of payments #2", LogEvent.eEventType.EMail, "automatic");
m.CurrentLog.SubEvents.Add(FormMail.GenerateBalanceNegativeMemberNotify2().Send(m));
skipInsufficientNotify = true;
} else
{
if (m.DebtLevel >= currentDeptLevel) m.DebtLevel--;
else m.DebtLevel = currentDeptLevel;
//We don't set skipInsufficientNotify here as we don't want to not-warn
//if it's still negative
}
switch(currentDeptLevel)
{
case 1:
{
//Member has given much money
m.StartLogEvent($"Excess amount of payments", LogEvent.eEventType.EMail, "automatic");
if (sm != null)
{
FormMail below2sm = FormMail.GenerateBalanceNegativeNotify2SM().ReplaceReflect(m);
below2sm.To = $"{sm.Nickname} <{sm.EMail}>";
m.CurrentLog.SubEvents.Add(below2sm.Send());
FormMail above200 = FormMail.GenerateBalanceAbove200NotifySM().ReplaceReflect(m);
above200.To = $"{sm.Nickname} <{sm.EMail}>";
m.CurrentLog.SubEvents.Add(above200.Send());
} else
Console.WriteLine("ERROR: CheckBalance_PostDegrade: sm = null");
}
} else if (m.AccountBalance < 0)
{
if (!skipInsufficientNotify)
} break;
case 0:
{
m.StartLogEvent($"Insufficient amount of payments #1", LogEvent.eEventType.EMail, "automatic");
m.CurrentLog.SubEvents.Add(FormMail.GenerateBalanceNegativeMemberNotify1().Send(m));
}
} else if (m.AccountBalance > 200 * 100)
{
m.StartLogEvent($"Excess amount of payments", LogEvent.eEventType.EMail, "automatic");
if (sm != null)
{
FormMail above200 = FormMail.GenerateBalanceAbove200NotifySM().ReplaceReflect(m);
above200.To = $"{sm.Nickname} <{sm.EMail}>";
m.CurrentLog.SubEvents.Add(above200.Send());
} else
Console.WriteLine("ERROR: CheckBalance_PostDegrade: sm = null");
//all is fine.
} break;
case -1:
{
if (!skipInsufficientNotify)
{
m.StartLogEvent($"Insufficient amount of payments #1", LogEvent.eEventType.EMail, "automatic");
m.CurrentLog.SubEvents.Add(FormMail.GenerateBalanceNegativeMemberNotify1().Send(m));
}
} break;
case -2:
{
if (!skipInsufficientNotify)
{
m.StartLogEvent($"Insufficient amount of payments #2", LogEvent.eEventType.EMail, "automatic");
m.CurrentLog.SubEvents.Add(FormMail.GenerateBalanceNegativeMemberNotify2().Send(m));
if (sm != null)
{
FormMail below2sm = FormMail.GenerateBalanceNegativeNotify2SM().ReplaceReflect(m);
below2sm.To = $"{sm.Nickname} <{sm.EMail}>";
m.CurrentLog.SubEvents.Add(below2sm.Send());
} else
Console.WriteLine("ERROR: CheckBalance_PostDegrade: sm = null");
}
} break;
case -3:
{
if (!skipInsufficientNotify)
{
m.StartLogEvent($"Deactivation (insufficient payment)", LogEvent.eEventType.Deactivation, "automatic");
m.CurrentLog.SubEvents.Add(FormMail.GenerateBalanceNegativeMemberDeactivation().ReplaceReflect(Program.config.VS).Send(m));
m.CurrentLog.SubEvents.Add(FormMail.GenerateBalanceNegativeMemberDeactivationVS().ReplaceReflect(Program.config.VS).Send(m));
m.Status = Member.eStatus.Disabled;
}
} break;
default:
break;
}
if (m.CurrentLog != null)
{
m.LastCronjobBalanceMail = ProgramStartTime;
m.SaveToFile();
}
}
}
}

View File

@ -138,9 +138,9 @@ namespace dezentrale.model
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "Willkommen in der dezentrale, {Nickname}! Welcome to the dezentrale, {Nickname}",
Body = "Hallo {Nickname}!\n"
To = "{EMailName} <{EMail}>",
Subject = "Willkommen in der dezentrale, {EMailName}! Welcome to the dezentrale, {EMailName}",
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "Willkommen im dezentrale Hackspace.\n"
+ "Deine Mitgliedsnummer ist {NumberString}.\n"
@ -149,7 +149,7 @@ namespace dezentrale.model
+ "\n"
+ "\n"
+ "\n"
+ "Hello {Nickname}!\n"
+ "Hello {EMailName}!\n"
+ "\n"
+ "Welcome to the dezentrale hackspace.\n"
+ "Your membership number is {NumberString}.\n"
@ -165,9 +165,9 @@ namespace dezentrale.model
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
Subject = "Dein Mitgliedsaccount wurde aktiviert, {Nickname}! Your membership account is now active, {Nickname}",
Body = "Hallo {Nickname}!\n"
To = "{EMailName} <{EMail}>",
Subject = "Dein Mitgliedsaccount wurde aktiviert, {EMailName}! Your membership account is now active, {EMailName}",
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "Dein Mitgliedsaccount ist nun aktiv.\n"
+ "Um die Tür zum Gebäude zu öffnen, kannst du den Schlüssel"
@ -187,7 +187,7 @@ namespace dezentrale.model
+ "\n"
+ "\n"
+ "\n"
+ "Hello {Nickname}!\n"
+ "Hello {EMailName}!\n"
+ "\n"
+ "Your member account is now active.\n"
+ "To open the building door, you can use the key from the tresor.\n"
@ -250,9 +250,9 @@ namespace dezentrale.model
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
To = "{EMailName} <{EMail}>",
Subject = "Mitgliedschaft geändert in \"Fördermitglied\"",
Body = "Hallo {Nickname},!\n"
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "Dein Mitgliedsstatus bei uns war bisher \"reguläres Mitglied\".\n"
+ "Da du zu den letzten beiden Mitgliedsversammlungen nicht anwesend warst,"
@ -275,14 +275,14 @@ namespace dezentrale.model
//Regular / Foerdermitglied
return new FormMail()
{
To = "{Nickname} <{EMail}>",
To = "{EMailName} <{EMail}>",
Subject = "Mitgliedschaft geändert in \"{Type}\". Membership type changed to \"{Type}\"",
Body = "Hallo {Nickname},!\n"
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "Deine Mitgliedschaft bei uns wurde manuell geändert zu \"{Type}\".\n"
+ "\n"
+ "\n"
+ "Hello {Nickname},!\n"
+ "Hello {EMailName}!\n"
+ "\n"
+ "Your membership type was changed manually to \"{Type}\".\n"
+ "\n"
@ -299,9 +299,9 @@ namespace dezentrale.model
//Achtung: xx euro im Minus, bei 2 Monaten Zahlungsverzug wird dein Account deaktiviert
return new FormMail()
{
To = "{Nickname} <{EMail}>",
To = "{EMailName} <{EMail}>",
Subject = "Beitragskonto im negativen Bereich. Membership fee balance is negative.",
Body = "Hallo {Nickname},!\n"
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "Dein Konto für Mitgliedsbeiträge ist im negativen Bereich:\n"
+ "Monatsbeitrag: {PaymentAmountString} {PaymentAmountCurrency}\n"
@ -309,7 +309,7 @@ namespace dezentrale.model
+ "Bitte bezahle deine Mitgliedsbeiträge.\n"
+ "\n"
+ "\n"
+ "Hello {Nickname},!\n"
+ "Hello {EMailName}!\n"
+ "\n"
+ "Your membership account balance is negative:\n"
+ "Monthly fee: {PaymentAmountString} {PaymentAmountCurrency}\n"
@ -330,9 +330,9 @@ namespace dezentrale.model
//xx euro im Minus
return new FormMail()
{
To = "{Nickname} <{EMail}>",
To = "{EMailName} <{EMail}>",
Subject = "Beitragskonto im negativen Bereich. Membership fee balance is negative.",
Body = "Hallo {Nickname},!\n"
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "Dein Konto für Mitgliedsbeiträge ist im negativen Bereich:\n"
+ "Monatsbeitrag: {PaymentAmountString} {PaymentAmountCurrency}\n"
@ -342,7 +342,7 @@ namespace dezentrale.model
+ "Hinweis: Zum Ende des Monats wird dein Mitgliedsaccount deaktiviert.\n"
+ "\n"
+ "\n"
+ "Hello {Nickname},!\n"
+ "Hello {EMailName}!\n"
+ "\n"
+ "Your membership account balance is negative:\n"
+ "Monthly fee: {PaymentAmountString} {PaymentAmountCurrency}\n"
@ -364,9 +364,9 @@ namespace dezentrale.model
//Konto wird nun deaktiviert --> member.
return new FormMail()
{
To = "{Nickname} <{EMail}>",
To = "{EMailName} <{EMail}>",
Subject = "Dein Mitgliedsaccount wurde deaktiviert. Your membership account was disabled.",
Body = "Hallo {Nickname},\n"
Body = "Hallo {EMailName}\n"
+ "\n"
+ "Dein Mitgliedsaccount wurde wegen fehlender Beitragszahlungen deaktiviert.\n"
+ "Monatsbeitrag: {PaymentAmountString} {PaymentAmountCurrency}\n"
@ -374,7 +374,7 @@ namespace dezentrale.model
+ "Bitte wende dich zur Klärung der Sache an: {VSName} <{VSEmail}>\n"
+ "\n"
+ "\n"
+ "Hello {Nickname},\n"
+ "Hello {EMailName}\n"
+ "\n"
+ "Your membership account was disabled due to lack of payments.\n"
+ "Monthly fee: {PaymentAmountString} {PaymentAmountCurrency}\n"
@ -452,9 +452,9 @@ namespace dezentrale.model
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
To = "{EMailName} <{EMail}>",
Subject = "dezentrale - Mitgliedsbeitrag erhalten",
Body = "Hallo {Nickname}!\n"
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "Dein Mitgliedsbeitrag ist angekommen. Vielen Dank.\n"
+ "\n"
@ -472,9 +472,9 @@ namespace dezentrale.model
{
return new FormMail()
{
To = "{Nickname} <{EMail}>",
To = "{EMailName} <{EMail}>",
Subject = "dezentrale - Schlosscode hat sich geändert",
Body = "Hallo {Nickname}!\n"
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "Der Schlosscode für den Schlüsseltresor hat sich geändert.\n"
+ "Die neue Kombination lautet {KeylockCombination}\n"
@ -498,5 +498,29 @@ namespace dezentrale.model
+ "Dies ist eine automatisch generierte E-Mail.\n",
};
}
public static FormMail GenerateReducedFeeReminder()
{
return new FormMail()
{
To = "{EMailName} <{EMail}>",
Subject = "dezentrale-members - Testmail",
Body = "Hallo {EMailName}!\n"
+ "\n"
+ "In der Datenbank ist erfasst, dass dein Nachweis für ermäßigte Mitgliedschaft bis {ReducedFeeValid} gilt.\n"
+ "Bitte reiche einen gültigen Nachweis ein, um weiter ermäßigt zu bleiben.\n"
+ "\n"
+ "\n"
+ "Hello {EMailName}!\n"
+ "\n"
+ "In our database we noted your prove for reduced membership fee is valid until {ReducedFeeValid}.\n"
+ "Please hand in a new document to be able to stay with the reduced fee.\n"
+ "\n"
+ "\n"
+ "--\n"
+ "Dies ist eine automatisch generierte E-Mail.\n"
+ "This is an auto-generated E-Mail.\n",
};
}
}
}

View File

@ -70,6 +70,7 @@ namespace dezentrale.model
private ePaymentClass paymentClass = ePaymentClass.Normal;
private bool paymentNotify = false;
private DateTime memberFormDate;
private DateTime reducedFeeValid;
//This is a bit ugly but I didn't have a good idea how to solve it better.
//The main goal is to track every change to every property.
@ -106,14 +107,20 @@ namespace dezentrale.model
[XmlElement] public DateTime SpawnDate { get { return spawnDate; } set { LogPropertyChange("SpawnDate", spawnDate, value); spawnDate = value; } }
[XmlElement] public UInt64 PaymentAmount { get { return paymentAmount; } set { LogPropertyChange("PaymentAmount", paymentAmount, value); paymentAmount = value; } }
[XmlElement] public ePaymentClass PaymentClass { get { return paymentClass; } set { LogPropertyChange("PaymentClass", paymentClass, value); paymentClass = value; } }
[XmlElement] public DateTime ReducedFeeValid { get { return reducedFeeValid; } set { LogPropertyChange("ReducedFeeValid", reducedFeeValid, value); reducedFeeValid = value; } }
[XmlElement] public bool PaymentNotify { get { return paymentNotify; } set { LogPropertyChange("PaymentNotify", paymentNotify, value); paymentNotify = value; } }
[XmlElement] public DateTime MemberFormDate { get { return memberFormDate; } set { LogPropertyChange("MemberFormDate", memberFormDate, value); memberFormDate = value; } }
//internal management data
[XmlElement] public DateTime GreetedDate { get; set; }
[XmlElement] public DateTime LastPaymentProcessed { get; set; } = DateTime.Now;
[XmlElement] public uint PaymentsTotal { get; set; }
[XmlElement] public DateTime LastBalanceDegrade { get; set; } = DateTime.Now;
[XmlElement] public DateTime GreetedDate { get; set; }
[XmlElement] public DateTime LastPaymentProcessed { get; set; } = DateTime.Now;
[XmlElement] public uint PaymentsTotal { get; set; }
[XmlElement] public DateTime LastBalanceDegrade { get; set; } = DateTime.Now;
[XmlElement] public int DebtLevel { get; set; } = 0;
[XmlElement] public DateTime LastCronjobBalanceMail { get; set; } = DateTime.Now;
[XmlElement] public DateTime LastCronjobReducedFeeMail { get; set; } = DateTime.Now;
[XmlElement("MoneyTransferId")] public List<string> MoneyTransfersIds { get; set; } = new List<string>();
[XmlElement("LogEvent")] public List<LogEvent> Log { get; set; } = new List<LogEvent>();

View File

@ -36,14 +36,18 @@ namespace dezentrale.model
//while (formattedStatus.Length < 8) formattedStatus = formattedStatus + " ";
mList += $"{m.Number:D3} | {formattedBalance} | {formattedStatus} | {m.Nickname}\n";
}
totalBalance += m.AccountBalance;
if (m.AccountBalance > 0)
totalSurplus += m.AccountBalance;
else
totalDebts += m.AccountBalance;
if (minBalance > m.AccountBalance) minBalance = m.AccountBalance;
if (maxBalance < m.AccountBalance) maxBalance = m.AccountBalance;
if (m.AccountBalance < 0) membersWithNegativeBalance++;
if (m.Status == Member.eStatus.Active)
{
totalBalance += m.AccountBalance;
if (m.AccountBalance > 0)
totalSurplus += m.AccountBalance;
else
totalDebts += m.AccountBalance;
if (minBalance > m.AccountBalance) minBalance = m.AccountBalance;
if (maxBalance < m.AccountBalance) maxBalance = m.AccountBalance;
if (m.AccountBalance < 0) membersWithNegativeBalance++;
}
switch (m.Status)
{