|
hello Pete,
The program i'm trying to make is supposedly for a quick service restaurant. More like a fastfood (e.g. Mcdonalds). It would be much better if I can get the data passed on to the KDS terminal immediately after being entered on the POS. If the KDS terminal cannot connect to the server, the operation will halt.
|
|
|
|
|
Then have the KDS terminal poll at a faster interval (e.g. 5 seconds). The architecture you are proposing currently is far too fragile.
|
|
|
|
|
What you're proposing will not work. Sure, you can send the order, but what if the second machine is down or the network is down at the time?? Your design is not fault tolerant at all, not to mention unscalable.
Once the order is sent, your POS machine no longer has any record of it once the other machines come back up. So what happened to the order and how are you going to get it back??
The POS machine should put the order in a submitted orders table in a database. The RDS machine would then have to pickup the orders from that table WHEN IT CAN, not when the POS sends it.
|
|
|
|
|
Pete O'Hanlon wrote: And what happens if you can't connect? You can't transmit the data then
Then the servers start manually carrying the tickets to the kitchen.
Pete O'Hanlon wrote: Would a one minute delay really cause that much of a problem?
That is pretty long for a high volume restaurant. Assuming single floor layout a server can deliver it to the kitchen in less time than that.
|
|
|
|
|
Member 8605543 wrote: I would prefer to have the data transferred realtime (upon input), rather than
the KDS sending frequent queries to the database.
Incorrect.
Polling is exactly what you want in that situation.
Casinos tend to be the single largest single location multi-business type POS deployments. You could implement a polling system where all of the resturants in the casino used the same system and still easily handle the load using a single database.
Any other resturant would have far less traffic than that.
|
|
|
|
|
What happens if, during the KDS operation you realise it needs some more POS, do you send it back to the POS? You are REALLY going to have to look at your workflow carefully.
Personally I'd go with the polling a table solution, it being the simplest and probably the most robust.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Hi Mycroft,
Upon submission of data by the POS to the KDS, it cannot send back to POS. Just like those being used in fastfood chains, when you've already paid for your meal, you cannot make any changes, not unless you make a new transaction. Polling a table is another option. Is this what you mean: POS enters data to database, then the KDS queries the database for new entries every specified interval? isnt this cpu intensive? thanks! - Carlos
|
|
|
|
|
Member 8605543 wrote: when you've already paid for your meal,
Even more of a reason to put this stuff in the database without going to the RDS machine. Once you take customer money, losing their order is very unacceptable.
Member 8605543 wrote: isnt this cpu intensive?
You're making a small database query every 10 seconds, so no, it's not.
|
|
|
|
|
Thanks Dave! Ill do a research on how to poll a database every specified intervals. what would be an acceptable interval rate for this kind of application(fastfood)? 3 seconds?
I got your point. Indeed I would have to put it in a database so when the network is down, or KDS is unavailable, It can still fetch data as soon as it goes back.
|
|
|
|
|
I would have thought that 10 seconds would be fast enough.
|
|
|
|
|
Member 8605543 wrote: Just like those being used in fastfood chains, when you've already paid for your
meal, you cannot make any changes, not unless you make a new transaction
Not sure about fast food itself but in other types of restaurants you can adjust orders on the POS.
Member 8605543 wrote: isnt this cpu intensive?
Not as long as you put a small delay in it. Small is like a second.
|
|
|
|
|
I'm going to disagree with almost everyone else and say that you want to do this with sockets, albeit with the central server storing information in a database for audit/recovery reasons. That's because polling is almost always an inferior solution (you're transferring, at best, the same data, and generally the same data plus a large number of empty poll requests, while having a slower response time), and not necessary in this case.
The data recovery scenarios are:
- POS down: everything has to be manual anyway, in either case
- Server down: ditto
- KDS down: this is the one you have to worry about
The server should be in primary control of the data. The POS and KDS software should both keep a socket open to it, assuming you're running on hardware that can do that (unless you have 1000 tills you should be fine; if not, you might need to use a different approach, i.e. fire-and-forget web service calls for POS->server).
When you make an order, the POS should send messages to the server: make an order, order paid for, order modified (if applicable), and allow the front desk staff to post notes to a particular order. When an order is ready (I guess this is when it's made for a fast food place) the server should, as well as writing to its local data store (which it should do with every order status update for tracking purposes), also push a message to the KDS to add an item to its queue. When the kitchen finishes with an order they should be able to select the order on the KDS and that will cause a status update message to go back to the server, which the server will then forward to the appropriate till (if you want the information there).
If the kitchen rejects an order (for example if they're out of some ingredient), that should also be sent back to the till that sent it.
Data recovery: if the server goes down, you're fairly screwed, so make sure it has a UPS and safe shutdown mechanics. If the server loses connection with the KDS, or the KDS goes down and needs rebooting, it needs a special request it can send to the server to get the full list of things which should be on its queue (i.e. all orders which were 'in progress' the last time the server knew about it).
|
|
|
|
|
BobJanova wrote: I'm going to disagree with almost everyone else and say that you want to do this
with sockets, albeit with the central server storing information in a database
for audit/recovery reasons. That's because polling is almost always an inferior
solution (you're transferring, at best, the same data, and generally the same
data plus a large number of empty poll requests, while having a slower response
time), and not necessary in this case.
However polling almost always is a sufficient design.
And it is more than sufficient in this case because the traffic is very low.
Thus there is no point in making the design more complex.
|
|
|
|
|
Polling isn't really any less complex than persistent sockets, you still have to link the same components together and send the same messages. Generally it's more complex because you also have to worry about how to send data the other way, and how to detect a dropped connection. The exception is if there is an existing HTTP service that does what you want, so the socket solution is duplicating existing code, but that's clearly not the case here.
|
|
|
|
|
BobJanova wrote: Polling isn't really any less complex than persistent sockets,
Your solution requires clients, servers and a database.
Mine requires clients and a database.
Thus it is less complex.
|
|
|
|
|
Beim erstellen des Ordners in dem Pfad: Environment.SpecialFolder.ProgramFiles
kommt es immer zu dem Fehler UnauthorizedAccessException weiß auch leider nicht wie ich es umgehen kann OS (Windows 7)
|
|
|
|
|
I'm sure English is not your native language, but it is the default language for this site.
Please, either try to find a better translation of your question to English, or find a site in your own native language, as they may be able to help you better than we can!
Google translate gives:
When you create the folder in the path: Environment.SpecialFolder.ProgramFiles
it always comes up to the error UnauthorizedAccessException do not know how I can handle it, unfortunately OS (Windows 7)
You need to have Admin privileges to access the Program files folder: There is an article here which may help. Getting Elevated Privileges on Demand using C#[^]
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
Tank you very much for the quick answer. I did not know that default language on this site is english but yet
|
|
|
|
|
No problem!
Google translate works wonders...
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
Try and ask questions in English.
It will allow a larger user base to answer it.
As an example, I have no idea what this question is about.
|
|
|
|
|
A non-administrative user must not write into the ProgramFiles folder (translation hint: "must not" bedeutet "darf nicht").
Create an installation package - the "System " account used by the installer can write to that folder.
In case you want to write application data used by all users, the folder should go to CommonApplicationData , and data by a specific user to LocalApplicationData .
|
|
|
|
|
i need to create chart with data from my database by select product from checkbox in listbox and between date from datetimepicker bet when click the button for generate graph value in graph show same data for every series i don't know how to fix this problem
this is my code
if (row.Cells[1].Value != null && (bool)row.Cells[1].FormattedValue)
{
String idtoselect = row.Cells[0].Value.ToString();
String str1 = idtoselect.ToString();
try
{
string sql2 = "select NAME_Product from Product where Product.ID_Product = '"+str1+"' ";
SqlCommand testcommand2 = new SqlCommand(sql2, conn);
rdr = testcommand2.ExecuteReader();
while (rdr.Read())
{
test = rdr["NAME_Product"].ToString();
}
rdr.Close();
try
{
CultureInfo ci = new CultureInfo("th-TH");
string sql = "SELECT * FROM Order1 where ID_Product = '"+str1+"' AND DATE_Order BETWEEN '" + dateTimePicker1.Value.ToString("s") + "' AND '" + dateTimePicker2.Value.ToString("s") + "' ";
da = new SqlDataAdapter(sql, conn);
ds = new DataSet();
da.Fill(ds, "Order1");
chart1.DataSource = ds.Tables["Order1"];
chart1.ChartAreas["ChartArea1"].Area3DStyle.Enable3D = true;
chart1.Series.Add(test);
chart1.Series[test].ChartArea = "ChartArea1";
chart1.Series[test].BorderWidth = 4;
chart1.Series[test].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
chart1.Series[test].YValueMembers += "QUANTITY_Order";
chart1.Series[test].XValueMember += "DATE_Order";
chart1.DataBind();
MessageBox.Show("test :" );
}
catch (Exception ex)
{
MessageBox.Show("test :" + ex);
}
}
catch
{
MessageBox.Show("exception");
}
and this my output
http://image.ohozaa.com/view/80v2q]
i'm so sorry if i type a wrong word because my english is not good
Thank you for answer
|
|
|
|
|
There are a number of "silly" things going on there which it would be worth fixing before you start looking at the meat of your problem:
String idtoselect = row.Cells[0].Value.ToString();
String str1 = idtoselect.ToString(); Why?
idtoselect is already a string, so why convert it to a string in order to load it into another string? In fact you never reference idtoselect agains, so why not just use that throughout, where the name is a bit more meaningfull than str1 ?
string sql2 = "select NAME_Product from Product where Product.ID_Product = '"+str1+"' "; Is a bad idea - do not concatenate strings to build a SQL command. It leaves you wide open to accidental or deliberate SQL Injection attack which can destroy your entire database. Use Parametrized queries instead.
while (rdr.Read())
{
test = rdr["NAME_Product"].ToString();
} test is a string - it can only hold a single value, so why use a loop? Use
if (rdr.Read()) instead.
CultureInfo ci = new CultureInfo("th-TH"); Does nothing at all unless you actually use it in a conversion.
string sql = "SELECT * FROM Order1 where ID_Product = '"+str1+"' AND DATE_Order BETWEEN '" + dateTimePicker1.Value.ToString("s") + "' AND '" + dateTimePicker2.Value.ToString("s") + "' "; Seriously, don't concatenate strings. You have the DateTime values as DateTime. SQL understands DateTime, and does not need it to be in any particular format. Unlike strings, where it does (SQL needs ISO format yyyy-MM-dd), and you aren't providing that, you are providing the short date form of your current culture.
string sql = "SELECT * FROM Order1 where ID_Product = @ID AND DATE_Order BETWEEN @D1 AND @D2";
da = new SqlDataAdapter(sql, conn);
da.SelectCommand.Parameters.AddWithValue("@ID", idtoselect);
da.SelectCommand.Parameters.AddWithValue("@D1", dateTimePicker1.Value);
da.SelectCommand.Parameters.AddWithValue("@D2", dateTimePicker2.Value);
And you may find that if you do all that, your problem may magically disappear! I suspect it might...
BTW: Stop using the Visual Studio default names for things. dateTimePicker1 , dateTimePicker2 don't mean a whole lot - try reading the above with them called startDate and endDate instead - see how much easier it is to read?
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
Thank you for your answer
i have fix my code but my problem still show i don't know what what happen
|
|
|
|
|
So what does your code look like now?
What values are you giving it?
What values are in your DB?
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|