Your SlideShare is downloading. ×
]project-open[ Data-Model “Categories”
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

]project-open[ Data-Model “Categories”

1,560

Published on

This tutorial explains the purpose and use of “categories” in ]project-open[. Categories are the most widely used data-structure in the system. They are used to represent the status and type of …

This tutorial explains the purpose and use of “categories” in ]project-open[. Categories are the most widely used data-structure in the system. They are used to represent the status and type of business objects and as general classifiers.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,560
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
57
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. ]po[ “Categories” The ]project-open[ Data-Model , Frank Bergmann, 2010-09-22 This tutorial explains the purpose and use of “categories” in ]project-open[. Categories are the most widely used data-structure in the system. They are used to represent the status and type of business objects and as general classifiers. In other words: Categories represent the values of most GUI drop-down boxes in the system.
  • 2. GUI Example
    • The screenshot at the right shows a typical drop-down box in ]project-open[. The values correspond to the lifecycle of a project from acquisition through operations to invoicing.
    • Hierarchical structure: Please note the sub-states of “Potential” and “Closed”. When searching for “Potential” projects, ]po[ will include projects in status “Inquiring”, “Qualifying” etc.,
    (The list of Project States from http://demo.project-open.net / )
  • 3. Problems Solved by “Categories”
    • Nearly every business object in every business application requires a field for:
      • Status – The lifecycle of the object: Typical values include “to be approved”, “finished”, “deleted” etc.
      • Type – The sub-type of the object
    • Following best practices in database modeling, these fields are usually moved into a separate table.
    • As a result, 2 out of 3 tables in most data-models are such status or type tables. ]po[ includes 130 business objects, so we would need some 500 status and type tables. A lot of repetitive code needs to be written to maintain the values of these tables, while providing little business value.
    • Most status and type table are “flat”, while states and types in the real world are closer to trees or DAGs (= Directed Acyclic Graphs - trees with multiple inheritance). However, hierarchical queries on trees and DAGs are usually very slow and cumbersome.
    • ]po[ provides a unified system to represent states and types
    • ]po[ includes support for high-speed category queries
    (The list of Project States from http://demo.project-open.net / )
  • 4. Solution: "Categories"
    • Conventional/ traditional database design normally
    • includes “foreign key tables” defining the type and
    • status of an object.
    • ] po [ takes a different approach in order to minimize
    • the number of database tables. We use a single
    • "im_categories" table for all types of states:
    • Pros:
    • The total number of DB tables is reduced to a third.
    • A single maintenance screen can deal with all categories.
    • Built-in features:
      • Translation/Localization
      • Hierarchical categories
      • Common GUI widgets
    • Referential Integrity is enforced
    • Cons:
    • In theory it is possible to assign the wrong Category to a field. However this has never happened in practice yet.
    object_type_id object_status_id object s object_type_id name object_type s description name description ... object_type_id object_status_id object s name description ... category_id name im_categories description category_type ] po [ DB-Design: All type and status information is stored in a single "im_categories" table. The "Classical" DB-Design: Every table has it's own tables for type, status and similar information. object_status_id name object_stat e s description
  • 5. Hierarchical Categories
    • To get closed to the real-world, categories can be hierarchical.
    • Every arrow in the diagram at the left corresponds to one entry in the im_category_hierarchy table.
    Potential “ Top” Open Closed Inquiring Qualifying Declined Delivered Quoting Quote Out Invoiced Deleted Canceled (The list of Project States from http://demo.project-open.net / ) Every arrow corresponds to one entry in the im_category_hierarchy table
  • 6. Hierarchical Categories
    • The table “im_category_hierarchy” contains the mapping between parents and children of the category hierarchy.
    • The SQL and the results on the right hand side show the values from the Project Status example.
    im_category_hierarchy object_type_id object_status_id object name description ... category_id name im_categories description category_type ] po [ DB-Design: The table im_category_hierarchy contains the is-parent-of relationship on categories. parent_category_id child_category_id SELECT parent_id, im_category_from_id(parent_id) as parent, hild_id, im_category_from_id(child_id) as child FROM im_category_hierarchy WHERE parent_id in ( select project_status_id from im_project_status ); parent_id | parent | child_id | child -----------+-----------+----------+------------ 81 | Closed | 83 | Canceled 81 | Closed | 77 | Declined 81 | Closed | 82 | Deleted 81 | Closed | 78 | Delivered 81 | Closed | 79 | Invoiced 71 | Potential | 72 | Inquiring 71 | Potential | 73 | Qualifying 71 | Potential | 75 | Quote Out 71 | Potential | 74 | Quoting
  • 7. DAG Hierarchies (“Multiple Inheritance”)
    • ]project-open[ categories even allow for “multiple inheritance”. That is, one category can have more then one parent.
    • In the case of “Company Type” above, the “CustOrIntl” category (Customer or Internal) represents a super-category of both “Customer” and “Internal”.
    • Please note the additional arrows in the diagram. Each arrow represents an entry in the im_category_hierarchy table.
    Customer “ Top” Internal Provider Translation Customer Software Customer Freelance Provider Office Equipment Provider Law Company CustOrIntl Every arrow corresponds to one entry in the im_category_hierarchy table Every arrow corresponds to one entry in the im_category_hierarchy table SELECT parent_id, im_category_from_id(parent_id) as parent, child_id, im_category_from_id(child_id) as child FROM im_category_hierarchy WHERE parent_id in (select company_type_id from im_company_types) ORDER BY parent, child; parent_id | parent | child_id | child -----------+------------+----------+--------------------------- 57 | Customer | 10245 | IT Consultancy 57 | Customer | 10244 | Law Company 57 | Customer | 54 | MLV Translation Agency 57 | Customer | 55 | Software Company 10246 | CustOrIntl | 57 | Customer 10246 | CustOrIntl | 53 | Internal 10246 | CustOrIntl | 10245 | IT Consultancy 10246 | CustOrIntl | 10244 | Law Company 10246 | CustOrIntl | 54 | MLV Translation Agency 10246 | CustOrIntl | 55 | Software Company 56 | Provider | 58 | Freelance Provider 56 | Provider | 59 | Office Equipment Provider Every arrow corresponds to one entry in the im_category_hierarchy table Every arrow corresponds to one entry in the im_category_hierarchy table
  • 8. Categories Shortcut Functions
    • im_category_from_id(category_id): Returns the category name for the ID. This function is useful, because it saves an SQL join in the SQL clause. Otherwise SQL clauses could get quite complex.
    • im_sub_category(caregory_id): Returns the set of sub-categories.
    • im_category_new(category_id, category, category_type): Creates a new “category” of type “Category”.
    SELECT im_category_from_id( 71 ) ; im_category_from_id --------------------- Potential (1 row) select * from im_sub_categories(57); im_sub_categories ------------------- 54 55 57 10244 10245 select im_category_new( nextval('im_categories_seq')::integer, 'Test', 'Intranet Project Status‘ ); im_category_new ----------------- 0
  • 9. SQL Queries with Hierarchical Categories
    • Let’s assume we want to list all “Potential” projects. This listing allows us for example to calculate the value of the projects in the “pre-sales pipeline”.
    • We use the im_sub_categories() function in an “in” sub-query to return all project states below and including “potential”.
    SELECT p.project_nr, p.project_name, im_category_from_id(p.project_status_id) as status, im_category_from_id(p.project_type_id) as type, p.cost_quotes_cache FROM im_projects p WHERE p.project_status_id in (select * from im_sub_categories(71)); project_nr | project_name | status | type | cost_quotes_cache ------------+--------------------------+-----------+-------------+------------------ 2010_0036 | Motor Development | Potential | Development | 12000 .00 2010_0002 | Rollout ABC | Potential | Rollout | 50000 .00 2010_0007 | Resource Planning Detail | Quoting | Development | 6500 .00 (3 rows)
  • 10. Categories as Constants
    • Categories are used as constants in many parts of ]project-open[.
    • This is necessary because there is business logic that behaves differently for “potential” vs. “open” projects (for example, you can configure in ]po[ whether users are allowed to log hours on potential projects or not).
    • Constants are defined by convention in the head of the TCL libraries.
    • Usually, the top level of a category type is used as constants.
    • Changing these constants will break the business logic. However, the user can add sub-categories without problems.
    „ All“ Open Inquiring Qualifying Quoting Quote Out Declined Delivered Invoiced Constants, don't change! Freely Configurable Deleted Canceled Closed Potential
  • 11. Categories SQL Examples “Cookbook”
    • Select Everything About Categories
    • select
    • c.*,
    • im_category_from_id(aux_int1) as aux_int1_cat,
    • im_category_from_id(aux_int2) as aux_int2_cat,
    • h.parent_id,
    • im_category_from_id(h.parent_id) as parent
    • from
    • im_categories c
    • left outer join im_category_hierarchy h
    • on (c.category_id = h.child_id)
    • where
    • c.category_type = 'Intranet Cost Types'
    • order by
    • category_type,
    • category_id;
    Categories Definition -- We use categories as a universal storage for business -- object states and types, instead of a zillion of tables -- like 'im_project_status' and 'im_project_type'. create sequence im_categories_seq start 100000; create table im_categories ( category_id integer constraint im_categories_pk primary key, category varchar(50) not null, category_description varchar(4000), category_type varchar(50), category_gif varchar(100) default 'category', enabled_p char(1) default 't' constraint im_enabled_p_ck check(enabled_p in ('t','f')), -- used to indicate "abstract" -- super-categorys that are not -- valid values for objects. -- For example: "Translation -- Project" is not a project_type, -- but a class of project_types. parent_only_p char(1) default 'f' constraint im_parent_only_p_ck check(parent_only_p in ('t','f')) ); Category Hierarchy -- Optional system to put categories in a hierarchy. -- This table stores the "transitive closure" of the -- is-a relationship between categories in a kind of matrix. -- Let's asume: B isa A and C isa B. So we'll store -- the tupels (C,A), (C,B) and (B,A). -- This structure is a very fast structure for asking: -- -- "is category A a subcategory of B?" -- -- but requires n^2 storage space in the worst case and -- it's a mess retracting settings from the hierarchy. -- We won't have very deep hierarchies, so storage complexity -- is not going to be a problem. create table im_category_hierarchy ( parent_id integer constraint im_parent_category_fk references im_categories, child_id integer constraint im_child_category_fk references im_categories, constraint category_hierarchy_un unique (parent_id, child_id) ); Extract Categories Without Join -- A helper functions to make our queries easier to read create or replace function im_category_from_id (integer) returns varchar as ' DECLARE p_category_id alias for $1; v_category varchar(50); BEGIN select category into v_category from im_categories where category_id = p_category_id; return v_category; end;' language 'plpgsql'; -- Example: -- select im_category_from_id(48); Create a New Category Entry insert into im_categories ( category_id, category, category_type, category_description, enabled_p, aux_int1, aux_int2, aux_string1, aux_string2 ) values ( :category_id, :category, :category_type, :category_description, :enabled_p, :aux_int1, :aux_int2, :aux_string1, :aux_string2 );
  • 12. Frank Bergmann [email_address] www.project-open.com

×