I am working on a sharepoint 2010 application where I need to "trick" SharePoint into updating a bunch of child list items when the parent is updated. What I have works some of the time to update some of the items in the child list. Most of the time I get an error for the workflow that updates the child list items.
The workflow could not update the item, possibly because one or more columns for the item require a different type of information.
There are three lists and related columns:
Project - Name (single line of text)
Project Tasks -Project Name (lookup field connecting to project), Project Name 2 (single line of text)
WorkFlowControl - This is used to create the looping
Here is a description of the logic:
When a Project Lead is assigned to that project a workflow fires to update the projects tasks with the project leader's name (updates a person field). It finds the first task that has the same Project Name 2 as the Project that was just updated. Once it sets the project lead it updates the Project Name 2 field by appending a number to the end of the Project Name. This is makes sure this item is not found and updated on the next loop.
When the task is updated it triggers a workflow that creates an item in the workflowcontrol list that holds both the project name and project lead
When an item is created in the workflow control list it triggers a workflow that updates the first matching item in the project task list that has the Project Name in the Project Name 2 field. When it finds one it sets the Project Lead and updates the Project Name in the Project Name 2 field.
The problem is the workflow that fires when an item is created in the workflow control list tends to error with the above error and sometimes the Task is updated with the project lead and other times it does nothing. I suspect the problem has to do with the fact that I am using the project name 2 value to find a list item and also updating that value to make sure it is not found on the next loop. Like I said it sometimes works (updates all tasks with project leads name) other times it only does a few. Which makes me think it is a timing thing but I don't know.
Here is a screen of what the workflow that updates the project tasks when an item is created in the workflow control list. It first sets a workflow variable to hold the project name, then updates the project lead with data found in the workflow control list. Next it should 'log' that the Project Lead was updated. Next it updates the project name 2 value where the project name 2 value matches the project name (see next image)
Related
I am having the following case:
There is entity 'Master_Entity'. This entity has properties as name, type, duration etc. There are other two type of entities 'Entity' and 'Sub-Entity'. There are identical as the 'Master_Entity' (They have absolutely the same properties).
At the end the 'Master_Entity' should hold a collection of 'Entity' and 'Entity' should hold a collection of 'Sub-Entity'. The tricky part is that records of type 'Entity' can be part of different 'Master_Entity' (same for 'Sub-Entity'), but they can have different values for duration for example. How can achieve such modularity?
Here I came up with, but it's not quite do the work. May you guys help me with this.
Edit: Imagine this as some sort of a work tracker. For example you have a 'Create PHP App' (Master entity). This entity contains duration of how long it will take to finish this job. In addition it contains a entity 'Writing Code' (Entity) and this one can be divided to 'Writing Http Client' (Sub-Entity) which has duration property which is specific for this job.
On other side you might have other job: 'Create an Java App' (Master Entity) which will contain the same 'Writing Code' entity, but with duration which will have different value, because of the context of the Application you are building.
I want to have a single record 'Writing Code', but the duration value that it have should be different for every job it's assigned to. How can achieve that with creating a minimum duplicating records of type 'Entity'?
It sounds like something like these 3 tables will work for you:
Entity
* Id
* Name
* Type
EntityGroup
* Id
* Name
* ParentEntityGroupId
* ParentEntityId
EntityRelationship
* Id
* EntityId
* ParentEntityId
* EntityGroupId
With this structure, you can have an Entity be a member of a Group, or a solo Child of another Entity. You can also have a Group be a Child of an Entity, or even a Child of another Group. Without knowing specifics of your data, it's hard to know what you might need, but this should get you started.
From what you have said, it seems that you don't need EAV at all because you don't have different properties for each item just different values. And thus you should not be using it.
What you need is a combination of lookup tables and then tables that address the actual tracking history of the work. This is because this is time sensitive data. The tasks at the time the projects was created may be substantially different than the tasks associated with that task group two years from now, but you need to record the tasks at the the time of creation). Note that this is not denormalizing, it is creating a picture of data in time. The real duration always goes to teh project not ever to the Task. In the task, you can have a suggested duration to use as a starting point. I used a similar design (with far more fields of course) to design a database for building sales proposals for technical-hardware related projects. The real key here is to recognize what data needs to be stored as a point time time and what is lookup data used to build the final project data. If someone adds a new task to the "Create a Java App" group, you don't want to change details about projects already completed or in work, only new projects.
So you need:
Task group
Task Group ID
Task Group Name
Task
TaskID
Task Name
SuggestedDuration (can be null if you have tasks that are always different
but filled in for tasks that usually have a similar duration)
Task_Taskgroup
TaskID
TaskGroupID
Project
ProjectID
ProjectName
TaskGroupID
ProjectTask (should be filled in automatically when the task group is
chosen for the project)
ProjectID
Task ID
EstimatedDuration (fills in the default value, but can be changed
by the person creating the work project)
ActualDuration (Field in after the task is done, can be used by an
analyst to create more reflective task default duration values)
Of course each of these tables may have other fields depending on the need.
I have a list called "Tasks"with a number column called "Count".
On the "Workflow Tasks" list, I have a workflow that gets triggered on item added or item changed. When a workflow task is created/edited, the workflow checks the status of the task and either adds 1 or minuses 1 to the "Tasks" "Count" column.
If I add a single task to the workflow task list, the workflow picks it up and adds 1 to the "Count" field perfectly. However, if i add two tasks to the workflow task list, one after the other, the second task's workflow results in an error.
It's almost like i'm unable to update the "Count" field multiple times. I assumed that the row was somehow "locked" while the first instance of the workflow was updating it, so I added a pause, which didn't help. (I guess because the 2 instances pause at the same time.) I then added another column to the "Tasks" list called "Busy" and set this to "Yes" while the first instance updated the row. When the second instance runs, it first checks if "Busy" is "Yes" and if so, it pauses for a duration and then carries on. This still does not work.
Is my assumption of row locking correct? Or what am I missing?
TIA!
Edit: I don't have access to the error logs and the error simply states "An error has occurred in [Workflow Name]".
do you have many workflows and only one task to change? workflow runs, when task is changed or workflow list is changed?
Basically, say I have a report A and I want to add a link column to it, and I set its target to a page in the application...the page its referring to has another report (lets call it B)
Is it possible for me to somehow make it so that table A's link column opens the page with Report B with rows that have the same column value for one of their columns?
Example here:
A
Name Num1 Num2
--------------
A 5 3
B 3 3
C 4 2
B
Name Quantity Serial
--------------------
D 2 3
E 1 8
F 4 6
So if I click the link column for row A, I want it to open report B and only shows rows where its Num2 = Serial, so only row D would show since it is the only one that equals 3
Using Report Linking to Filter Other APEX Report Outputs
I had some fun with this one although. The "A" and "B" stuff was pretty dry, so I decided to create a data set that was more engaging, and perhaps clearer to understand for the rest of us... :) This is how the data-ecosystem was broken down, and the way I fulfilled the OP requirements.
The Test Schema:
Welcome to the manufacturing facilities of the "Recipe Stack" Food Works. The schema design and ERD (Entity Relation Diagram) is below, with the sample data used for this demonstration:
The data relations are as follows:
The staff at the Stack Food-Works keeps an inventory of all ingredients for the types of meals and prepared foods they manufacture. Each ingredient has a unique ID (INGREDIENT_ID) and the staff tracks the amounts of each item in their pantry.
Each ingredient can be used in multiple recipes, but they will be used exactly once for a given recipe.
The ENTREE_RECIPE table has a COMPOSITE KEY which means it is the combination of the two pieces of this composite key (ENTREE_NAME and INGREDIENT_SEQ) that should be unique.
There is a FOREIGN KEY relation between the INGREDIENT_ID values of both tables.
Report Display Requirements (APEX and SQL Design Elements)
Selecting an item from the FIRST report is used as the input and the restriction/filter criteria of the second report.
User Case #1:
User Selects a Ingredient ID from the list of available ingredients in the pantry.
Input from (1) filters output of the RECIPE REPORT. This is a list of all the recipes that have the chosen ingredient in their formula.
User Case #2:
User Selects an ENTREE_NAME from the RECIPE REPORT. The ENTREE_NAME is used to deliver a third report: the RECIPE FORMULA which is the full recipe for the entree item that was selected from the previous report.
Testing Tools
(You usually need these these for the more complex pages, so it's a good start to use or develop them for the easier ones...)
I made my own, but you can also invoke the SESSION link on the developer's tool bar at the bottom of the APEX page on your running application (when it is displayed).
Here's my idea; it's a header region that also has a button to RESET input values so that I can clear the cache and retest or try other examples. I'll show later how you can use this link to see what is going on. You can see it in the discussion of testing at the bottom of this guide.
APEX Report/Page Design and SQL Parametrization
My columnn linking scheme looks similar to the previous post such as the one from FTaveras. This is how my linking works. What's different is that I do not go to another page, I simply go BACK to the same page I came from. Redirects and Branches apparently don't care if they are simply returning to the same location.
What is different on the return trip is that page parameters that were originally null or unpopulated NOW have a value. That value now brings life to the reports on the page that were empty.
Step 1: The PANTRY REPORT
Output: Query all items from the FOOD_SUPPLIES table.
Inputs: Supply links by INGREDIENT_ID to filter the RECIPE_REPORT output.
How to do it: (hint) To accomplish this, define the report column/field value in your report layout design page as a "linked" column and assign its value as a page item. The page item will be referenced in the SQL query of the next report...
Step 2: The RECIPE REPORT
Output: Query all records from the ENTREE_RECIPE table which have the INGREDIENT_ID from Step 1 within their formula.
Input: Supply links by ENTREE_NAME to filter the RECIPE_FORMULA output.
How to do it: (hint) Include the page item defined from Step 1 within the SQL query of this report:
SELECT * FROM entree_recipe
WHERE ingredient_id = :P3_INGREDIENT_ID
Step 3: The FORMULA REPORT
Output: Query all records from the ENTREE_RECIPE table which have the ENTREE_NAME selected from Step 2.
Debug and Test Run
Most will be able to get this far without any problems. If not, here are a couple of examples of how you can debug and test your work. There may be some built-in tools and packages that already exist within Apex, so any suggestions on alternate approaches are welcome in the comments...!
Using the APEX Developer SESSION Output
After selecting the inputs for the trial run, click on the SESSION link on the developer toolbar at the bottom of the page. This is an example output:
Note that the page items that were set for that session are displayed. The inputs I used for this test were:
INGREDIENT_ID: 6432
ENTREE_NAME: peach cobbler (fresh)
Extra Credit: This one is an alternate approach. It may be useful to design something like this as an add-on to any app you design. You do not need to remove it from your app when you push it to production because there is a "conditional display/suppress" feature for page regions. (check it out)
Simply set a global parameter as a "mode" on your Apex app. Set the value to "DEBUG" or "TEST" or whatever and key all your instances of this page region to display only when the global parameter is set to it.
Wrap Up and Discussion
Hopefully, you've enjoyed your visit to the "Stack Food Works" (no tasting or sampling from the line, please).
This has been more of a holistic approach to Apex app design. It helps to have a methodology to map out each step, and a way to check your work at both the beginning and the end of your development process. Using smaller examples like this demo to apply these methods provides a chance to understand Apex development as a Software Creation PROCESS.
Yes it's possible.
On page B, add and hidden Item name for example P(#)_SERIAL where (#) is your current page number.
Modify your query and add one line like AND SERIAL=:P(#)_SERIAL.
On Page A go to "Report Attributes" tab on the report region, click edit.
On the column link section configure your link to page B and set the hidden item on page B to the value on report column of page A.
Name: Item 1 [P(#)_SERIAL] Value: #Num2#
Demo
I've got an Access 2007 database where I created a report showing projects (using tblProjects). I then created a sub-report showing project history (using tblProjectHistory). The sub-report is linked to the parent report by fldProjectID (tblProjectHistory) and projectID (tblProject).
The layout is such.
::Project information
--> project history information
++++++++
::Project information
--> project history information
(repeat)
The projects list out correctly, and any project history is also appropriately underneath the respective project. No overlap at all.
I'm wanting to limit the number of project history records in the sub-report to no more than 5 for each project. I've tried modifying the sub-report record source to have "TOP 5" in it. but then it ends up limiting the overall number of sub-report records - no matter if they are under one project or not.
Any idea how I could accomplish that mission? Thank you in advance for your time.
You were on the right track with TOP 5 but I can't think of a way you can do this using the tables themselves as a datasource for the subreport.
I would recommend using a query as the data source for the subreport based on the project ID in the report WHERE projectID = [reports]![reportname]![report project ID field]. You will then be able to group relevant records together by project and select the TOP 5 records for the subreport.
I have a spreadsheet in excel with three headers:
Project Name
The name of a project i'm working on.
Requested Role
The job title/profession of the project employee. (example: mechanic, manager, engineer)
Name
The name of the employee.
When i click on the Person's name i want another page or tab (specific to this person) to appear showing details about them such as their name, job title, how long they worked, what project they are doing... etc. (similar to a Facebook profile)
When i click on the project name i want another page or tab (specific to this project) to appear showing details about it such as the requirements, the deadline, who is currently working on it... etc.
Furthermore, i would like to set up two levels of access:
Managers:
People who can add new information but not change or delete existing information
(write-only permissions)
Administrators:
People who can have full access to all information.
All highest level of access.
I don't know how i would go about displaying and/or organizing so much information in a vb.net application. if anyone could provide some suggestions as to some possible layouts of the GUI it would be greatly appreciated!
Additional Details:
For the specific pages i was thinking of using the tab control but i want it so that i can search through the list of projects or names, select one, and then it brings up the page about it.
The levels of access is the least of my worries... although it is still a worry.
You don't want to store that information in an excel spreadsheet, a database is much, much better. For what you've described here I'm going to assume that you have Projects and Employees, and that multiple Employees can work on a project. You'll need a few tables then:
Project
ProjectSeq 'Int - unique sequence for this project record
Name 'String - name of project
Descr 'String - description of project
... 'Various - other fields as needed
Employee
EmployeeSeq 'Int - unique sequence for this employee record
Name 'String - Name of employee
Title 'String - Job title of this employee
IsManager 'Boolean - Is this employee a manager?
IsAdmin 'Boolean - Is this employee an administrator?
... 'Various - other fields as needed
ProjEmpl
ProjEmplSeq 'Int - unique sequence for this project-employee record
ProjSeq 'Int - link to project record
EmployeeSeq 'Int - link to employee record
... 'Various - other fields that apply to this project-employee combination
Once you have your tables all set up and populated with data, you'll want to read the data and transfer it to your .NET application. There are a few ways of doing this, you'll have to decide which works best for your needs. I'm a big fan of DataSets, they always work nicely.
To fill the grid, you'll need to use a sql statement that fills a datatable from the three tables (I'm using notepad as my IDE, so this may not be exact):
SELECT pe.*, p.Name as ProjName, e.Name as EmplName, e.Title
FROM ProjEmpl pe, Project p, Employee e
WHERE p.ProjectSeq = pe.ProjectSeq AND
e.EmployeeSeq = pe.EmployeeSeq
To display the data to the end user, you would use a DataGridView control. Set the datagrid.DataSource to use the datatable you just populated and the data should show up.
To display the related Employee & Project information, I'd use a tab control underneath the datagrid. One tab for Project, and one tab for Employee. Use individual controls for each field in the table. When the user changes rows in the datagrid, load the related Project and Employee information for that row into two datatables and populate the controls from that.
Lastly, to set permissions on the program you'll need to have the employee log onto the application. Once they've logged on you can look them up in the Employee table, find out if they are a manager or an administrator, and set the permissions accordingly.