I am designing a database for a sales company having a complex workflow. The flow starts at Sales Officer, then go to Team Lead and finally Manager. Before approving a proposal, manager will send it to the Division Business Analyst. After getting remarks from dba, he may send the proposal back to sales officer for modification in the proposal. The manager may also reject the proposal. If satisfied, manager will forward it to Director, Sales. The tables designed so far as follows:-
Table: ProposalBasicData
Id, Title, ProposalDate, Scope, Objective
Table: ProposalState
Id, Name
(Values - Forwarded , Approved , Returned , Rejected)
Table: UserType
Id, Name
(Values - SalesOfficer, TeamLead, Manager , DBA, DirectorSales)
Table: WorkFlow
Id, StartUserType, NextUserType, StateId, IsActive
Table: RequestAction
Id, ProposalId, WorkFlowId, UserId, ActionDate
Please suggest regarding the design.
There are many questions raised by such problems. Ex:
in your tables, Workflow defines transitions from state to state as changing the assignment from one user to the next.
this can be an issue. Lets say the user is sick, leaving, on vacation, ... Then your flow is blocked.
It does not allow for the group concept either.
others (like I) would define a transitions table. StartState, NextState.
The workflow would be a list of transitions.
Each transition requires the user to be of a certain type. Or from a user management point of view, have a certain role, or be member of a group.
If your workflow is fixed and is not subject to change, your method could be ok. But if the workflow is flexible or might be changed / adapted, you should go with something more flexible.
The type of setup you are talking about make me think of the Jira software (form Atlassian), where you define tickets, with status, workflows and users. Is it possible for you to use (i.e purchasse or OpenSource) a workflow management tool? It might be cheaper in the long run than building one.
Your model will potentially be expanded to include:
clients. Which client is the proposal for?
who is the sales representative or account manager who is responsible for auditing the workflow and moving it forward?
link to other systems: how does it link to purchasing, accounts receivable, ...
All this to day, this requires an in-depth analysis which is hard to do on a medium such as this (SO).
EDIT: 20181004
I added the following model following your comment. I decided to put the workflow(s) in the database:
Notes (tables in alphabetical order):
Employee
Each employee can be linked to n number of EmployeeRole via the Employee_has_EmployeeRole table.
Proposal
An Employee is linked as the Sales Officer, since he initiates a proposal.
A workflow is linked since many workflows could exist for different proposals.
Transition
Linked to State twice. The start state and the end state.
An EmployeeRole is linked, to identify which role an employee must have to perform this transition.
Enforcing that will be done by the application.
Workrlow_has_Transition
Links Transitions to Workflows.
The Employee who completed the transition is recorded here.
The date it was done is also kept here.
The OrderInWorkflow is just a number that allows you to order Workflow_has_Transition entries.
The application will have to make sure a Transition is not done before the others of lower order are done (i.e. DoneDate is null).
It will also validate that the Employee trying to complete it has the proper EmployeeRole.
Now, the employee group concept. You can say that a group are employees with the same EmployeeRole. Therefore, when a notification needs to be sent by your application, send it to all users with the required role for the Transition. This avoids you having to create an EmployeeGroup table, which links employees together.
Application scenarios:
- Start a Proposal
- Verify that the user trying to start a new one has the role "Sales Officer"
- Collect basic information.
- Link the Sales Officer to it (current user).
- Link a Workflow to it. Only propose the workflows which have at least 1 Workflow_has_Transition.
- Send a notification to the Employee(s) which have the EmployeeRole for the first Workflow_has_Transition for this new Workflow.
- These employees receive a notification.
- Progressing through the workflow
- An employee receives a notification about a Proposal and it's "todo" Transition.
- Employee views Proposal and Workflow (use the OrderInWorkflow to ORDER BY Transitions).
- Employee approves if he has the proper EmployeeRole, fill DoneBy_idEmployee and DoneDate.
While going through your application scenarios, you will find gaps or missing items.
Ex.1 do you want to record the rejection of a Transition? How would that be handled then? You send a notification to the employees with the role for that Transition to review it?
Ex.2 do you want to keep the complete history of the proposal? Ex. it Transition X is rejected twice, but approved the third time around.
There are many scenarios like this which will show the weaknesses of your model, which you fix as you complete this analysis. Now it is not perfect, I did not put a lot of time on it. But it is a starting point and illustrates my idea.
I would suggest you structure some where along this
ProposalBasicData {PBID,Title, ProposalDate,Scope,Objective}
ProposalState {PSID,Name}
UserType {UTID,Name}
User {UID,Name,UTID(Usertype UTID FK) }
Request{ RID, StartUID, StartDate ,PSID, IsActive }
RequestAction {AID,RID, RequesterUID, ReceiverUID, Date, Comments, IsCompleted }
as I think there could be multiple users of the same type, more over you would want to have comments on why it a RequestAction was rejected, A requester would make a requestAction to a receiver and if its completed it would show in the system make life easier when handling multiple requestActions of the same Request.
Hope this helps but i suggest you make a flow chart and look at what are all the possible use cases.
Related
I'm an intern student at a company that does both wiring and aircon services. The job that they gave me was to make a database for them. I don't have any experience in anything related to databases.
So, I started to look up videos and stuff to at least learn a bit about databases and made something that works and I made it after 1.5 months of learning.
in the database that I created,
I have 1 table (CustomerDetailsT):
CustomerID (pk)
CustomerName
PhoneNumber
Address
Aircond (type and model of ac,ex: WM daikin 1.0HP)
AcDetails (what has been done for the ac.)
Others (yes/no) (Wiring, installing a fan and so on)
WhatHasBeenDone (shows what has been done for others)
Then 3 queries (CustomerOthersDetailsQ, CustomerAcDetailsQ, CustomerDetailsQ).CustomerAcDetailsQ has CustomerName, PhoneNumber, Address, Aircond and AcDetails. CustomerOthersDetailsQ has CustomerName, PhoneNumber, Address, Others, and WhatHasBeenDone.CustomerDetailsQ has CustomerID, CustomerName, PhoneNumber and Address
And 1 form with 3 subforms.
it's a search form, which would search for customers as we're typing in their name/phone number and it will show what has been done for the customer.
With this, I have created what the company wants, but now they want to add dates. Dates which would show when we have done something for a customer. Dates for Aircond and the Others stuff.
I've tried with what I know and it didn't work. tried searching it on youtube and google, but still couldn't find it.
how can I go about doing this?. I have tried having separate tables for each service, but it became a hassle when I wanted to create a new customer. . I hope I could some help, I could send pictures if someone needs them.
[1]: https://i.stack.imgur.com/mtrmC.png [The Customer search form] [1]: https://i.stack.imgur.com/A3Y9d.png [example of a customer that has ac installation] [1]: https://i.stack.imgur.com/dsGL5.png [example of a customer that has both ac and wiring done]
Acknowledging the question is too broad, here is some guidance. One of the nice things about Access is that each database is a single file. First protect your work by finding that file and make two copies. Make a backup and a play around version. Only mess with the play around version.
Your question indicates you are still learning Table Normalization and 1 to many relationships. Both of these topics are general to all databases, so you don't have to restrict yourself to just Access when looking for guides and Youtube videos.
Part of normalization is putting separate entities into their own tables. Also, in Access there is a big payoff for using the Relationship Tool, so here is a rather lame example of normalization:
Make sure to select the checkboxes when setting up relationships.
WhatHasbeenDone should also have WhatHasbeenDoneDate. I've wrapped AC and Other as Unit because later it will be easier than having two WhatHasBeenDone tables(AC)(Other).
Now imagine someone taking the customer request call. They just want to see a form to enter the customer details, request, unit-type, etc. They don't want to see those tables. Even with training entering data in the tables is error prone. The person fulfilling the request just wants to enter what they did and when. That's how you start to figure out what your final Data entry forms will look like.
Since we normalized the tables and used the relationships tool, the payoff is Access can give us an assortment of working starter forms. Select Each Table and then hit Create and then hit Form. Choose your Favorites and start playing around from there. While playing, keep in mind that Access will not let you add an item on the many side of a relationship unless there is an item on the 1 side.
For example I selected the customers table and hit create form:
Access uses a concept of form and subform based on separate but related tables. So, to get a form that shows what has been done for each customer I created a form for the What has been done table, and dragged it onto the customers form:
Unless an ID is also being used as a part number or something there is probably no reason for the person entering data to see it. So I removed the texboxes bound to ID's. Except for UnitTypeID, where I replaced the textbox with a combobox that displays the userfriendly UnitDescription. The ID's are still part of the form recordsources, Access is still adding new IDs and using those IDs to put the appropriate data in the right tables.
Oh, didn't we need dates (went back and added a date to the table, and adjusted the subform accordingly). Also changed the subform format from single record to continuous records to show multiple dates:
In conclusion and in my opinion your final forms will use VBA behind the scenes to insert data from the forms into the tables. This is because either you will want to rapidly insert multiple records or How the end users think about the data will not match the default forms and subforms approach Access depends upon to figure out how to insert the data. However, the default approach is fast and I always use it for version 1 of my Access Databases.
P.S. For simplicity I avoided including any Many to Many relationships
I'm developing a call ticketing system for a hospital, where multiple users from different branches do CRUD activity on one table. This table has relationship restricted value column called, let say [BranchId]. There are three different type of users,
A. Ticket Manager (where they can CRUD without restriction),
B. Ticket Issuer (where they can issue/view/delete tickets but they can't resolve)
C. Ticket Resolver (where they can view/resolve/delete tickets but they can't issue).
So for example,
A patient, who has an appointment with [BranchId] 1, calls to the hospital, and wants to cancel their appointment,
A Ticket Issuer answers the phone and adds this event onto the ticket table and assigns it to [BranchId]=1.
Then the colleagues who work on [BranchId]=1 (they can only see dataset with [BranchId]=1) views the data and resolves (sets the [IsResolved] column to 1)
The patient gets a phone call to notify that their appointment was cancelled.
Solutions so far I can think of
Table Triggers:-
The Ticket Manager adds all users into a table, let say called [BranchUsers] and this table as a column called [Username] where this is populated with Domain\Username, [IsIssuer], [IsResolver] and [BranchId]. The ticket table now has a CRUD trigger when it checks if SYSTEM_USER can issue/resolve and their branch. A separate View table would be used to select from the ticket table with INNER JOIN on [BranchId] for the SYSTEM_USER. However, the problem with this approach is that users can select data directly from the ticket table and so be able to read everything in the table and the [BranchUsers] table may be hard to maintain but that is ok.
Using Active Directory Group:-
So in the Windows Server AD Group, create a group called, let say [Branch1Users], [Branch2Users] etc..., and create multiple ticket tables... you see now it got complex as if one table need some changing such as renaming a column, then the .NET Core API references need too and going back to the Trigger approach above seems easier.
So what would you think be best, please advice anything even if you think it might not help as it may help create a light bulb ideas, I will start the trigger approach for now as this project has deadline soon :-)
Specs that might help:-
Microsoft SQL Server 2019
Windows Server 2019
I'm really stuck on the best way to implement this database.
Here is my problem: The database is to store information on wedding photography clients.
A user can sign up to my site, enter the details of their wedding and get their own "wedding profile page". They can do this without having to have us shoot their wedding.
At any point the user can book a meetup, wedding, or engagement shoot. The website will check if we are available. (weddings take preference over meetups so a client that wants to book a wedding on a day we have a meetup, the meetup will be flagged for a reschedule)
We must also be able to book days off. On these days a wedding/meetup/engagement shoot can not be booked.
engagement shoots cost and upfront fee. With weddings, a deposit is due within 14 days or the date is freed up again. Meetups are free.
I am so stuck with how to implement this system. I just keep going round in circles, the best way I can think is to have a "dates" table, that links all the other tables but I'm sure this is not the most efficient way.
I think what is putting me off is the fact that there can be multiple weddings on the same day (for people who just want a wedding profile), but only one BOOKED wedding per day.
So have I got this completely wrong? or do I store all appointments in one table and use a "type of appointment" table.
SO SO Stuck, I hope you can help me!
P.S. I have missed most fields out to make it simpler to understand.
Keep it simple to begin with. You've identified many of the nouns that should correspond to entities:
USERS
WEDDINGS
ENGAGEMENT_SHOOTS
MEETUPS
UNAVAILABLE
DATES
PAYMENTS
I'd suggest that WEDDINGS, ENGAGEMENT_SHOOTS, MEETUPS and UNAVAILABLE are all type of bookings. You could have just:
USERS
BOOKINGS - this has a date and perhaps a status
BOOKING_TYPE (wedding, meetup, engagement_shoots, unavailable)
PAYMENTS
You may wish to package up all on the things a use has bought relating to a single wedding into a TRANSACTION entity etc which will allow a single payment to be mapped to multiple bookings. When one of your staff isn't available they could have a booking of type holiday etc.
There may be 2 types of USERS - your photography staff who are assigned to a booking and your customer.
Based on the status of the booking, eg. CONFIRMED, PENDING, COMPLETED and the date your business logic could send out payment demands, followups etc.
Create a simple model and start adding data you will soon see the gaps and issues if any. You should have test cases up front to ensure that the data model supports all the scenarios for your application, best to do this with a set of use cases.
I am very new to sales-force, In sales-force the owner can manually share the account with another user. I need a list that shows the manual sharing of all accounts.Would it be possible by using apex class or trigger or any other way?
Examine the AccountShare table, especially something like that:
SELECT Id, AccountAccessLevel, AccountId, UserOrGroupId
FROM AccountShare
WHERE RowCause IN ('Manual', 'TerritoryManual')
LIMIT 100
You can read up more about the values here, there's also a nice example of Apex used to share records based on rules that can't be expressed in normal sharing rules.
UserOrGroupId is tricky one -> if it will start with "005" that's an userid and your search is done. Otherwise you'll have to look it up in Group table. This will contain real groups (called "Public Groups" in the setup) as well as system-generated groups that correspond to Queues, Roles, Roles+Subordinates, Territories etc. So you might have a bit of recursive world of pain here trying to learn who actually is in this group.
I admit I was lucky in the past, level of nesting I saw in the Group table was never > 2 levels deep.
I'm a noob, development wise and logistically-wise.
I'm developing a site that lets people take a test...
My client wants the ability for a user with the roll/privledge "admin" (a step below a super-admin) to be allowed to create users and only see/edit the users that they create...
The users created in that "category" or group need some information that their superior provides.
For example, I log in as a "manager", I have the ability to invite people to take the test, and manage those people. Before adding those people, I will have filled out a short survey about myself...
Right now, the users that are invited will be asked some of the same questions as the manager. I'd like to cut down the redundancy by using the information put into the database by the manager and apply it to the invited users.
How do I set up my database to work with this criterion? I'm a little confused about how to do this! Let me know if I can add more details...
(This is a mysql and php app)
I am sure there are several ways to do this but here is one that comes to mind.
In the "users" database, I am sure you have a column to specify which manager is assigned to the user by some kind of user key. Well If this field has a value, then pull the info from that users (manager user) record.
Example:
table 'users'
key----name------managerid-----questionone------questiontwo----
1-------randy-----0------------------california----------c++--------------
2-------bob--------1------------------nevada------------------------------
Since record(key)1 has managerid == 0 then use questiontwo record to answer "Question 2".
Since record(key)2 has managerid == 1 then pull questiontwo from record(key)1 and use that for answer to question two.
You could either insert this information into the record or use it from the manager record dynamically as needed, which thought the space is still being used in the database, would be helpful since manager data might be updated and you might not want to have to update all records with that share the managerid wheh info is changed.
Make sense?