Add telephone numbers

This commit is contained in:
2023-05-27 17:56:17 +02:00
parent 70ad8188c4
commit c1b8b68513
6 changed files with 195 additions and 34 deletions

View File

@ -30,6 +30,7 @@ namespace Elwig.Helpers {
public DbSet<Branch> Branches { get; private set; } public DbSet<Branch> Branches { get; private set; }
public DbSet<Member> Members { get; private set; } public DbSet<Member> Members { get; private set; }
public DbSet<BillingAddr> BillingAddresses { get; private set; } public DbSet<BillingAddr> BillingAddresses { get; private set; }
public DbSet<MemberTelNr> MemberTelephoneNrs { get; private set; }
public DbSet<AreaCom> AreaCommitments { get; private set; } public DbSet<AreaCom> AreaCommitments { get; private set; }
public DbSet<AreaComAttr> AreaCommitmentAttributes { get; private set; } public DbSet<AreaComAttr> AreaCommitmentAttributes { get; private set; }
public DbSet<Season> Seasons { get; private set; } public DbSet<Season> Seasons { get; private set; }

View File

@ -141,7 +141,7 @@ namespace Elwig.Helpers {
public static ValidationResult CheckPhoneNumber(TextBox input, bool required) { public static ValidationResult CheckPhoneNumber(TextBox input, bool required) {
string text = ""; string text = "";
int pos = input.CaretIndex; int pos = input.CaretIndex;
for (int i = 0, v = 0; i < input.Text.Length && v < 15; i++) { for (int i = 0, v = 0; i < input.Text.Length && v <= 15; i++) {
char ch = input.Text[i]; char ch = input.Text[i];
if (v == 0 && input.Text.Length - i >= 2 && ch == '0' && input.Text[i + 1] == '0') { if (v == 0 && input.Text.Length - i >= 2 && ch == '0' && input.Text[i + 1] == '0') {
v++; i++; v++; i++;
@ -154,21 +154,30 @@ namespace Elwig.Helpers {
} else if (v == 0 && ch == '+') { } else if (v == 0 && ch == '+') {
v++; v++;
text += ch; text += ch;
} else if (v > 0 && char.IsAsciiDigit(ch)) { } else if (v > 0 && (char.IsAsciiDigit(ch) || ch == ' ' || ch == '-')) {
if (PHONE_NRS.Any(kv => text == "+" + kv.Key)) if (PHONE_NRS.Any(kv => text == "+" + kv.Key))
text += ' '; text += ' ';
if (text.StartsWith("+43 ")) { if (text.StartsWith("+43 ")) {
var nr = text[4..]; var nr = text[4..];
var vws = PHONE_NRS["43"]; var vws = PHONE_NRS["43"];
if (v >= 4 && v - 4 < vws.Length && vws[v - 4].Any(vw => nr.StartsWith(vw))) if (!text.EndsWith(" ") && v >= 4 && v - 4 < vws.Length && vws[v - 4].Any(vw => nr.StartsWith(vw))) {
text += ' '; text += ' ';
else if (nr == "1") } else if (nr == "1") {
text += ' '; text += ' ';
else if (v == 7 && nr.Length == 4) } else if (v == 7 && nr.Length == 4) {
text += ' '; text += ' ';
}
var vw = text.Split(" ");
if (char.IsAsciiDigit(ch)) {
v++;
text += ch;
} else if (char.IsAsciiDigit(text[^1]) && vw.Length > 2 && v >= 10 && (vw[1].Length - 1 >= vws.Length || !vws[vw[1].Length - 1].Any(v => vw[1].StartsWith(v)))) {
text += ch;
}
} else {
v++;
text += ch;
} }
v++;
text += ch;
} }
if (i == input.CaretIndex - 1) if (i == input.CaretIndex - 1)
pos = text.Length; pos = text.Length;
@ -182,7 +191,7 @@ namespace Elwig.Helpers {
return new(false, "Telefonnummer zu kurz"); return new(false, "Telefonnummer zu kurz");
} }
return new(true, null); return new(char.IsAsciiDigit(text[^1]), null);
} }
public static ValidationResult CheckEmailAddress(TextBox input, bool required) { public static ValidationResult CheckEmailAddress(TextBox input, bool required) {

View File

@ -128,15 +128,6 @@ namespace Elwig.Models {
[Column("email")] [Column("email")]
public string? Email { get; set; } public string? Email { get; set; }
[Column("phone_landline")]
public string? PhoneLandline { get; set; }
[Column("phone_mobile_1")]
public string? PhoneMobile1 { get; set; }
[Column("phone_mobile_2")]
public string? PhoneMobile2 { get; set; }
[Column("default_kgnr")] [Column("default_kgnr")]
public int? DefaultKgNr { get; set; } public int? DefaultKgNr { get; set; }
@ -177,6 +168,9 @@ namespace Elwig.Models {
[InverseProperty("Member")] [InverseProperty("Member")]
public virtual ISet<Delivery> Deliveries { get; private set; } public virtual ISet<Delivery> Deliveries { get; private set; }
[InverseProperty("Member")]
public virtual ISet<MemberTelNr> TelephoneNumbers { get; private set; }
public string FullAddress => $"{Address}, {PostalDest.AtPlz.Plz} {PostalDest.AtPlz.Ort.Name}"; public string FullAddress => $"{Address}, {PostalDest.AtPlz.Plz} {PostalDest.AtPlz.Ort.Name}";
public int SearchScore(IEnumerable<string> keywords) { public int SearchScore(IEnumerable<string> keywords) {

View File

@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;
namespace Elwig.Models {
[Table("member_telephone_number"), PrimaryKey("MgNr", "Nr")]
public class MemberTelNr {
[Column("mgnr")]
public int MgNr { get; set; }
[Column("nr")]
public int Nr { get; set; }
[Column("type")]
public string Type { get; set; }
[Column("number")]
public string Number { get; set; }
[Column("comment")]
public string? Comment { get; set; }
[ForeignKey("MgNr")]
public virtual Member Member { get; private set; }
}
}

View File

@ -160,29 +160,68 @@
<GroupBox Header="Kontaktdaten" Grid.Column="1" Grid.Row="3" Grid.RowSpan="2" Margin="5,5,5,5"> <GroupBox Header="Kontaktdaten" Grid.Column="1" Grid.Row="3" Grid.RowSpan="2" Margin="5,5,5,5">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="115"/> <ColumnDefinition Width="135"/>
<ColumnDefinition/> <ColumnDefinition Width="*" MinWidth="180"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Label Content="E-Mail-Adresse:" Margin="10,10,0,0" Grid.Column="0"/> <Label Content="E-Mail-Adresse:" Margin="10,10,0,0" Grid.Column="0"/>
<TextBox x:Name="EmailInput" Margin="0,10,10,0" Grid.Column="1" <TextBox x:Name="EmailInput" Margin="0,10,10,0" Grid.Column="1" Grid.ColumnSpan="2"
TextChanged="EmailInput_TextChanged" LostFocus="EmailInput_LostFocus"/> TextChanged="EmailInput_TextChanged" LostFocus="EmailInput_LostFocus"/>
<Label Content="Tel.-Nr. (Festnetz):" Margin="10,40,0,0" Grid.Column="0"/> <ComboBox x:Name="PhoneNr1TypeInput" DisplayMemberPath="Value" Margin="6,40,5,0" FontSize="12" Padding="6,4,4,4"/>
<TextBox x:Name="PhoneLandlineInput" Margin="0,40,10,0" Grid.Column="1" <TextBox x:Name="PhoneNr1Input" Margin="0,40,5,0" Grid.Column="1"
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
<TextBox x:Name="PhoneNr1CommentInput" Margin="0,40,10,0" Grid.Column="2"
TextChanged="TextBox_TextChanged"/>
<Label Content="Fax-Nr.:" Margin="10,70,0,0" Grid.Column="0"/> <ComboBox x:Name="PhoneNr2TypeInput" DisplayMemberPath="Value" Margin="6,70,5,0" FontSize="12" Padding="6,4,4,4"/>
<TextBox x:Name="FaxInput" Margin="0,70,10,0" Grid.Column="1" <TextBox x:Name="PhoneNr2Input" Margin="0,70,5,0" Grid.Column="1"
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
<TextBox x:Name="PhoneNr2CommentInput" Margin="0,70,10,0" Grid.Column="2"
TextChanged="TextBox_TextChanged"/>
<Label Content="Tel.-Nr. (mobil):" Margin="10,100,0,0" Grid.Column="0"/> <ComboBox x:Name="PhoneNr3TypeInput" DisplayMemberPath="Value" Margin="6,100,5,0" FontSize="12" Padding="6,4,4,4"/>
<TextBox x:Name="PhoneMobile1Input" Margin="0,100,10,0" Grid.Column="1" <TextBox x:Name="PhoneNr3Input" Margin="0,100,5,0" Grid.Column="1"
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
<TextBox x:Name="PhoneNr3CommentInput" Margin="0,100,10,0" Grid.Column="2"
TextChanged="TextBox_TextChanged"/>
<Label Content="Tel.-Nr. (mobil):" Margin="10,130,0,0" Grid.Column="0"/> <ComboBox x:Name="PhoneNr4TypeInput" DisplayMemberPath="Value" Margin="6,130,5,0" FontSize="12" Padding="6,4,4,4"/>
<TextBox x:Name="PhoneMobile2Input" Margin="0,130,10,0" Grid.Column="1" <TextBox x:Name="PhoneNr4Input" Margin="0,130,5,0" Grid.Column="1"
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
<TextBox x:Name="PhoneNr4CommentInput" Margin="0,130,10,0" Grid.Column="2"
TextChanged="TextBox_TextChanged"/>
<ComboBox x:Name="PhoneNr5TypeInput" DisplayMemberPath="Value" Margin="6,160,5,0" FontSize="12" Padding="6,4,4,4"/>
<TextBox x:Name="PhoneNr5Input" Margin="0,160,5,0" Grid.Column="1"
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
<TextBox x:Name="PhoneNr5CommentInput" Margin="0,160,10,0" Grid.Column="2"
TextChanged="TextBox_TextChanged"/>
<ComboBox x:Name="PhoneNr6TypeInput" DisplayMemberPath="Value" Margin="6,190,5,0" FontSize="12" Padding="6,4,4,4"/>
<TextBox x:Name="PhoneNr6Input" Margin="0,190,5,0" Grid.Column="1"
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
<TextBox x:Name="PhoneNr6CommentInput" Margin="0,190,10,0" Grid.Column="2"
TextChanged="TextBox_TextChanged"/>
<ComboBox x:Name="PhoneNr7TypeInput" DisplayMemberPath="Value" Margin="6,220,5,0" FontSize="12" Padding="6,4,4,4"/>
<TextBox x:Name="PhoneNr7Input" Margin="0,220,5,0" Grid.Column="1"
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
<TextBox x:Name="PhoneNr7CommentInput" Margin="0,220,10,0" Grid.Column="2"
TextChanged="TextBox_TextChanged"/>
<ComboBox x:Name="PhoneNr8TypeInput" DisplayMemberPath="Value" Margin="6,250,5,0" FontSize="12" Padding="6,4,4,4"/>
<TextBox x:Name="PhoneNr8Input" Margin="0,250,5,0" Grid.Column="1"
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
<TextBox x:Name="PhoneNr8CommentInput" Margin="0,250,10,0" Grid.Column="2"
TextChanged="TextBox_TextChanged"/>
<ComboBox x:Name="PhoneNr9TypeInput" DisplayMemberPath="Value" Margin="6,280,5,0" FontSize="12" Padding="6,4,4,4"/>
<TextBox x:Name="PhoneNr9Input" Margin="0,280,5,0" Grid.Column="1"
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
<TextBox x:Name="PhoneNr9CommentInput" Margin="0,280,10,0" Grid.Column="2"
TextChanged="TextBox_TextChanged"/>
</Grid> </Grid>
</GroupBox> </GroupBox>
<GroupBox Header="Bankverbindung" Grid.Column="1" Grid.Row="5" Margin="5,5,5,10"> <GroupBox Header="Bankverbindung" Grid.Column="1" Grid.Row="5" Margin="5,5,5,10">

View File

@ -9,12 +9,20 @@ using Elwig.Helpers;
using Elwig.Models; using Elwig.Models;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.ChangeTracking;
using System.Collections.ObjectModel;
namespace Elwig.Windows { namespace Elwig.Windows {
public partial class MemberAdminWindow : AdministrationWindow { public partial class MemberAdminWindow : AdministrationWindow {
private List<string> TextFilter = new(); private List<string> TextFilter = new();
private readonly RoutedCommand CtrlF = new(); private readonly RoutedCommand CtrlF = new();
private readonly (ComboBox, TextBox, TextBox)[] PhoneNrInputs;
private static ObservableCollection<KeyValuePair<string, string>> PhoneNrTypes { get; set; } = new() {
new("landline", "Tel.-Nr. (Festnetz)"),
new("mobile", "Tel.-Nr. (mobil)"),
new("fax", "Fax-Nr."),
};
public MemberAdminWindow() { public MemberAdminWindow() {
InitializeComponent(); InitializeComponent();
@ -30,10 +38,23 @@ namespace Elwig.Windows {
AddressInput, PlzInput, OrtInput, BillingOrtInput, AddressInput, PlzInput, OrtInput, BillingOrtInput,
BusinessSharesInput, BranchInput, DefaultKgInput BusinessSharesInput, BranchInput, DefaultKgInput
}; };
PhoneNrInputs = new (ComboBox, TextBox, TextBox)[] {
(PhoneNr1TypeInput, PhoneNr1Input, PhoneNr1CommentInput),
(PhoneNr2TypeInput, PhoneNr2Input, PhoneNr2CommentInput),
(PhoneNr3TypeInput, PhoneNr3Input, PhoneNr3CommentInput),
(PhoneNr4TypeInput, PhoneNr4Input, PhoneNr4CommentInput),
(PhoneNr5TypeInput, PhoneNr5Input, PhoneNr5CommentInput),
(PhoneNr6TypeInput, PhoneNr6Input, PhoneNr6CommentInput),
(PhoneNr7TypeInput, PhoneNr7Input, PhoneNr7CommentInput),
(PhoneNr8TypeInput, PhoneNr8Input, PhoneNr8CommentInput),
(PhoneNr9TypeInput, PhoneNr9Input, PhoneNr9CommentInput),
};
foreach (var input in PhoneNrInputs) input.Item1.ItemsSource = PhoneNrTypes;
} }
private void Window_Loaded(object sender, RoutedEventArgs evt) { private void Window_Loaded(object sender, RoutedEventArgs evt) {
ActiveMemberInput.IsChecked = true; ActiveMemberInput.IsChecked = true;
UpdatePhoneNrInputVisibility();
} }
private async Task RefreshMemberList() { private async Task RefreshMemberList() {
@ -108,6 +129,31 @@ namespace Elwig.Windows {
await RefreshMemberList(); await RefreshMemberList();
} }
private void SetPhoneNrInput(int nr, string? type, string? number, string? comment) {
var inputs = PhoneNrInputs[nr];
inputs.Item1.SelectedItem = (type == null) ? null : inputs.Item1.ItemsSource.Cast<KeyValuePair<string, string>>().FirstOrDefault(p => p.Key == type);
inputs.Item2.Text = number;
inputs.Item3.Text = comment;
}
private (string, string, string?)? GetPhonenrInput(int nr) {
var inputs = PhoneNrInputs[nr];
var number = inputs.Item2.Text;
if (string.IsNullOrEmpty(number))
return null;
var type = (inputs.Item1.SelectedItem as KeyValuePair<string, string>?)?.Key ?? (number.StartsWith("+43 ") && number[4] == '6' ? "mobile" : "landline");
var comment = inputs.Item3.Text;
return (type, number, comment == "" ? null : comment);
}
private void SetPhoneNrInputVisible(int nr, bool visible) {
var inputs = PhoneNrInputs[nr];
var vis = visible ? Visibility.Visible : Visibility.Hidden;
inputs.Item1.Visibility = vis;
inputs.Item2.Visibility = vis;
inputs.Item3.Visibility = vis;
}
private void MemberList_SelectionChanged(object sender, RoutedEventArgs evt) { private void MemberList_SelectionChanged(object sender, RoutedEventArgs evt) {
RefreshInputs(); RefreshInputs();
} }
@ -123,6 +169,7 @@ namespace Elwig.Windows {
HideNewEditDeleteButtons(); HideNewEditDeleteButtons();
ShowSaveResetCancelButtons(); ShowSaveResetCancelButtons();
UnlockInputs(); UnlockInputs();
UpdatePhoneNrInputVisibility(true);
InitInputs(); InitInputs();
LockSearchInputs(); LockSearchInputs();
} }
@ -137,6 +184,7 @@ namespace Elwig.Windows {
HideNewEditDeleteButtons(); HideNewEditDeleteButtons();
ShowSaveResetCancelButtons(); ShowSaveResetCancelButtons();
UnlockInputs(); UnlockInputs();
UpdatePhoneNrInputVisibility(true);
LockSearchInputs(); LockSearchInputs();
} }
@ -164,6 +212,7 @@ namespace Elwig.Windows {
HideSaveResetCancelButtons(); HideSaveResetCancelButtons();
ShowNewEditDeleteButtons(); ShowNewEditDeleteButtons();
LockInputs(); LockInputs();
UpdatePhoneNrInputVisibility();
UnlockSearchInputs(); UnlockSearchInputs();
await RefreshMemberList(); await RefreshMemberList();
SearchInput.Text = ""; SearchInput.Text = "";
@ -189,6 +238,7 @@ namespace Elwig.Windows {
RefreshInputs(); RefreshInputs();
ClearInputStates(); ClearInputStates();
LockInputs(); LockInputs();
UpdatePhoneNrInputVisibility();
UnlockSearchInputs(); UnlockSearchInputs();
} }
@ -259,6 +309,17 @@ namespace Elwig.Windows {
ActiveMemberInput.IsEnabled = true; ActiveMemberInput.IsEnabled = true;
} }
private void UpdatePhoneNrInputVisibility(bool extra = false) {
bool lastVisible = true;
var m = (Member)MemberList.SelectedItem;
for (int i = 0; i < PhoneNrInputs.Length; i++) {
var input = PhoneNrInputs[i];
var vis = !string.IsNullOrEmpty(input.Item2.Text) || (m?.TelephoneNumbers.Any(p => p.Nr - 1 == i) ?? false);
SetPhoneNrInputVisible(i, vis || (extra && lastVisible));
lastVisible = vis;
}
}
private async Task<Member> UpdateMember(Member m) { private async Task<Member> UpdateMember(Member m) {
int newMgNr = int.Parse(MgNrInput.Text); int newMgNr = int.Parse(MgNrInput.Text);
m.PredecessorMgNr = (PredecessorMgNrInput.Text == "") ? null : int.Parse(PredecessorMgNrInput.Text); m.PredecessorMgNr = (PredecessorMgNrInput.Text == "") ? null : int.Parse(PredecessorMgNrInput.Text);
@ -272,9 +333,6 @@ namespace Elwig.Windows {
m.Address = AddressInput.Text; m.Address = AddressInput.Text;
m.Email = (EmailInput.Text == "") ? null : EmailInput.Text; m.Email = (EmailInput.Text == "") ? null : EmailInput.Text;
m.PhoneLandline = (PhoneLandlineInput.Text == "") ? null : PhoneLandlineInput.Text.Replace(" ", "");
m.PhoneMobile1 = (PhoneMobile1Input.Text == "") ? null : PhoneMobile1Input.Text.Replace(" ", "");
m.PhoneMobile2 = (PhoneMobile2Input.Text == "") ? null : PhoneMobile2Input.Text.Replace(" ", "");
m.Iban = (IbanInput.Text == "") ? null : IbanInput.Text.Replace(" ", ""); m.Iban = (IbanInput.Text == "") ? null : IbanInput.Text.Replace(" ", "");
m.Bic = (BicInput.Text == "") ? null : BicInput.Text; m.Bic = (BicInput.Text == "") ? null : BicInput.Text;
@ -324,6 +382,29 @@ namespace Elwig.Windows {
} }
} }
for (int i = 0, j = 0; i < PhoneNrInputs.Length; i++) {
var input = GetPhonenrInput(i);
var phoneNr = m.TelephoneNumbers.FirstOrDefault(p => p.Nr - 1 == i);
if (input == null) {
if (phoneNr != null) {
Context.Remove(phoneNr);
}
} else {
var pInput = input.Value;
MemberTelNr p = phoneNr ?? Context.CreateProxy<MemberTelNr>();
p.Nr = ++j;
p.Type = pInput.Item1;
p.Number = pInput.Item2;
p.Comment = pInput.Item3;
if (phoneNr == null) {
p.MgNr = newMgNr;
await Context.AddAsync(p);
} else {
Context.Update(p);
}
}
}
await Context.SaveChangesAsync(); await Context.SaveChangesAsync();
if (newMgNr != m.MgNr) { if (newMgNr != m.MgNr) {
@ -369,9 +450,16 @@ namespace Elwig.Windows {
} }
EmailInput.Text = m.Email; EmailInput.Text = m.Email;
PhoneLandlineInput.Text = m.PhoneLandline; var phoneNrs = m.TelephoneNumbers.OrderBy(p => p.Nr).ToList();
PhoneMobile1Input.Text = m.PhoneMobile1; for (int i = 0; i < PhoneNrInputs.Length; i++) {
PhoneMobile2Input.Text = m.PhoneMobile2; if (i < phoneNrs.Count) {
var phoneNr = phoneNrs[i];
SetPhoneNrInput(i, phoneNr.Type, phoneNr.Number, phoneNr.Comment);
} else {
SetPhoneNrInput(i, null, null, null);
}
}
UpdatePhoneNrInputVisibility(IsEditing || IsCreating);
IbanInput.Text = m.Iban; IbanInput.Text = m.Iban;
BicInput.Text = m.Bic; BicInput.Text = m.Bic;
@ -453,5 +541,10 @@ namespace Elwig.Windows {
private void PredecessorMgNrInput_LostFocus(object sender, RoutedEventArgs evt) { private void PredecessorMgNrInput_LostFocus(object sender, RoutedEventArgs evt) {
InputLostFocus((TextBox)sender, Validator.CheckPredecessorMgNr); InputLostFocus((TextBox)sender, Validator.CheckPredecessorMgNr);
} }
private new void PhoneNrInput_TextChanged(object sender, RoutedEventArgs evt) {
base.PhoneNrInput_TextChanged(sender, evt);
UpdatePhoneNrInputVisibility(IsEditing || IsCreating);
}
} }
} }