Recording a many-to-one relationship in Access 2007 forms - ms-access

Here's what I want to do:
The user should be able to enter a new "sale" record with some basic information (who's buying, etc.), and then add items to that sale (like a shopping cart). There's one master "Sales" table and one "SaleContents" table, that look like:
Sales: int ID, name of person buying, etc.
SaleContents: FK SaleID, Item Purchased, Quantity, etc.
How do I make a form that will allow a user to add an arbitrary number of purchased items, and then, upon saving, it:
Makes a Sale record
For each item purchased, makes a SalesContent record with a FK pointing to the above
If the user cancels, neither the Sale record nor the SalesContent record are created.
Will I have to do all of this by hand in VBA, or is there some functionality in Access to help me?

The simplest way is to use a bound form for the sale and a subform for the sales content, however, you will have to delete the record if the user cancels. It will be simpler if you allow cascade delete in the relationship between sale and sale content.
With a form / subform set-up the Link Master Field (which can also be a control) provides the value for the Link Child Field, in this case SalesID. The content ID can be provided with an autonumber.

Related

MySQL: How to keep history of an item?

I have a process wherein I need to keep the history of a database records information, however the user needs to be able to change it at any time they please.
Scenario:
Seller creates an item with price of $5 and name of "foo"
Buyers buys item, an order is created linking to that item id
A while later, seller updates item name to "foobar" and item price to $6
Buyer views order history. The item name should be "foo" and price should be $5 since that's what they bought it at, but they are "foobar" and $6, respectively
This happens because when the seller updates the item, they are updating the same item the order is related to.
I thought of 3 possible solutions to this problem, and I would like to get your thoughts on which one you think is best (maybe from your prior experience), or a better solution I have not yet thought of. This is my first time dealing with this situation, so not sure how best to proceed without needing a refactor later.
My solutions:
Make the item name and price immutable.
Bad UX, cause now user has to delete item and recreate it if they want to make a modification
Requires some kind of deleted_at column in case user wants to delete the item after it has been purchased so that I can still keep it for referencing later to grab history data
Create a second table for history purposes
Not horrible, but requires a second table with a different name, not a big fan of the idea
Would have to run queries potentially twice to check both tables for similar data, as opposed to just querying one table
Create two records in the same table, and mark a boolean flag or some other flag to differentiate from historical/current records
I like this one the best, but not sure if the boolean flag may have any negative performance implications
I've encountered this issue too, particularly in product catalogs where the price changes frequently. Or the price may be on sale or discounted for a specific customer for some reason.
The only solution I've found is to copy the relevant product details to the customer's order record at the time they buy the product. In your example, at least the product name and the product price would be copied.
This might seem like it goes against the philosophy of "don't store redundant data" but it's not redundant—it's a fact that the customer bought the product for some specific price on a specific date, and that is still a useful fact forever, even if the current price for that product changes.
There should still be a link to the original product table, so managers can track how many orders included each product, for example. But the current price in the product table does not affect the record of each customer's order.
You might also need to create a product history table, to keep a record of all the times the price or name was changed. But that's for historical record-keeping only, it wouldn't affect typical queries during shopping or buying activities.
In this design:
Product table always stores the current price.
When a customer buys a product, they copy the current price into their own order record.
When a manager changes a price, the app creates a new record in the ProductHistory table.
The most recent record for each product in the ProductHistory table matches the current price for the same product.

Access: Entering multiple subform values with one entry in the form

I've been using Access to create simple databases for a while with great success, but have run into a problem I can't find an answer to.
We ship individualized serialized units to various end-users, and occasionally to resellers that stock them for end-users. I must keep track of which serial numbers end up with each end-users.
The first database I created to handle this recorded company information in one table using their account number as primary key, order information in a second table using the order number as the primary key and linked via the company name, and unit information in a third table with the serial number as the primary key and linked via the order number.
This worked very well until I had to account for these stock orders with a reseller. As it was structured, every unit was linked to one company via the sales order. The issue is that I may ship 20 units on one order to Company A, who then sells 5 to Company B and 3 to Company C.
I realized I needed to link the company name directly to the units, not the orders and have fixed that.
My issue now is simplicity in entering information in the form. My previous database involved the employee in our shipping department merely entering the sales order, selecting the customer name from a drop down menu, then scanning the serial numbers in a subform. This was to ensure simplicity and try to eliminate human error. He had only three things to input, and most of the input was done by scanning barcodes.
As it is currently structured now, the employees out in shipping would have to populate the company name for every record in the subform with the serial number and that complicates things in a way that is unacceptable. At the point of shipping, the company name will always be the same for every unit in the subform.
So.
How would I go about creating a form where the company name is entered once in the form, and automatically populates itself for every record in the subform? The caveat here is that I must also be able to go back occasionally and change the company name of individual units in an order without necessarily affecting the rest of the order. I suppose it starts out as a one-to-many relationship that then must be able to change.
I hope that makes sense.
I have looked for answers using various approaches with auto-fill and relationships and not preserving data integrity, but I feel the answer is just beyond my reach.
The only solution I can think of is to create another field in the unit table for the end-user, and perhaps write a formula that sets this default value as the company name from the order that shipped it. This seems unnecessarily complicated and redundant, there has to be a better way.

Database Schema for Registered Customers and Guest Checkout

For an ecommerce site that allows both Guest checkouts and registered user checkouts, how will you handle the 2 different customer groups?
Do you store both groups in the same table customers which has a foreign key customer_group_id pointing to another table customer_groups? In this case, will you worry about duplicate guest checkouts "polluting" the customers table?
How will the information captured for the 2 customer groups be different? I am thinking the difference is that the guest checkout customers will not have a password thats it.
I store customer information directly in the order rather than rely on the information in the customer record. That does a couple things:
I don't have to have a guest user in the customer database
If my customer information changes, or if a customer wants to ship one item to one place, and another item to another place the information about the order will still be correct.
I view order information as historical data. It should not change because something else in your database changes. For example if I order something from you, and at some later time I move and update my billing and shipping information, you should still know that the previous order was billed and shipped to the previous address. If you rely on the relationship between the customer and the order to retain bill to and ship to information, Once I move and update my profile, you think you shipped to my new address. You may not see that as an issue, but it will be.
You can still get the current information from the customer record to populate the fields on the order if the customer has an account. For a guest, he has to type it every time.
The common entity is a Checkout. The guest checkout would be a null FK link on the checkout entity to a registerd user entity.

UniDac MySQL transaction issue

I am using Delphi, UniDac and MySQL.
I have a table Invoices and one other InvoiceItems.
Table Invoices holds the basic information such as date, number, customerid etc
Table InvoiceItems holds the items that are attached to the invoice productid, price etc
When user clicks to add a new Invoice
Invoices.Insert;
He can start adding the details. But when he wants to add items, with the current design I have he has to save the record first, obtain the InvoiceId and then start adding records to InvoiceItems with the corresponding InvoiceID.
Is there anyway to do it without saving the record first? As I can see it can be done with transactions but I am not sure how to design this.
Please note that the software is multi-user, two users can insert an invoice at the same time.
Thank you

Challenging data modeling problem

I have a table that stores customer items. The table needs to reflect the following activities:
When a customer adds an item to his/her queue.
When the item is marked for shipping to the customer.
When the item actually ships.
When the item is marked for return by the customer.
When a return shipping label is created for the item.
When the item is received back from the customer.
The work flow will be as follows:
User(s) add item(s) to list.
Scheduled event marks items for shipping (corresponds to info point 2).
Employee creates shipping labels, then marks items as shipped (to info point 3)
--- Customer receives item, customer is happy.
Customer marks item for return.
Employee creates a shipping label the item.
Item gets picked up and returned.
A customer's account should show the following:
Items in queue.
Items shipped.
Items marked for return (to allow customer to cancel if customer wants to keep the item for longer).
There is no value (in my scenario) for alerting the customer when an item has been marked for shipping on our end.
I initially thought of inheritance, but things have started to get out of handle quickly. I don't know if I should have a subclass for each info point. Also, some things seem like they should not be in their own subclass (items marked for shipment, and for return, seem to be "in between" classes)
Should I be using inheritance and create a class for each information point? Or am I over complicating this?
Current schema
items
- id
- typeid (in queue, shipped, etc....)
- userid
- itemid
- shippedat
- returnedat
I'm using mySql, and anticipate the table to be large!
It sounds like you need a good way to separate the items themselves from the workflow which applies to them. One approach could be as follows:
Define a table of items, minimally containing the userid and itemid
Define a table of workflow states, minimally containing an id and a name (e.g. 'processing', 'shipped')
Define a table linking items to workflow states, containing a foreign key to the item's id and a foreign key to the state's id, plus metadata applicable to the given item in the given state, such as when the state was entered or started/finished, who handled or checked-off the item in that state, etc.
Now, instead of having state-specific fields such as shippeddate and returneddate on the items table, you can find that data by joining a given item to its workflow (warning: pseudocode ahead!):
SELECT item.id, item.userid, item_workflow.completed_date AS returned_date
FROM item
JOIN item_workflow
JOIN workflow
WHERE workflow.state = 'Returned'
By joining items to their workflow and filtering for specific states, you can find items that are or are not in given states, and count items per state. So to address an example from your question:
There is no value (in my scenario) for
alerting the customer when an item has
been marked for shipping on our end.
In this schema, you search for a given item for a given user, and see if an item_workflow record exists for that item and the workflow state "Shipped".