Тёмный

Modifying SQL, the API, and WPF to Add Taxes - A TimCo Retail Manager Video 

IAmTimCorey
Подписаться 421 тыс.
Просмотров 14 тыс.
50% 1

Опубликовано:

 

3 окт 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 130   
@ben.thornhill
@ben.thornhill 4 года назад
Great video Tim! Please never stop doing your style of long-form, soap-box fueled content. I know that "{{ Some Topic }} in 60 Seconds" types of videos get a lot more clicks, but your style of teaching is at the pace where students like myself actually learn. Since discovering your content, I've enjoyed how you don't simply focus on the technical, but also on how to have a good problem-solving mindset as a developer. I'm really excited to go through your new Blazor course when I get some time. Have a great day!
@IAmTimCorey
@IAmTimCorey 4 года назад
Thank you! I am glad you are getting so much value out of the content.
@Jawsh27
@Jawsh27 5 лет назад
Great video. I remember we put product descriptions in the product table, but we haven't used them yet. Possible feature to add in the future: when the item is highlighted/selected, its description will pop up in a text box, possibly below the remove from cart button.This can be useful in a situation, for example, where someone doesn't know what is included in the home repair kit. We could also put how much of that product is in stock, and update it as items are added
@IAmTimCorey
@IAmTimCorey 5 лет назад
I like the suggestion. I'll add it to the list.
@tnysvntr
@tnysvntr 5 лет назад
I am happy this series is still active, although Im still at lesson 3 ❤❤ Thank you Tim Corey!
@IAmTimCorey
@IAmTimCorey 5 лет назад
You are welcome.
@tinumurymury38
@tinumurymury38 5 лет назад
Hi Tim. This series keeps getting better by the lesson. Someone posted before some details about the issue of tax and I only mention this for the sake of conversation not as a suggestion. The European standard for tax is different from the one in the US. As a general rule, when dealing with retail sales it's a custom to include the tax in the retail price. For example a $10 items' retail price is made of $9.20 + $0.80 (using the 8.75% tax from this video). If you go online or in a store to buy a specific item, you get the final price right from the start. In this project this would translate as whenever you add an item to the cart the SubTotal and the Tax properties are subtracted from the Total, if the product is taxable. Some friends of mine that spent time in the US mentioned that in almost every store the price displayed on the shelf doesn't contain tax and the tax is calculated and added only at the register. For bulk sale, the pricing system is roughly the same as yours (as far as I can see): the tax is added to the listed price. I do have a suggestion in regards to the Remove button, but some might find it's just a quirk: you should consider allowing the user to remove from the cart a specific quantity of the selected item. The mindset is that the user clicked twice by mistake on the Add button and wants to remove just a partial quantity of that item. The way the Sales page is at this point, I would consider adding a Removed quantity TextBox defaulted to the total quantity in the cart of the selected item. Keep up the great work! This is by far the most complex beginners C# (or any language) tutorial on the web.
@IAmTimCorey
@IAmTimCorey 5 лет назад
Yeah, I've experienced the European standard recently. I advertise my courses as one amount but if you are in Europe, it shows the price as reflects your area. That has confused people. I've been working on updating what I say to better reflect this reality. While I like people seeing the true cost up front, it is hard when every country has a different VAT rate. The US way is more work (you need to do the math in your head), but it has the advantage of being the same between all of the different states, even though the tax rates per state are different. I'm not sure which I prefer. I like the remove button suggestion. I'll have to think on that one. Thanks!
@stinefelt
@stinefelt 4 года назад
Tim, this is very helpful and thank you for making these videos.
@IAmTimCorey
@IAmTimCorey 4 года назад
My pleasure!
@markvandersalm
@markvandersalm 5 лет назад
Hi Tim, first of all thanks a lot for all the great videos you produce. I'm a viewer from the Netherlands. Our currency is the Euro, and I noticed that the ToString() method, when using the "C" format parameter, automatically uses my current culture setting to set the format of the monetary values, so I get Euros, not Dollars. While I'm sure you can make the program use a specific culture setting to make sure it uses the correct money format, there is another problem. In the Netherlands, the usage of commas and periods in numbers is inverted. For example, in English you'd write 'a thousand' as 1,000 -- but in Dutch we'd write 1.000. Similarly, 'one half' would be 0.5 in English, but 0,5 in Dutch. The consequence is that I also need to use a comma instead of a period in the 'taxRate' value in the in App.config to make sure the tax is calculated correctly. I wanted to give you a heads-up on this behaviour, because it means the 'taxRate' setting should probably change to have a comma or a period according to the current culture setting.
@IAmTimCorey
@IAmTimCorey 5 лет назад
The system will work based upon the culture of the computer it is running on. So, you should be able to put commas in your app.config and it will work. The tricky bit is transitioning to other cultures on the same machine or with the same app. I intend to do a video on culture-aware applications and how to deal with these types of situations this summer.
@luckyJYK
@luckyJYK 5 лет назад
@@IAmTimCorey Can't wait for that video Tim. Thanks a lot for your teachings Mr.Corey.
@Stoney_Eagle
@Stoney_Eagle 4 года назад
I was wondering why the tax needed an extra divide by 100 to work properly. Dank je!
@CynicalSaint48
@CynicalSaint48 5 лет назад
Thanks for the video Tim! Not sure what types of 'cleanup' suggestions you are looking for, but pet peeve of mine is quality of life stuff, so my suggestion would be auto-focus on the Username field on Load, and return to the LogIn button. Easy little fixes, that prevent you from having to use the mouse. Thanks!
@IAmTimCorey
@IAmTimCorey 5 лет назад
I like it. Thanks for the suggestion.
@MohdRizwan-pf3ex
@MohdRizwan-pf3ex 5 лет назад
Eagerly waiting since yesterday.
@IAmTimCorey
@IAmTimCorey 5 лет назад
Yeah, that was my bad. Yesterday was a holiday in the US but I intended for this video to come out then. However, when I scheduled it, I put the wrong date on it. Since I was out at a BBQ all day, I didn't check in on my channel to see that the video hadn't posted. I discovered it this morning when it was already out. Oops.
@luckyJYK
@luckyJYK 5 лет назад
@@IAmTimCorey hmmm BBQ yummy...
@nahco3994
@nahco3994 3 года назад
Taxation laws literally fill entire bookshelves in every single country on this planet. And they are almost certainly going to be different from each other in all sorts of ways. I'd say it's acceptable to just gloss over this minefield in a tutorial series tailored for beginner programmers. This does raise an interesting question though: How does professional enterprise software tackle the issue of internationalization/localization in regards to taxes? Is there some sort of "best practice" for this? I was having similar thoughts with the currency value in the ToString() method, which gets localized automatically by the system's locale. The purchase and retail price would obviously have to be tied to a certain currency, which then needs to either remain constant, or be converted accurately to a different one. It would be fairly impractical to "purchase" something in USD, only to have the retail price be displayed 1:1 in RUB or JPY.
@IAmTimCorey
@IAmTimCorey 3 года назад
Well, I can tell you that as a small business owner myself, I outsource it to a company that specializes in handling taxes based upon where a person is located. That is a tough nut to crack, especially with all of the different regulations. What FastSpring does for me is they identify the person's location (based upon at least two factors, not just IP address) and then they display the price in the currency of the region and apply the taxes for the specific area in that region. They put the price in the local currency after identifying what the conversion rate will be at the time. I gladly pay a percentage of every sale to them in order for them to handle that (they support dozens of currencies, hundreds of countries, and thousands of taxation regions for me).
@TheGenZProgrammer
@TheGenZProgrammer 5 лет назад
Great videos as always sir
@IAmTimCorey
@IAmTimCorey 5 лет назад
Thank you!
@ClaesEngelin
@ClaesEngelin 4 года назад
First off, I want to thank you for a most excellent series. I only recently discovered your channel,and am busily working my through it. You seem to teach at the same pace at which I learn, so the match is great :-) Now, I have a question about how you handle taxes in this lesson. I have read all the comments, and nobody seems to have picked up on this. Why don't you adopt a real world model for taxes? That is, have a separate table of TaxeRates and one of ProductCategory. Then, just give each Product a CategoryID, which can be used to look up the tax rate for the specific product. Most countries in Europe have systems like this. We have different tax rates for food, clothing, tobacco products, alcohol (some even for spirits/wine/beer), fuel. The list goes on. It makes for a very flexible, albeit messy, system. Oh, on top of all these "spot taxes", we have the VAT, which goes on top of everything. And even that can vary with the ProductCategory... A system like this, or a simplified one, would greatly enhance the application, and bring it that much closer to the real world. At least that's my humble opinion.
@IAmTimCorey
@IAmTimCorey 4 года назад
I wasn't sure if it would add enough to the demo compared to the confusion it would add. Here in the US, we have one tax rate for all items and then we don't tax certain ones. So for us, a tax rate and then a checkbox for taxable is all we need.
@ClaesEngelin
@ClaesEngelin 4 года назад
@@IAmTimCorey Fair enough. Edit: After having talked with some friends in the retail business, I understand that a retailer never sees the spot taxes, as they are included in the wholesale price. All the retailer needs to worry about is VAT. Depending on if you are doing B2B or B2C business, your sales and pricing will be without or with VAT. In our model, that would mean that the "IsTaxable" flag applies per sale (actually, per customer) rather than per item. Of course, some countries have different VAT rates for different product categories, which brings us right back to the start of the discussion. However, that is the exception rather than the norm, I believe. So, for us Europeans, we can just consider the Tax to be VAT and label it as such. A small twist to the plot is that when you shop in Europe, all goods are marked with prices VAT inclusive. In other words, a bottle of wine with a price tag saying €10.00 will cost you 10 euros at checkout. Your receipt will specify that you paid €10.00 and that €2.00 of that was VAT (given a 25% VAT rate, which is quite common). Again, that wouldn't change the code very much.
@harag9
@harag9 5 лет назад
Thanks for this Tim, great episode. I'm about to start a Xamarin.Forms project at work and no idea where to start, but the XAML in these tutorials will help. Hope you get around to putting some videos up about Xamarin.Forms soon. Keep up the excellent work!
@IAmTimCorey
@IAmTimCorey 5 лет назад
Yep, that's on the radar. Probably late July or so.
@harag9
@harag9 5 лет назад
@@IAmTimCorey Excellent, that is really good to hear. I'm more interested in the Forms side of things personally.
@nogo1880
@nogo1880 3 года назад
Is there a reason we couldn't divide the tax rate by 100 in the ConfigHelper, rather than having to do the calculation every time we call the CalculateTax method? I know it's not a complex calculation and can be done in a split second. But if it were a much more complex calculation, I feel like it would make sense to have the calculation done in the singleton instance, that way the value is stored for the life of the application. And that would also mean we don't have to remember to do the calculation anywhere else in our application. And as always, thank you for these videos! Super helpful!
@Vibratebalance
@Vibratebalance 5 лет назад
You're the man. Looking forward to how this will build out.
@IAmTimCorey
@IAmTimCorey 5 лет назад
Me too, actually.
@Vibratebalance
@Vibratebalance 5 лет назад
@@IAmTimCorey What is a general outline of the steps left? Are you going to add any WPF POST functionality?
@IAmTimCorey
@IAmTimCorey 5 лет назад
There is a lot left to do. We need to finish up the shopping cart so that we can actually make a purchase. Then we need to add a few screens for managing inventory, users, and more. We also need to build out a web front-end for self-serve. We also need to add DI to our WebAPI. After all of that, we need to convert the application over to be .NET Core (one of the big goals of this course) and then we need to think about Docker and Xamarin.
@sebastiandhom7172
@sebastiandhom7172 3 года назад
Hi Tim, again - thanks a lot for your effort! Really great stuff! I got some questions I think, I'm not the only one who got stuck on this.... 1. Why do you use decimal in one place and double in another? Is there any reason (memory usage)? Why not always use the highest precision? Or: Use the type that comes from the database as this is the given precision by SQL Server. The parsing / rounding / casting drives me crazy ;-) 2. Why do you return money-values as a string? Is that for educational reasons (easier to display a.t.m.)? Or: Is it the way to use fields in ViewModels? Again: THANK YOU SO MUCH! I learned so many things til now..... Sebastian
@sebastiandhom7172
@sebastiandhom7172 3 года назад
.....after watching min. 30 I got answered my second question... lol
@IAmTimCorey
@IAmTimCorey 3 года назад
We use double because it is a lot cheaper to use (memory). Every type has rounding (even decimal - it is just done over 25+ places out). Also, since it is commonly accepted to use double for all non-money/non-astronomical purposes, most methods that work with numbers use double.
@sebastiandhom7172
@sebastiandhom7172 3 года назад
@@IAmTimCorey thank you for the answer.
@objectaware5296
@objectaware5296 5 лет назад
@28:00 - When changing a block of code to its own method you can select the code and use ctrl + , @36.24 - Should not the conversion to percentage be done in GetRate? The rate is not 8.75 but .0875 and that is what should be returned.
@IAmTimCorey
@IAmTimCorey 5 лет назад
Thanks for the tip. As for the conversion, it depends. If you also want to show the percentage then no, probably not. We need it in both formats.
@objectaware5296
@objectaware5296 5 лет назад
@@IAmTimCorey I don't follow. If you want it in a different format then you could use formatting string.Format("Value: {0:P2}.", GetRate()) // formats as 8.75 % (varies by culture) In fact, I would create a method in ConfigHelper that would do the conversion to string percentage public string GetTaxRatePercentage() { return string.Format("{0:P2}", GetTaxRate()); } This encapsulates the taxRate within a single class.
@aloguinsandrrmo8674
@aloguinsandrrmo8674 4 года назад
Great content as always.
@IAmTimCorey
@IAmTimCorey 4 года назад
Thank you!
@steveteece8889
@steveteece8889 5 лет назад
Hi Tim, Another great video as usual. There is one minor improvement that I think should be made with calculating the rate of Sales Tax. Wouldn't it be better to do the division by 100 in the GetTaxRate() method? That way, the correct rate for the calculation will always be returned, and if we need to have the tax rate on other screens and reports, we are not relying remembering to put the division into the ViewModel.
@IAmTimCorey
@IAmTimCorey 5 лет назад
I debated that but the issue is that then I have to convert it back to display it anywhere. It all comes down to which is expected and the answer is I'm not sure. I see valid arguments on both sides.
@andywalter7426
@andywalter7426 5 лет назад
I was watching the video about adding taxes. Here is one suggestion that can be helpful. You could have created an interface that returns a tax rate and is async. If that was done, then the system would not care if it comes from config, the key vault, a file or even hard coded in a special class. I've done that many times and that made things very flexible because its easy to swap from one interface implementation to another with dependency injection so you just register the implementation you want to use for the tax rate.
@IAmTimCorey
@IAmTimCorey 5 лет назад
Thanks for the suggestion. We will get there eventually with that. When we move to .NET Core, we will move this setting out of app.config and into appsettings/KeyVault/etc. For now, I want something in the app.config since that will provide a hurdle to overcome when converting to .NET Core. As far as async, I'm not sure if this setting warrants it. Committing to async means changing a LOT of things. I'm not sure this setting will ever be a blocking setting.
@andywalter7426
@andywalter7426 5 лет назад
@@IAmTimCorey If KeyVault is Azure, is that async though? With interfaces, there can even be options to put into SQL Lite or even a text file. The problem I can see with putting them into an app settings is if the rate changes and you have more than one UI, you have to change in all. However, if planned properly, it could even be possible to change the rate without even recompiling any program at all.
@dyachenkoserj
@dyachenkoserj 5 лет назад
Tim, thanks for the course and others video. It would be great, if you can make video about cleaning unmanaged and managed resources and applying Dispose/Finalize Pattern in a real project(e.g.: retail manager project). Thank you.
@IAmTimCorey
@IAmTimCorey 5 лет назад
Thanks for the suggestions!
3 года назад
Hi Tim. Thanks for the videos. very educational so far! I’ve got a question. When we calculate the “Total”, We’re essentially doing the calculations of subtotal and tax again. This feels redundant as we already did those calculations. On a small program this will probably be ok, but would it make sense to store the “subtotal” and “tax” in a variable and use that instead, or would that be nitpicking. Hope to hear your thoughts.
@andywalter7426
@andywalter7426 5 лет назад
There was another idea i see you could do based on watching the video. The sub total and tax can be decimal. Then you can use a converter to convert to currency. In almost all of my projects if currency is being displayed, i still use the decimal type and then create a converter so the ui shows proper values. I've even created a custom converter that is cross platform so then a person just needs to inherit and implement their converter and it just works.
@IAmTimCorey
@IAmTimCorey 5 лет назад
They are of type decimal, we are just doing the UI display work in the property itself (which is the UI in a MVVM project - Models, Views, and ViewModels are all UI technically).
@andywalter7426
@andywalter7426 5 лет назад
@@IAmTimCorey I thought that with MVVM only the view is the UI and the rest has nothing to do with the UI. I watched many videos and they said the main purpose of MVVM is keeping the UI separate from the business logic so more things can be cross platform.
@IAmTimCorey
@IAmTimCorey 5 лет назад
MVVM is a UI framework. All three are part of the UI. The separation of the business logic happens outside of MVVM (and in a class library).
@janne_kekalainen
@janne_kekalainen 4 года назад
Funny Thing, TryParse works differently based on the localization settings of the computer running it. By default, TryParse uses the rules of current culture e.g. "," or "." as decimal separator, so if one is used and it expects another it fails to parse (or interprets it as a thousand separator). Encountered this myself here. I used this instead: Return Decimal.Parse(x, NumberStyle.AllowDecimalPoint, CultureInfo.CurrentCulture); (And wrapped it in try-catch)
@IAmTimCorey
@IAmTimCorey 4 года назад
Interesting. Thanks for sharing.
@girornsveinsson7970
@girornsveinsson7970 4 года назад
I had problems with localization settings too which I fixed by changing the bootstrapper like this: protected override void OnStartup(object sender, StartupEventArgs e) { DisplayRootViewFor(); CultureInfo ci = new CultureInfo("en-US"); Thread.CurrentThread.CurrentCulture = ci; Thread.CurrentThread.CurrentUICulture = ci; }
@HollandHiking
@HollandHiking 4 года назад
@@girornsveinsson7970 Great thanks for this. I think it is worth a discussion on localization and wher eyou want to apply this. I discoevred that even at SQServer level I had to use comma's as a decimal separator. I think it is not desirable, most of it you want to do in the UI. But replacing dollars by Euro's automatically is a very bad idea ... I think localazation definitely deservers a lot of attention. Tim, I hope this is already on your list ...
@SuperDre74
@SuperDre74 4 года назад
Be careful, decimal.TryParse("1.1", NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out decimal result); (where CurrentCulture="nl-NL" which means comma is decimalseparator) result is 0, so it does not work. best is to just use decimal.TryParse("1.1", NumberStyles.Any, CultureInfo.InvariantCulture, out decimal result), so no matter what culture, result is always 1.1 (which ofcourse means you must advice in the config file that the taxRate should be entered with a point as decimal separator, by adding a line like "!-- taxRate with . for decimalseparator -->" so people who are going to change the config know what to enter as a rate.
@umblnc
@umblnc 3 года назад
Or you can leave the code as it was, but in App.config put "8,75" instead of "8.75" if that is the decimal separator for your current culture.
@daschrauba
@daschrauba Год назад
it took me quite a while to figure out that I have to use comma instead of dot for decimal, as I am from Germany :D
@IAmTimCorey
@IAmTimCorey Год назад
Ah, yep, that is a tricky one.
@marekott4432
@marekott4432 4 года назад
Hi guys! Tim, great video. I have a question for you and others here. What do you think about replacing foreach loops with LINQ querries? Advantage ot this is for sure less code but it is harder to read through those methods for someone new and debbuging can be tricky. So you would leave methods as in video or rather refactor it for something like this: public string SubTotal => CalculateSubTotal().ToString("C"); private decimal CalculateSubTotal() { return Cart.Sum(item => item.Product.RetailPrice * item.QuantityInCart); } public string Tax => CalculateTax().ToString("C"); private decimal CalculateTax() { var taxRate = _configHelper.GetTaxRate(); return Cart.Where(item => item.Product.IsTaxable).Sum(item => item.Product.RetailPrice * item.QuantityInCart * taxRate); }
@IAmTimCorey
@IAmTimCorey 4 года назад
I do like it and I think it is a refactor we will end up doing. I think it is readable enough for a new developer but you make a very good point about being careful about that and about making it more difficult to debug. This is probably something we would want to hold off on doing until after we have unit testing in place to help offset those issues. Great thoughts!
@onyebuchiboss
@onyebuchiboss 5 лет назад
Thanks Tim!!
@IAmTimCorey
@IAmTimCorey 5 лет назад
You are welcome.
@andywalter7426
@andywalter7426 5 лет назад
One suggestion I would have as well is I noticed you had 5 projects. Would it maybe be better if you reduced it to 3. One can be the back end. Another can be the cross platform and the third would be the wpf. Even for the backend, you can have namespaces. So one namespace can be for Data but another one can be other processes that access the database directly.
@IAmTimCorey
@IAmTimCorey 5 лет назад
We use 5 projects so that we have good code reusability. Class libraries can be used by more than one project. The UI projects should be just UI so that we can replace them without replacing our logic. The fifth project is the database itself. That can't be merged into another project. Don't be afraid to have multiple projects. It allows for greater separation and reduces coupling. That's a good thing.
@objectaware5296
@objectaware5296 5 лет назад
If it was me I would have more and not for code reusability but for Separation of Concerns (SOC) and maintainability. The stack looks like this on the service side Data -- EF / Dapper / Mongo Repository - I/F to the Data Library - I/F to the Repository (Business) API / Service - WebApi or WCF IOC - Unity / Autofac Also has DTO (Data Transfer Objects) and Common The stack on the UI side Gateway - communicates to the API/Service Library - I/F to Gateway (Business) UI -- WPF or MVC IOC - Unity / Autofac Also has Models and Common Both have Test
@recurringnews
@recurringnews 5 лет назад
Hi Tim. Would not it be nice to have a field for the rate of each product in the database? Thanks for the great work!
@IAmTimCorey
@IAmTimCorey 5 лет назад
What do you mean by rate? Do you mean a customer rating (4 stars out of 5 type of thing)? Or do you mean how much it costs? We have the retail price in the products table and we have the cost to purchase each lot of items (so we can calculate the wholesale cost, which can vary over time).
@StudentCompanion
@StudentCompanion 5 лет назад
If one subscribe with Patreon will I have access to previous source code already released of this course series or only the new released? Thanks a lot for great tutorials.
@IAmTimCorey
@IAmTimCorey 5 лет назад
Yes, you get access to all previous posts with the source code.
@StudentCompanion
@StudentCompanion 5 лет назад
@@IAmTimCorey thanks
@andrewthompson9714
@andrewthompson9714 4 года назад
Good evening, I have a question for you about the content in this video? In a real environment, would the logic for totalling and dealing with tax be handled in this class? I feel that this is a specfic set of business logic that should not be mixed in with the code that directly interacts with the UI? For SRP and SOC reasons. It also helps to maintain a consistent single source of truth. Also for the tax, It seems to me that the GetTaxRate is a little bit dishonest - It returns the tax rate multiplied by 100, which causes a related part of the logic for calculating the tax rate to be placed in a view model. I am not trying to be critical, as I understand this is a demonstration, but I am curious as to whether this is a normal practice or whether more separation would normally be done. This series is fantastic,, and you have made MVVM, API's and WPF so easily digestible for me.
@IAmTimCorey
@IAmTimCorey 4 года назад
Good question. This is actually a simulation of the real world. It is expensive to go back to the server to get a calculation that you could do on the client. We do the calculation twice in order to save cycles and bandwidth. There is a slight chance of causing a discrepancy but our source of truth is always on the server. In order to create a scalable infrastructure, you have to do work like this. It is the same reason why we used cached information on front-ends. For example, Amazon will tell you it has 3 books left in stock. However, it didn't actually go to the back-end to check that. It used a cached value. Upon checkout, an asynchronous process will verify the book is in stock and allocate one to you. If the inventory cache was incorrect, it will let you know that your order can't be placed after all. That is the price for scale.
@alfonsdeda8912
@alfonsdeda8912 Год назад
Hello Tim, thank you very much for your efforts in this playlist. I have a serial class that when specific string is received I want to save to database the model received from serial string, should i put an event in serial class that notify the viewmodel that string is received and view model will save in database and monster this model in UI or there is another better approach? Thanks in advance.
@SuperDre74
@SuperDre74 4 года назад
you say normally percentages are doubles, but that's not true, double is just a 'cheaper' type to store a percentage in, but seemingly a lot of developers don't know that the double type cannot store all floating point numbers, even some simple ones, for instance if you set it to 2.24 it might actually be stored as 2.2399999999999999999999... and it calculates with that number, not 2.24 as you meant (number itself is just an example as I can't remember which 'simple' number it actually goes fubar). So if you really want it to store correctly and calculate correctly with, you have to use the decimal type (which is a much more 'expensive' type in regard to memorystorage and speed), float and single have the same problem. So be very careful in using doubles when calculating prices/wages etc. it might give you unwanted rounding problems.
@IAmTimCorey
@IAmTimCorey 4 года назад
As I was saying in the video, we use decimal for money and since the percentage is affecting money, we also use decimal for it. For "normal" uses that don't involve high levels of precision, doubles are the normal way to go. This is why the Math library that Microsoft provides primarily works with double. Math.Pow (power), Math.Sqrt (Square Root), and more all use double, not decimal. Normally, 16 digits after the decimal of significance is enough. It is only in the cases of more exact precision that you need decimal (such as money). Decimal is not the correct way to store numbers. The correct way is to make a choice based upon the number and your environment.
@zdenekhorejsi8140
@zdenekhorejsi8140 5 лет назад
Hello Tim, I am a junior student learning about C#,Sql Server and also ASP.NET.Saw your videos and wanted to ask you as an experienced developer,what are the best resources for learning .NET stack of languages? I have tried RU-vid,also Udemy and a bit of Pluralsight,except your videos.I have seen also your videos here,since I cant afford those at your site,but could you give me a precious tip about this? Thanks!
@IAmTimCorey
@IAmTimCorey 5 лет назад
Check out the PDF on this page. It should help: www.iamtimcorey.com/p/learncsharp
@matterece3164
@matterece3164 5 лет назад
How should I organize my database and my API so that each user would have different data? Like a todolist that user's have different lists of todos?
@IAmTimCorey
@IAmTimCorey 5 лет назад
You would just need to add the user's ID onto records (you already have that in the API for every call once they log in). Then, when you query data, you always filter by the userId as well.
@Vitalick15
@Vitalick15 2 года назад
Thanks))))!!
@IAmTimCorey
@IAmTimCorey 2 года назад
You are welcome.
@danirdd92
@danirdd92 5 лет назад
I think GetTaxRate() should return a decimal since we are dealing with money after all and precision matters
@IAmTimCorey
@IAmTimCorey 5 лет назад
It does now. A percentage isn't typically a decimal because it isn't money but in this case, we had to turn it into a decimal in order to get it to interact with money.
@Musa1978K
@Musa1978K 3 года назад
thanks
@IAmTimCorey
@IAmTimCorey 3 года назад
No problem
@hughmcdaid9060
@hughmcdaid9060 5 лет назад
Hey Tim, Why would you add a data property to your UI (taxRate)? That makes your application dependent on having the taxable rate on any other UI you create instead of on your API/Data layer. You could be setting yourself up for inconsistent data between UIs.
@IAmTimCorey
@IAmTimCorey 5 лет назад
It reduces the calls I need to make since I'll need to know the taxable amount on the UI. The API will verify that rate when saving the record but this way the user has a good experience during the sale process.
@simon_smale
@simon_smale 4 года назад
I was thinking this too. I would put it in the DB as taxRates and then use the ID as a ref in the product table. Would also allow for you to look up old tax rates
@HollandHiking
@HollandHiking 4 года назад
@@simon_smale I agree with you Simon. Also it is risky to do the division by 100 in the calculation. It is better to dot hat in GetTaxRate. Additionally, you may add there some logic to give a least a warning is TaxRate is out of bounds.
@chrishuerta2506
@chrishuerta2506 5 лет назад
Thanks for the video Tim! I tried to produce the exception by replacing 8.75 with the string "abc" and was unable to. I even removed the if statement and replaced it with TRUE, and was unable to produce the exception error. The only consequence was tax not calculated and left blank. Any help is appreciated.
@IAmTimCorey
@IAmTimCorey 5 лет назад
Put a breakpoint in and see what is going on. The TryParse should return a false if the number is not valid. Check that it is doing so and that you are checking for the boolean value.
@chrishuerta2506
@chrishuerta2506 5 лет назад
​@@IAmTimCorey Thanks for your response. I tried what you suggested and it does show TryParse as false when I change the taxrate in app.config to a non decimal value. But, it still does not produce the exception. I think it may have to do with how the shell quickly goes from loginview to the salesview (?). When I place the throw new exception in the shellview it does work when the app loads. So I am not sure why it is not triggering correctly when places elsewhere.
@LarryB15
@LarryB15 3 года назад
Being in the UK, I wanted to add different tax rates as we have Tax Exempt (0%), Standard VAT Rate (20%) and Reduced VAT Rate (5%) at the moment. What I did was to create a Tax Table, (Tax Category v Tax Rate) and then for the Product table I added a Tax Category column. Then in the spProducts_GetAll() stored procedure I changed the query to join the Product and Tax tables so that the the query returned the appropriate Tax Rate for each product. Hope that was clear. If I wanted to use an enum for the categories, how would I go about that?
@IAmTimCorey
@IAmTimCorey 3 года назад
Sounds good. As for the enum, there's a lot to explain there. I don't think I have an example of that. You would need to do casting back and forth in C#.
3 года назад
I ended up with a similar solution as we have different Taxes here in the Netherlands aswell. My Stored procedure ended up like this; begin set nocount on; SELECT [Product].[Id], [ProductName], [Product].[Description], [RetailPrice], [QuantityInStock], [TaxCategoryId], [t].[Description] as TaxCategory, [t].[Tax] FROM dbo.Product AS product INNER JOIN [dbo].[Taxes] AS t ON [Product].[TaxCategoryId] = [t].[Id] ORDER BY ProductName; END I'm curious if yours ended up the same. Dd you also add a "Tax ID" field to the table, or use Tax Category as your unique field?
@LarryB15
@LarryB15 3 года назад
@ Here is my implementation, very similar: SET NOCOUNT ON SELECT Id, ProductName, [Description], RetailPrice, QuantityInStock, VAT_Rate FROM dbo.Product INNER JOIN dbo.VAT_Rates ON dbo.Product.VAT_Category = dbo.VAT_Rates.VAT_Category WHERE Id = @Id
@girornsveinsson7970
@girornsveinsson7970 4 года назад
At this point in the series there is a bug in CanAddToCart. The SalesView does not fire an event to this property when an invalid value is in quantity. So we can enable the button by selecting an item and then, if we enter a letter or erase the value completely, the button remains enebled. How can this be fixed?
@IAmTimCorey
@IAmTimCorey 4 года назад
We would need to do some validation on the number before we add it.
@andrewthompson9714
@andrewthompson9714 4 года назад
@@IAmTimCorey I believe it is to do with the way the binding works when converting to an integer value. It doesn't update the property when an invalid value is entered, so this causes the property to retain the value of the last valid number entered - Maybe convert the property to a string and do view model validation on it? Seems hacky. I believe you can bind to a validator, though I haven't done this yet, but even so, you have to choose an error value of int when invalid input is entered - 0 I guess would work here.
@flabberdog
@flabberdog 4 года назад
I think the most confusing part of this is not being American. It may be one of the only places that doesn't include tax when buying? Most places generally include tax, you often only get a pre-tax and post-tax value if you are buying from a shop that's a wholesaler or shop for other companies that may be tax exempt etc. This may be why it seems to be counter-intuitive for some people, not sure.
@IAmTimCorey
@IAmTimCorey 4 года назад
Tax is a messy business. In the US, some items are taxable, others are not. Sales tax varies by state. Tax is not shown on an item until you purchase it (so a $1 item becomes $1.06 if there is a 6% tax rate). I would much rather have the EU system of VAT, where it is already applied to the item and the price you see is the price you pay.
@flabberdog
@flabberdog 4 года назад
@@IAmTimCorey You certainly made a good choice by simplifying and sticking the current tax implementation rather than listening to all us moaners in the comments!
@jakobhendrix1753
@jakobhendrix1753 4 года назад
I'm having issues accessing the new key from the App.config file. While Debugging, it keeps telling me that there is only a single item in "AllKeys", "api", which when examined points to the localhost setting we added in an earlier video. I tried adding several new keys, and it still only reports seeing a single key. When I looked into the /bin/Debug/ of the DesktopUI project, I found the RetailManager.exe.config file being used, and it had a single key, "api" which matched what the Debugger was telling me. A clean/rebuild did not resolve this. Here are the appsettings sections: App.Config: RetailManager.exe.config in /Bin/Debug
@IAmTimCorey
@IAmTimCorey 4 года назад
It sounds like your app.config is not marked correctly as copy when newer. Try deleting the bin directory and running the application. That should resolve the issue. In that case, check the properties of the app.config file to be sure they are correct.
@jakobhendrix1753
@jakobhendrix1753 4 года назад
@@IAmTimCorey After setting that property, the correct App.config is being added to the ..bin/Debug/ directory, but it is not correctly being added to {appname}.exe.config, which appears to be what ConfigurationManager is actually using. Given that the "api" key with that "localhost" value exists only in the App.config file that I am editing, this seems very odd. I will keep digging around.
@jakobhendrix1753
@jakobhendrix1753 4 года назад
For the purposes of moving on with the application, I moved the configured tax rate out of the App.config file, and into the Application settings in the Library. This has the added benefit of providing type safety, so now the GetTaxRate() method is 1 line: public double GetTaxRate() => Properties.Settings.Default.TaxRate;
@SuperDre74
@SuperDre74 4 года назад
@@jakobhendrix1753 But don't you just have the same problem as now you have to keep updating your project file and recompile if the taxrate changes, otherwise the user still has to change the local configfile themselves.
@TheDogfighter13
@TheDogfighter13 9 месяцев назад
Hi guys , i was wandering if anyone had a similar bug (IsTaxable property doesn't get in the API) i tracked it down but have no idea what to do next -When i modify the sql file to add IsTaxable it doesn't post it on api (when i oppen swagger in browser , product doesn't show it's taxable property in it , and as a result it loads in false in the model and taxes are always zero (One can dream i know)) , in the api/Product window in swagger i doesn't even show IsTaxable prop , (i did publish the db after changing it and added prop to api model and then went to add it to wpf library as well and so on) -Honestly i went over the video several times and i am not sure where did i go wrong , so far i managed to debug all problems i've found but i could use some help here , thx anyhow
@TheDogfighter13
@TheDogfighter13 9 месяцев назад
Anyone?
@TheDogfighter13
@TheDogfighter13 9 месяцев назад
Found it , if you have this problem , add check where you add IsTaxable prop , i added it to internal (i guess it was the first one that i saw and like an idiot wasted 5 days trying to figure out why api doesnt have that prop in it .... PUT IT IN BOTH MODELS FILES WITHING THE DLL)
@IAmTimCorey
@IAmTimCorey 8 месяцев назад
I’m glad you figured it out.
@marmictanghus
@marmictanghus Год назад
8% 😂 In DK we pay 25%
@IAmTimCorey
@IAmTimCorey Год назад
You probably get more for your money too.
@bassamsami7319
@bassamsami7319 4 года назад
HI SIR , sorry for bothering you but we need just the CRUD operation using dapper and caliburn micro without the API complications just simple app please. 😙
@IAmTimCorey
@IAmTimCorey 4 года назад
This might help: docs.microsoft.com/en-us/aspnet/web-forms/overview/performance-and-caching/using-asynchronous-methods-in-aspnet-45
@MBCDC1
@MBCDC1 2 года назад
I hope it is obvious that we have a big "QuantityInStock" problem here. The system runs properly as long as there is only one customer in the shop. If we have more customers with us in the shop, we might run into chaos soon. Let me explain why in a short example and lets remember that all we did so far with the "Sales Page" happened in memory and as long as we don´t "Check Out" nothing happens in the database. Lets assume that customer X puts 5 "Fluffy Bath Towels" into his cart. At the beginning we had 10 Sets of this item physically in our stock. Customer X reserves 5 of these 10 items for himself by putting them into his cart. And even though there are 10 items physically in stock, only 5 items are available for sale now at the moment. Now customer Y enters the shop while customer X ist still on his shopping-tour. Customer Y is eager to buy "Fluffy Bath Towels", too. He logs in, and to his delight sees, that 10 "Fluffy Bath Towels" seem to be available and puts them all into his cart - which unfortunately is possible. Now we have the situation that 2 customers reserved a quantity of 15 "Fluffy Bath Towels" while only 10 are physically in stock. Now, one possible solution is, that we also offer AR-15 rifles in our shop an let them fight this out. But the preferred solution here seems, that we have to interact with the database before we come to the "Check Out" scenario. We have to work with "Reserved Quantities" in addition to "QuantitiesInStock" and as soon as a customer puts an amout of an item into the cart, we have to update the "Reserved Quantity" in the database and in addition we have to calculate the value for the quantity we are able to offer at the moment by substracting the "Reserved Quantity" from the "QuantityInStock". If a customer removes the item from his cart, we have to reduce the "Reserved Quantity" in the database by the "QuantityInCart". The same goes for the "Check-Out" scenario. But in addition we have to reduce the physically available amount of items in stock ("QuantityInStock") by the amount the customer had just bought. For the sake of the simplicity of our Application, the current functionality of the system may be OK, but as soon as we come to the moment we develop a WebUI, we should at least mention this quantity problem.
@vr77323
@vr77323 Год назад
I think the idea here was that this app isn't going to be used by the customers but by the cashiers. Meaning you (as a customer) get in the shop, tell the cashier what you want, and the cashier marks the products, takes your money, and on to the next customer.
@MBCDC1
@MBCDC1 Год назад
@@vr77323 Well, that my be the case and this specific function is indeed for 1 cashier only. But I think we can assume that the company may have more than one employee. There may be not only the store with a cashier, maybe the company also sells via an online-store and maybe there is selling taking place over the phone, too. All of them are accessing the same inventory. If you don´t work with reserved quantities, your business will quickly end up in chaos. Of course Tims app is for demonstrational purposes only and just a rudimentary construct, but he should at least have mentioned that handling the inventory is more complex in the real world.
@TheDogfighter13
@TheDogfighter13 9 месяцев назад
Hi @IAmTimCorey , i just bought all access pass , i'm wandering do i have access to the source code of this lession with it (i can't seem to find it) I have a problem and i'm stuck described more in my previous comment (IsTaxable property doesn't get through the API) and i was wandering what i was doing wrong , spent 3 days i sware to god if i don't fix it soon i'll just hardcode it^^ My best and Happy new year!!
@IAmTimCorey
@IAmTimCorey 9 месяцев назад
Look below the video. It should be there. You can also email help@iamtimcorey.com if you still can’t find it.
@TheDogfighter13
@TheDogfighter13 9 месяцев назад
@@IAmTimCorey Thx for replying , when i tried again oppening the link and it asks me to enroll into that cource even though i have access to it in my cources , but i managed to do it , i just went to that cource , found the lecture and zip file was there , my best , Nick
@IAmTimCorey
@IAmTimCorey 9 месяцев назад
I'm glad you figured it out.
@maximilianobruzzone7964
@maximilianobruzzone7964 2 года назад
Thank you for making these videos. I get stuck.. decimal taxRate = _configHelper.GetTaxRate()/100; Not working and keeps giving me the product * 8.75 please can you help me.?
@maximilianobruzzone7964
@maximilianobruzzone7964 2 года назад
Solved the problem by changing the value in App.config 8,75 instead of 8.75. my decimal separator is "," instead of "."
@IAmTimCorey
@IAmTimCorey 2 года назад
Ah, yep, that will get you. Good job tracking it down.
Далее
Early Refactoring in C# - A TimCo Retail Manager Video
40:41
Living life on the edge 😳 #wrc
00:17
Просмотров 3,5 млн
#kikakim
00:10
Просмотров 14 млн
Display Product Data - A TimCo Retail Manager Video
1:17:22
Solving one of PostgreSQL's biggest weaknesses.
17:12
Просмотров 198 тыс.
Microservices with Databases can be challenging...
20:52
Brutally honest advice for new .NET Web Developers
7:19