-2

I have a table named members and table named membership records. Currently in table membership records I have column named month in which I'm saving for what month the member payed membership. And with each payment it adds new record in datagridview but for different month. Check image to see how it displays data now when user makes payment.

enter image description here

If I would alter membership records table with month names (January-December) and I want to fill with each payment, for example member John for month January that it fills column name January, and if I wanted to make payment also for member John (same ID, let's say ID 1) and month February that it doesn't add new record in database but that it updates member John ID 1 for column February? So it would show name (John), DoB, OIB (personal identification number), gender, January, February, etc. all the way to December, type of membership (monthly or yearly) and fee of the membership?

Basically I want to display only one record for each member that makes payment but that in one record it holds all months and with each payment for different month it adds month member payed.

This is how I'd like to display it in datagridview. Note that I made this table quickly and it's not the same as in the picture above ^^ and it's here only to show you what I mean, I will delete it and I won't include it in my database and my project.

enter image description here

 private void Plati_Clanarinu_tipka_Click(object sender, EventArgs e)
    {
        MySqlConnection connection;
        string conString = "server=localhost; database=bazakudsumari; uid=David; password=root;";
        try
        {
            connection = new MySqlConnection();
            connection.ConnectionString = conString;
            connection.Open();

            if (string.IsNullOrWhiteSpace(iznos_clanarine.Text) || (string.IsNullOrWhiteSpace(odaberi_mjesec.Text)) || (string.IsNullOrWhiteSpace(godina_uplate_clanarine.Text)))
            {
                MessageBox.Show(" Ispunite sva polja prije naplate članarine! ");
            }
            else
            {
                string Query = "INSERT INTO evidencija_clanarina (id_clana, mjesec, godina, vrsta, iznos) VALUES (@id_clana, @mjesec, @godina, @vrsta, @iznos)";

                using (MySqlCommand command = new MySqlCommand(Query, connection))
                {
                    command.Parameters.AddWithValue("@id_clana", Convert.ToInt32(id_clana.Text));
                    command.Parameters.AddWithValue("@mjesec", odaberi_mjesec.Text);
                    command.Parameters.AddWithValue("@godina", godina_uplate_clanarine.Text);
                    if (mjesecna_clanarina.Checked)
                    {
                        command.Parameters.AddWithValue("@vrsta", "Mjesečna");
                        command.Parameters.AddWithValue("@iznos", iznos_clanarine.Text);
                    }
                    else
                    {
                        command.Parameters.AddWithValue("@vrsta", "Godišnja");
                        command.Parameters.AddWithValue("@iznos", iznos_clanarine.Text);
                    }

                    command.ExecuteNonQuery();
                }

                MessageBox.Show("Uspješno plaćena članarina!");

                DialogResult dialogResult = MessageBox.Show(" Želite li naplatiti još jednu članarinu? ", "", MessageBoxButtons.YesNo);
                if (dialogResult == DialogResult.Yes)
                {
                    this.Focus();
                }
                else
                {
                    this.Close();
                }

                odaberi_mjesec.Text = string.Empty;
                iznos_clanarine.Text = string.Empty;
                godina_uplate_clanarine.Text = string.Empty;
                mjesecna_clanarina.Checked = false;
                godisnja_clanarina.Checked = false;
                baza_podataka_clanovi_clanarine.Refresh();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

This is code I'm currently using for making payments, all of the code is in my language (Croatian) and I know that I need to change Query and Parameters. I need to know if it's possible to do what I'm asking and how to do it.

(id_clana = id_member, mjesec = month, godina = year, vrsta = type, Mjesečna = Monthly, iznos = fee, Godišnja = Yearly). This is quick translate of what I have in my code so you guys can manage.

  • 1
    what you mean in one query? Those are two different query commands. – daremachine Sep 27 '19 at 23:40
  • 1
    In a normal accounting system you would record the payments separately, even if you got thirty payments in one month, and group them into monthly amounts at the reporting level. Recording separate payments allows accountants to do reconciliation. – AlwaysLearning Sep 27 '19 at 23:40
  • @AlwaysLearning I am recording payments in different table, output in datagridview are two joined tables, members and the one I'm recording payments in. – David Hruškar Sep 27 '19 at 23:47
  • Please Post your table as text or as dbfiddle . The translation is a good point. – nbk Sep 27 '19 at 23:47
  • @nbk I've created that table and inserted data by myself in Workbench and I've already deleted it.. – David Hruškar Sep 27 '19 at 23:57
  • tja, then look at this https://stackoverflow.com/questions/1241178/mysql-rows-to-columns it explains how you can make rows into columns – nbk Sep 28 '19 at 00:10

2 Answers2

0

Probably you need INSERT ON DUPLICATE KEY UPDATE

INSERT INTO t1 (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=3;
exxbrain
  • 596
  • 4
  • 11
0

If you're already recording payments in a first table, don't record them again in a second table, just transform the first table data into what you want to show:

--assumed structure of payments table
MemberId, PaymentDate, Type, Amount
1, 2001-01-01, fee, 30
1, 2001-02-01, fee, 20
1, 2001-02-02, fee, 10

--assumes structure of members table
Id, Name
1, John

Query:

SELECT
  m.Id,
  m.Name,
  SUM(CASE WHEN MONTH(p.PaymentDate) = 1 THEN p.Amount END) as JanTotal,
  SUM(CASE WHEN MONTH(p.PaymentDate) = 2 THEN p.Amount END) as FebTotal,
  SUM(CASE WHEN MONTH(p.PaymentDate) = 3 THEN p.Amount END) as MarTotal,
  ...
  SUM(CASE WHEN MONTH(p.PaymentDate) = 12 THEN p.Amount END) as DecTotal
FROM
  Members m
  INNER JOIN Payments p ON m.id = p.memberid
WHERE
  p.Type = 'fee' and YEAR(p.PaymentDate) = 2001
GROUP BY m.Id, m.Name

Output:

1,John,30,30,0,0,0,0,0,0,0,0,0,0

Incidentally, did you know that those 30+ lines of code you wrote to make a sql command, set its text, fill its parameters, run it etc, could be reduced to just one by using Dapper? Take a look - not as heavy as entity framework and you still get to write the sql yourself if that's your bag - http://dapper-tutorial.net - you'll see straight off from the examples that it will save you hours of boring coding filling parameter collections and dragging results out of a reader to turn them into a strongly typed object

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • I'm saving members in one table, then saving payments in another table and then outputting results in datagridview by joining tables 1 and two (members and payments). I added a foreign key into a table payments so when making a payment through app I know for which member ID I'm making a payment. Well, it's too late now in project to start using Dapper, I'd have to learn to use it first and I'm 98% done with my app so Dapper is not an option right now. Maybe in future. – David Hruškar Sep 28 '19 at 11:58
  • Anyway, thanks for your comment and solution. I'm trying a different approach by having columns Payed and Owes in table membership records and inserting months into one of those 2 columns when a member makes a payment or when he doesn't make a payment. – David Hruškar Sep 28 '19 at 12:00
  • No probs. If you get stuck feel free to come back. Before you start your next project take a quick look at Dapper - there isn't really anything to learn that you don't already know (you already know how to create a class, write an sql and form a list of sql parameters; that's pretty much it) - it's absolutely not EF, fluent mappings, torturous LINQ etc. Best of luck! – Caius Jard Sep 28 '19 at 17:42
  • Well, actually, I am stuck haha. I've dropped the whole idea that I wrote in original post and I added columns Payed and Owes. And now when member John says to me that he doesn't have money for January membership fee, I pay the membership through app but I put on radiobutton that he owes me money for that month (January) and that works great. But let's say John comes back after 10 days and says to me I have money, then I go into my app, select John, select the month he did not pay me (January) and now I select Payed radiobutton. (I'm gonna continue in another comment). – David Hruškar Sep 28 '19 at 17:55
  • And instead of updating the current row he's paying, my app adds another row in datagridview with new information that John payed for month January. Old record where John didn't pay January is still visible in datagridview, and I don't know how to fix it so that it updates row that holds month January and Owed columns. – David Hruškar Sep 28 '19 at 17:57
  • Surely the only way you can add another row in the DGV is because you added another row to the table that drives the view. If you want to edit the existing row surely you'd either just find it in the table (use a loop, or Select, or Find, or ask the user to find it by clicking) and edit the existing row's properties. Kinda gonna need to see more info to be any more specific but your DGV should be bound to your datatable through a bindingsource, which has a Current property, so to get the DAtaTable row related to the grid line the user clicked on it's: (cont..) – Caius Jard Sep 29 '19 at 07:12
  • `var row = (myBindingSource.Current as DataRowView)?.Row` - if you're using a strongly typed table then this will be - `var row = (myBindingSource.Current as DataRowView)?.Row as MyStronglyTypedRowTypeName` so the full code might look like `blah MarkAsPaidButton_Click(...){ var row = (myBindingSource.Current as DataRowView)?.Row; if(row == null){ MessageBox(...); } row["Owed"] = false; row["Paid"] = true; }` or if strongly typed: `blah XButton_Click(...){ var row = (myBindingSource.Current as DataRowView)?.Row as ...; if(row == null){ MessageBox(...); } row.Owed = false; row.Paid = true; }` – Caius Jard Sep 29 '19 at 07:18
  • Thanks, I solved it last night by adding update button, so when I save John for month January that he didn't pay I just load John, select month he didn't pay and change it to payed. And it works perfectly. Thank you anyway. Sorry for bothering you. :) – David Hruškar Sep 29 '19 at 15:31