On my template i have a button to collect fee that takes the user to next screen. However, i want a check on this button's click event if the fee is already paid-in-full and prompts the user via message on screen.
In related model i have method that checks if fee is paid in full. I had added the condition on template like this and it disabled the button
<td>Add Fee</td>
but this increases the number of queries as i have a many students records on current view.
In general if i want such validations before user can go to new/assigned view, what would be the best practice.
Since you've asked for best practices followed, I will point out a few:
Pagination, use offset and limit for fetching the list of Students - have a look at index function here - thereby preventing too many database calls in one go.
Getting such information ideally shouldn't require extra DB calls, the table joins should suffice - thereby taking away the need for several database calls.
Note: I'm not suggesting changing the view/ user experience, as that would be out of the scope of this discussion.
Related
I'm building a Django web application, part of it involves an online ordering system for food. I want to make a "receipt" object to save transactions.
My concern, however, is this - let's say I have an object Receipt that relates to Orders which relate to Items, if the items get edited or change over time, it will make the receipts look different down the line. Is there a way to save these at the moment of a transaction?
I am implementing a "soft deletion" to my models to avoid deletion issues however I don't think this would protect against edits.
The only way I can think of to deal with is to 'materialize' the Receipt. In other words when a receipt is generated use the Order and Items information current at the time and then write the actual values, not the Order/Items id to a receipt table. So for a Items item write out the attributes(description, price, qty.etc) you are interested in recording to the table, instead of just an Items.id that points to a possibly changed value in future.
I am having a problem in QTP with selection of a web list box and I have exhausted what I know to do to resolve it. I am hoping someone can help.
There are 5 controls in a container, 2 webedit controls and 3 weblist controls. Together, they allow entry of accounts associated with a customer, and there can be 16 accounts for any customer. There are only ever five controls active at any time, whether editing or entering information for an account. When the information for an account is entered and accepted, it changes to a read-only table row and a new set of controls appears below it for entry of the next account.
The information entered in these controls is the account number, type, description, designation, and status. The status value is contingent on the designation, and the items in the list change dynamically depending on what the user specifies for the designation. The status list is not enabled until the designation is specified.
After some experimenting with timing, I was able to get past an issue where the status list for the first account was seen by QTP as disabled even though it was clearly enabled. I was then able to advance to entry of the second account.
I change the designation on the second account and try to select an appropriate item (specified in a data table) in the status list. My specification from the data table is never found. I figured it was a problem with verbiage differences and also that I should probably anticipate that and address it now, so I wrote a function to accept three parameters, the list and up to two search items. My function searches the listbox passed to it and looks for a match (full or partial) on the search items it receives. Here is where I encountered a significant problem.
The list of the control my function received was from the previous iteration of the test, corresponding to the designation of that account. This is why my function was not finding the selection item. The list on the screen shows the appropriate items, which suggests that I am looking at the wrong object. I also get the ‘object is disabled’ message when I put my data table value directly into the list with the select statement.
The active controls are displayed below the readonly presentation of the previously entered accounts. I am very new to QTP, but I also read documentation. My only theory at this point is that ATP is not passing the right list to my function… that perhaps that how it was learned included the position, which will change each time. However, the spy identifies the screen control as the same item I processed for the preceding account, which makes my theory suspect. In addition, the other four controls, which are not dynamically changing, do not present the same problem. I can put the information in them consistently.
I apologize for the length of this question, but I wanted to be as thorough and clear as possible. Can anyone help me get past this obstacle.
There are many possiblities why it is exposing this behaviour, so let's start with something simple:
Did you try a myWebList.Refresh call before you do something with the listbox? Refresh re-identifies the object.
Have you put a break point (red dot) inside the custom function. Just see what is happening there. With the debug viewer you can enter a realtime command in the scope of that function like msgbox myWebList.exist(0) or myWebList.Highlight
Can you see how the disabled property is propagated to the webpage? If you can 'Object Spy' it as TO property, you can add it in the GUI Map description.
A more sophisticated aproach is to create a Description with the weblist properties. If you can read the disabled property as an RO property from the 'Object Spy', you can use it as an identifier like "attribute/customDisabledProperty:=false".
If you cannot correctly read the disabled property, you can create a description object and do a count on the amount of items that match that description on that page with numberOfLists = Browser("my browser").Page("my page").ChildObjects(myDescription).Count and get the last list with Set lastList = Browser("my browser").Page("my page").ChildObjects(myDescription)(numberOfLists-1)
Keep us informed. Depending on how this works out, we can work into a direction for a solution.
I figured this out early this morning. There are 4 different list boxes used, each made visible or enabled dependent on the selection of the previous list. This is why the spy found the one listed when I was using it and also why the items in the list were not appropriate to what I had selected and also why it appeared disabled to QTP but enabled to me.
I was selecting the same designation when trying to spy it. It was intuitive that the controls were all the same. I am also a windows programmer and I would have populated the same list each time with the appropriate list items, and I presumed that was what the web developer was doing. It was not and it took some time to figure that out. Now that I figured it out, everything is working fine, and I came back to report that. This was a significant, time-intensive lesson.
Thank you very much for your input. It is still useful because I am very new to QTP and every thing I learn is of value.
Imagine a little webshop which uses its own currency.
In the database, there is a table for items, which can be bought. The count of each item is limited. This limit is stored in a collumn in this table as integer.
Also, there is a table for the user's cash accounts, whereas for each account the current balance is saved.
If, for example, two users conduct their purchases at the same time and only one item is available, it could be possible that both users pay but only one receives the item due to racing conditions.
How can such racing conditions be resolved, without relying on entity framework throwing exceptions on saving?
How can I ensure the count of available items and the account balance of the buyer is correctly updated?
This isn't really a problem specific to Entity Framework, it's applicable to just about any shop scenario. It comes down to a question of policy - the only way to ensure that two customers do not purchase the same item is to allow a temporary lock to be placed on that item when they add the item to the cart, or begin the checkout process, similar to how concert tickets or flights are sold. This lock would expire if the purchase is not completed within a set amount of time, and the item would be released back for other customers to purchase.
In an e-commerce setting, this is not as suitable, since people may add an item to their cart and not check out, or spend extra time choosing additional items. This may lead to the scenario where you have items for sale but they can't be bought because they're in someone's cart who's not planning on checking out. Instead, duplicate orders are allowed, but payments are typically only pre-authorised and then completed at the time of shipping or order confirmation, so even if the second customer enters all their details and presses Buy, their card wouldn't be charged since the item wouldn't be shippable.
You can implement checks at different stages during the Checkout process to ensure the items in the cart are still available, or at the simplest level, leave it for the final "Pay Now" button on the last page. Ultimately though, this just reduces the potential for the race condition, rather than eliminating it.
What are strategies to deal with seemingly common scenario of a limited inventory and an order form.
If there is one item left, and two people attempt to purchase at the same time. How do you deal with whoever submits payment last?
When a user adds a limited-supply item to their shopping cart, put a hold on the item for a small window of time - say, 15 minutes. It's theirs if they pay within the window, otherwise the hold is removed and the item is returned to the pool. (For the duration of the hold, the item considered "not available" to other users.)
AFAIK, it's pretty standard technique - I've seen Gilt do this, for instance.
My model:
class Order(models.Model):
property_a = models.CharField()
property_b = models.CharField()
property_c = models.CharField()
Many users will access a given record in a short time frame via admin change page, so I am having concurrency issues:
User 1 and 2 open the change page at the same time. Assume all values are blank when they load the page. User 1 sets property_a to "a", and property_b to "b", then saves. A second later if user 2 changes property b and c then saves, it will quietly overwrite all the values from user 1. in this case, property_a will go back to being blank and b and c will be whatever user 2 put in.
I need recommendations on how to handle this. If I have to have a version field in the model, how do i pass it to the admin, where do I do the check so I can elegantly notify the user their changes can't be saved because another user has modified the record? Is there a more seamless way than just returning an error to the user?
The standard solution is to prevent your users from sharing a single record. It's not at all clear why so many users are messing with the exact same Order instance.
Consider that Order is probably a composite object and you've put too much into a single model. That's the first -- and best -- solution.
If (for inexplicable reasons) you won't decompose this, then you have to create a two-part update transaction.
Requery the data. Compare with the original query as done for this user's session.
If the data doesn't match the original query, then someone else changed it. The user's changes are invalidated, rolled back, wiped out, and the user sees a new query.
If the data does match, you can try to commit the change.
The above algorithm has a race condition, which is usually resolved via low-level SQL. Note that it invalidates a user's work, making it maximally irritating.
That's why your first choice is to decompose your models to eliminate the concurrency.
my model has a miscellaneous notes field
This is a bad design. (a) Concurrency is ruined by collisions on this field. (b) There's no log or history of comments.
Item (b) means that a badly-behaved user can maliciously corrupt this data. If you keep notes and comments as a log, you can -- in principle -- limit users to changing only their own comments.
[In most databases with "miscellaneous notes" the field has become a costly, hard-to-maintain liability full of important but impossible-to-parse data. Miscellaneous notes is where users invent their own processes outside the application software. ]
"miscellaneous notes" must be treated like a log, with an unlimited number of notes -- date-stamped -- identified by user -- appended to the Order.
If you simply partition the design to put notes in a separate table, you solve your concurrency issues.