OFBiz
  1. OFBiz
  2. OFBIZ-149

Better describe complex party relationships

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Later
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: party
    • Labels:
      None

      Description

      Change to the party data model to support relationships where parties act in several capacities (roles) and allowing polynary relationships.

      If someone could describe a situation where the direcition of the role matters (partyIdTo/partyIdFrom) and where the roleType is insuficient to understand the direction I will try to come up with a solution. I'm trying to understand if simply better role designations would alleviate ambiguity or if there is a real need to support direction.

      I began a discussion on this topic, there has yet to be any response
      http://mail-archives.apache.org/mod_mbox/incubator-ofbiz-dev/200608.mbox/%3c20060809155147.18528.qmail@web80615.mail.yahoo.com%3e

        Activity

        Hide
        Daniel Kunkel added a comment -

        Are all relationships bidirectional?

        I would guess by the apparent definition of relationship that they are, but it gets me to brainstorming a bit...

        The current relationship system has always seemed a bit clunky because there are two different ways of specifying data...

        Abe is a employee of Bravo Inc or Bravo Inc is a employer of Abe

        If we ever want software to know and track a certain relationship, it seems like that relationship has to be searched for in two ways.

        How would it work to create role_type pairs (employee, employer) (customer, provider) (isp, website) etc. One of the role types could be dominant, say employee, customer, isp, and only that one would ever be stored in the database.

        Furthermore, and getting back to your original question, creating these combinations would likely expose any one way relationships.

        Show
        Daniel Kunkel added a comment - Are all relationships bidirectional? I would guess by the apparent definition of relationship that they are, but it gets me to brainstorming a bit... The current relationship system has always seemed a bit clunky because there are two different ways of specifying data... Abe is a employee of Bravo Inc or Bravo Inc is a employer of Abe If we ever want software to know and track a certain relationship, it seems like that relationship has to be searched for in two ways. How would it work to create role_type pairs (employee, employer) (customer, provider) (isp, website) etc. One of the role types could be dominant, say employee, customer, isp, and only that one would ever be stored in the database. Furthermore, and getting back to your original question, creating these combinations would likely expose any one way relationships.
        Hide
        BJ Freeman added a comment -

        I may be way off, but the relationship, in views is based on which entity you specify first.
        so for employer to employee would be
        partyiD with InternalOrganisation role connected to partyID with role of employee.

        for employee to employer it would be reversed.

        Show
        BJ Freeman added a comment - I may be way off, but the relationship, in views is based on which entity you specify first. so for employer to employee would be partyiD with InternalOrganisation role connected to partyID with role of employee. for employee to employer it would be reversed.
        Hide
        Chris Howe added a comment -

        Keep in mind PartyRelationship.patch is specifically a change to the data layer. My comments will be about the types of logic layers that are possible with this data layer that are not possible or as Daniel put it, clunky with the current party relationship data layer. Subsequent patches will be to mirror the functionality of the current relatinoship system while allowing for more complex relationships.

        The relationship where someone is an agent

        Disclaimer: These descriptions may not be 100% accurate but are close enough to get the idea

        The current system employer/employee description
        <PartyRelationship partyIdFrom="10000" roleTypeIdFrom="Employee" partyIdTo="12000" roleTypeIdTo="Employer"/>
        or
        <PartyRelationship partyIdFrom="12000" roleTypeIdFrom="Employer" partyIdTo="10000" roleTypeIdto="Employee"/>

        Both are valid. Both are even possible inputting data styles as suggested by the applications. Two result sets must be obtained. Is also clunky if this employee ends their employment for a period and then comes back to work.

        The patched employer/employee description.
        <PartyRelationship partyRelationshpId="20000"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="Employee"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="12000" roleTypeId="Employer"/>

        Only one result set needs to be obtained.

        In the employee/employer relationship the direction partyIdTo/partyIdFrom is not necessary.. The direction adds no additional information about the relationship. I can't think of any relationships where the direction adds information about the relationship. However, I assume there must be at least one kind of relationship where the direction adds information otherwise I don't think the direction would even exist in the project.

        Now let me show a relationship where the patched approach is a BIG improvement over the current system and actually exists in our production environment as it is in the current system.

        10000 is an employee of 12000
        10000 is an agent of 12000 (can act on their behalf)
        10000 is a buyer for 12000 (can purchase on their behalf)

        Patched System
        <PartyRelationship partyRelationshpId="20000"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="Employee"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="12000" roleTypeId="Employer"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="Agent"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="Buyer"/>

        Curent System
        <PartyRelationship roleTypeIdFrom ="Employer" partyIdFrom =12000 roleTypeIdTo ="Employee" partyIdTo =10000/>
        <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Agent" partyIdTo =10000/>
        <PartyRelationship roleTypeIdFrom ="NA" partyIdFrom =12000 roleTypeIdTo ="Buyer" partyIdTo =10000/>
        or
        <PartyRelationship roleTypeIdFrom ="Employer" partyIdFrom =12000 roleTypeIdTo ="Employee" partyIdTo =10000/>
        <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Agent" partyIdTo =10000/>
        <PartyRelationship roleTypeIdFrom ="Buyer" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/>
        or
        <PartyRelationship roleTypeIdFrom ="Employer" partyIdFrom =12000 roleTypeIdTo ="Employee" partyIdTo =10000/>
        <PartyRelationship roleTypeIdFrom ="Agent" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/>
        <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Buyer" partyIdTo =10000/>
        or
        <PartyRelationship roleTypeIdFrom ="Employer" partyIdFrom =12000 roleTypeIdTo ="Employee" partyIdTo =10000/>
        <PartyRelationship roleTypeIdFrom ="Agent" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/>
        <PartyRelationship roleTypeIdFrom ="Buyer" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/>
        or
        <PartyRelationship roleTypeIdFrom ="Employee" partyIdFrom =10000 roleTypeIdTo ="Employer" partyIdTo =12000/>
        <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Agent" partyIdTo =10000/>
        <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Buyer" partyIdTo =10000/>
        or
        <PartyRelationship roleTypeIdFrom ="Employee" partyIdFrom =10000 roleTypeIdTo ="Employer" partyIdTo =12000/>
        <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Agent" partyIdTo =10000/>
        <PartyRelationship roleTypeIdFrom ="Buyer" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/>
        or
        <PartyRelationship roleTypeIdFrom ="Employee" partyIdFrom =10000 roleTypeIdTo ="Employer" partyIdTo =12000/>
        <PartyRelationship roleTypeIdFrom ="Agent" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/>
        <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Buyer" partyIdTo =10000/>
        or
        <PartyRelationship roleTypeIdFrom ="Employee" partyIdFrom =10000 roleTypeIdTo ="Employer" partyIdTo =12000/>
        <PartyRelationship roleTypeIdFrom ="Agent" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/>
        <PartyRelationship roleTypeIdFrom ="Buyer" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/>

        Our actual current need for this is to describe our slightly complex commission structure which is ternary
        The relationship is between the customer and company and sometimes the sales rep gets paid on sales and sometimes that get paid on receivables. or a mixture of the two. So, we need
        <PartyRelationship partyRelationshipId="20000"

        <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="InsideRep"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="14002" roleTypeId="Customer"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="Company" roleTypeId="Company"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="10002" roleTypeId="FieldRep"/>

        Show
        Chris Howe added a comment - Keep in mind PartyRelationship.patch is specifically a change to the data layer. My comments will be about the types of logic layers that are possible with this data layer that are not possible or as Daniel put it, clunky with the current party relationship data layer. Subsequent patches will be to mirror the functionality of the current relatinoship system while allowing for more complex relationships. The relationship where someone is an agent Disclaimer: These descriptions may not be 100% accurate but are close enough to get the idea The current system employer/employee description <PartyRelationship partyIdFrom="10000" roleTypeIdFrom="Employee" partyIdTo="12000" roleTypeIdTo="Employer"/> or <PartyRelationship partyIdFrom="12000" roleTypeIdFrom="Employer" partyIdTo="10000" roleTypeIdto="Employee"/> Both are valid. Both are even possible inputting data styles as suggested by the applications. Two result sets must be obtained. Is also clunky if this employee ends their employment for a period and then comes back to work. The patched employer/employee description. <PartyRelationship partyRelationshpId="20000"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="Employee"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="12000" roleTypeId="Employer"/> Only one result set needs to be obtained. In the employee/employer relationship the direction partyIdTo/partyIdFrom is not necessary.. The direction adds no additional information about the relationship. I can't think of any relationships where the direction adds information about the relationship. However, I assume there must be at least one kind of relationship where the direction adds information otherwise I don't think the direction would even exist in the project. Now let me show a relationship where the patched approach is a BIG improvement over the current system and actually exists in our production environment as it is in the current system. 10000 is an employee of 12000 10000 is an agent of 12000 (can act on their behalf) 10000 is a buyer for 12000 (can purchase on their behalf) Patched System <PartyRelationship partyRelationshpId="20000"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="Employee"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="12000" roleTypeId="Employer"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="Agent"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="Buyer"/> Curent System <PartyRelationship roleTypeIdFrom ="Employer" partyIdFrom =12000 roleTypeIdTo ="Employee" partyIdTo =10000/> <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Agent" partyIdTo =10000/> <PartyRelationship roleTypeIdFrom =" NA " partyIdFrom =12000 roleTypeIdTo ="Buyer" partyIdTo =10000/> or <PartyRelationship roleTypeIdFrom ="Employer" partyIdFrom =12000 roleTypeIdTo ="Employee" partyIdTo =10000/> <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Agent" partyIdTo =10000/> <PartyRelationship roleTypeIdFrom ="Buyer" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/> or <PartyRelationship roleTypeIdFrom ="Employer" partyIdFrom =12000 roleTypeIdTo ="Employee" partyIdTo =10000/> <PartyRelationship roleTypeIdFrom ="Agent" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/> <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Buyer" partyIdTo =10000/> or <PartyRelationship roleTypeIdFrom ="Employer" partyIdFrom =12000 roleTypeIdTo ="Employee" partyIdTo =10000/> <PartyRelationship roleTypeIdFrom ="Agent" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/> <PartyRelationship roleTypeIdFrom ="Buyer" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/> or <PartyRelationship roleTypeIdFrom ="Employee" partyIdFrom =10000 roleTypeIdTo ="Employer" partyIdTo =12000/> <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Agent" partyIdTo =10000/> <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Buyer" partyIdTo =10000/> or <PartyRelationship roleTypeIdFrom ="Employee" partyIdFrom =10000 roleTypeIdTo ="Employer" partyIdTo =12000/> <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Agent" partyIdTo =10000/> <PartyRelationship roleTypeIdFrom ="Buyer" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/> or <PartyRelationship roleTypeIdFrom ="Employee" partyIdFrom =10000 roleTypeIdTo ="Employer" partyIdTo =12000/> <PartyRelationship roleTypeIdFrom ="Agent" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/> <PartyRelationship roleTypeIdFrom ="Principal" partyIdFrom =12000 roleTypeIdTo ="Buyer" partyIdTo =10000/> or <PartyRelationship roleTypeIdFrom ="Employee" partyIdFrom =10000 roleTypeIdTo ="Employer" partyIdTo =12000/> <PartyRelationship roleTypeIdFrom ="Agent" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/> <PartyRelationship roleTypeIdFrom ="Buyer" partyIdFrom =10000 roleTypeIdTo ="Principal" partyIdTo =12000/> Our actual current need for this is to describe our slightly complex commission structure which is ternary The relationship is between the customer and company and sometimes the sales rep gets paid on sales and sometimes that get paid on receivables. or a mixture of the two. So, we need <PartyRelationship partyRelationshipId="20000" <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="InsideRep"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="14002" roleTypeId="Customer"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="Company" roleTypeId="Company"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="10002" roleTypeId="FieldRep"/>
        Hide
        David E. Jones added a comment -

        My first thought on this new "PartyRelationship" structure is that it pretty much accomplishes the same thing as a PartyGroup type Party, except that it is a bit simplified.

        On a business story level, what is it you are trying to accomplish with this?

        Show
        David E. Jones added a comment - My first thought on this new "PartyRelationship" structure is that it pretty much accomplishes the same thing as a PartyGroup type Party, except that it is a bit simplified. On a business story level, what is it you are trying to accomplish with this?
        Hide
        Chris Howe added a comment -

        We have two actually.

        The first is a complex commision structure where there is an insideRep, fieldRep and the turnover associated with these fields complicated by commisions earned by orders generated as well as on receivables converted and bonus based on account growth. This can probably be handled in other ways but the multitude of journal entries and correcting joural entries required to do it is less than desirable. The commission structure being based around this multiparty relationship makes this approach the simplest and less prone to errors.

        Our second is that our company deals with continuity of care in the medical field with as many 10 parties being intertwined in role and various levels of information needs/allowances. There is a primary relationship (the provider and end user customer) and then the ancilary parties. Creating the parties alone give the 2^n (n= number of party/role combinations) number of searches that need to be done to obtain a complete data set.

        Show
        Chris Howe added a comment - We have two actually. The first is a complex commision structure where there is an insideRep, fieldRep and the turnover associated with these fields complicated by commisions earned by orders generated as well as on receivables converted and bonus based on account growth. This can probably be handled in other ways but the multitude of journal entries and correcting joural entries required to do it is less than desirable. The commission structure being based around this multiparty relationship makes this approach the simplest and less prone to errors. Our second is that our company deals with continuity of care in the medical field with as many 10 parties being intertwined in role and various levels of information needs/allowances. There is a primary relationship (the provider and end user customer) and then the ancilary parties. Creating the parties alone give the 2^n (n= number of party/role combinations) number of searches that need to be done to obtain a complete data set.
        Hide
        Chris Howe added a comment -

        David,

        I was going to work on implementing this over the weekend. Do you have any concerns on this data model before I get started?

        My implementation will
        1) replace all CRUD operations on the PartyRelationship entities so that the same data comes back as now.
        2) Redesign the create and update screens so they're straight forwarrd for utilizing this implementation.

        Also, I made notes in the patch for the entity definitions. If you could comment on about those notes, I would appreciate it. Otherwise I'll aim for mirroring current functionality as is.

        Show
        Chris Howe added a comment - David, I was going to work on implementing this over the weekend. Do you have any concerns on this data model before I get started? My implementation will 1) replace all CRUD operations on the PartyRelationship entities so that the same data comes back as now. 2) Redesign the create and update screens so they're straight forwarrd for utilizing this implementation. Also, I made notes in the patch for the entity definitions. If you could comment on about those notes, I would appreciate it. Otherwise I'll aim for mirroring current functionality as is.
        Hide
        David E. Jones added a comment -

        If you're going to work on this, do it in addition to the existing PartyRelationship structure, not instead of it.

        As for your concerns about n! (not 2^n) combinations, that is what a PartyGroup with 1 relationship to each member of the group is for. You wouldn't relate each group member to each other group member, that would a pain!

        Show
        David E. Jones added a comment - If you're going to work on this, do it in addition to the existing PartyRelationship structure, not instead of it. As for your concerns about n! (not 2^n) combinations, that is what a PartyGroup with 1 relationship to each member of the group is for. You wouldn't relate each group member to each other group member, that would a pain!
        Hide
        Si Chen added a comment -

        I think David is right--what you are talking about really is just PartyGroup membership.

        There are some other subtleties, most importantly for us the PartyRelationship.securityGroupId and from-thru date ranges, which the current PartyRelationship data model supports but your patch does not.

        This is a pretty fundamental change that you're proposing, and I think we would need to spend some time discussing it first.

        Show
        Si Chen added a comment - I think David is right--what you are talking about really is just PartyGroup membership. There are some other subtleties, most importantly for us the PartyRelationship.securityGroupId and from-thru date ranges, which the current PartyRelationship data model supports but your patch does not. This is a pretty fundamental change that you're proposing, and I think we would need to spend some time discussing it first.
        Hide
        Chris Howe added a comment -

        Of no importance: I think it is 2^n. See the example of describing the three relationships above (employer/employee, principal/agent, principal/buyer) creates a possible 8 (2^3) result sets, where as n! would only give 6 (3! = 3x2x1).

        If what I'm talking about is PartyGroup membership, then aren't all relationships PartyGroup memberships? (I'm really asking this, I'm not being rhetorical.) If that's the case, what is the benefit of PartyRelationship at all?

        PartyRelationship.securityGroupId is still there. I have a comment about it potentially being dangerous depending on how it's implemented (I admit I haven't looked into how it is implemented), but I don't have any intention on addressing changes to how it's currently used with any work I'll do.
        *side question* SecurityGroups are UserLogin based, yet this is Party based. Seems awkward, please feel free to answer with RTFA or in this case RTFC(ode)

        fromDate and thruDate were moved to the PartyRelationshipRole as people can enter, leave and enter again a relationship.

        The begining of a relationship automatically receives a creationDate from the entity engine. The thruDate is easily extrapolated by the latest PartyRelationshipRole.thruDate provided one is not null. In addition the PartyRelationship.statusId field should give quick extrapolation on whether there remains a thruDate one that is null.

        Show
        Chris Howe added a comment - Of no importance: I think it is 2^n. See the example of describing the three relationships above (employer/employee, principal/agent, principal/buyer) creates a possible 8 (2^3) result sets, where as n! would only give 6 (3! = 3x2x1). If what I'm talking about is PartyGroup membership, then aren't all relationships PartyGroup memberships? (I'm really asking this, I'm not being rhetorical.) If that's the case, what is the benefit of PartyRelationship at all? PartyRelationship.securityGroupId is still there. I have a comment about it potentially being dangerous depending on how it's implemented (I admit I haven't looked into how it is implemented), but I don't have any intention on addressing changes to how it's currently used with any work I'll do. * side question * SecurityGroups are UserLogin based, yet this is Party based. Seems awkward, please feel free to answer with RTFA or in this case RTFC(ode) fromDate and thruDate were moved to the PartyRelationshipRole as people can enter, leave and enter again a relationship. The begining of a relationship automatically receives a creationDate from the entity engine. The thruDate is easily extrapolated by the latest PartyRelationshipRole.thruDate provided one is not null. In addition the PartyRelationship.statusId field should give quick extrapolation on whether there remains a thruDate one that is null.
        Hide
        David E. Jones added a comment -

        Chris: do you by change have a copy of "The Data Model Resource Book, Revised Edition, Volume 1"? That might be the best source, and most effective for everyone, of information about these structures.

        Because of the way the Party is used, being a Person or a Group, a PartyRelationship can directly relate "Persons", or they can relate various Persons to a Group, or Groups to other Groups, and so on.

        Show
        David E. Jones added a comment - Chris: do you by change have a copy of "The Data Model Resource Book, Revised Edition, Volume 1"? That might be the best source, and most effective for everyone, of information about these structures. Because of the way the Party is used, being a Person or a Group, a PartyRelationship can directly relate "Persons", or they can relate various Persons to a Group, or Groups to other Groups, and so on.
        Hide
        Daniel Kunkel added a comment -

        In giving this some more thought I'm starting to like your idea, largely because I think it's a great way of structuring the relationship more simply, or in other words, it handles the bidirectional issue beautifully.

        I'm still confused on how it would handle multiple parties as currently structured... you said:

        Our actual current need for this is to describe our slightly complex commission structure which is ternary
        The relationship is between the customer and company and sometimes the sales rep gets paid on sales and sometimes that get paid on receivables. or a mixture of the two. So, we need
        <PartyRelationship partyRelationshipId="20000"

        <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="InsideRep"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="14002" roleTypeId="Customer"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="Company" roleTypeId="Company"/>
        <PartyRelationshipRole partyRelationshipId="20000" partyId="10002" roleTypeId="FieldRep"/>


        I think you intended
        10000 is inside rep to Company Company
        14002 is customer to Company Company
        10002 is a field rep of Company
        10000 is inside rep to customer 14002
        14002 is customer to 10002 Fieldrep

        But, It seems like an unintential relationship is also being created:

        10000 is inside rep to 10002 Fieldrep

        Agreed, that's a little non-sensical, and most of the unintential relationships would be non-sensical. Say someone tried to add another customer, 14003, then the system would indicate14002 is a customer of 14003 and 14003 is a customer of 14002.

        To solve this, I could imagine setting one party or party group as the hub and all relationships only pertain to that party, but then we loose neat bidirectional solution.

        I could also imagine requiring that only two parties be mentioned might work well.

        Thanks

        Show
        Daniel Kunkel added a comment - In giving this some more thought I'm starting to like your idea, largely because I think it's a great way of structuring the relationship more simply, or in other words, it handles the bidirectional issue beautifully. I'm still confused on how it would handle multiple parties as currently structured... you said: Our actual current need for this is to describe our slightly complex commission structure which is ternary The relationship is between the customer and company and sometimes the sales rep gets paid on sales and sometimes that get paid on receivables. or a mixture of the two. So, we need <PartyRelationship partyRelationshipId="20000" <PartyRelationshipRole partyRelationshipId="20000" partyId="10000" roleTypeId="InsideRep"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="14002" roleTypeId="Customer"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="Company" roleTypeId="Company"/> <PartyRelationshipRole partyRelationshipId="20000" partyId="10002" roleTypeId="FieldRep"/> — I think you intended 10000 is inside rep to Company Company 14002 is customer to Company Company 10002 is a field rep of Company 10000 is inside rep to customer 14002 14002 is customer to 10002 Fieldrep But, It seems like an unintential relationship is also being created: 10000 is inside rep to 10002 Fieldrep Agreed, that's a little non-sensical, and most of the unintential relationships would be non-sensical. Say someone tried to add another customer, 14003, then the system would indicate14002 is a customer of 14003 and 14003 is a customer of 14002. To solve this, I could imagine setting one party or party group as the hub and all relationships only pertain to that party, but then we loose neat bidirectional solution. I could also imagine requiring that only two parties be mentioned might work well. Thanks
        Hide
        Scott Gray added a comment -

        What's wrong with just having an eeca creating the reciprocal relationship? You'd need to add a few more relationshipTypeIds like Employer, Principal etc. then its just a matter of:

        New relationship:
        <PartyRelationship partyIdFrom="JSmith" partyIdTo="Company" roleTypeIdFrom="EMPLOYEE" roleTypeIdTo="EMPLOYER" partyRelationshipTypeId="EMPLOYMENT"/>

        upon being saved automatically creates:
        <PartyRelationship partyIdFrom="Company" partyIdTo="JSmith" roleTypeIdFrom="EMPLOYER" roleTypeIdTo="EMPLOYEE" partyRelationshipTypeId="EMPLOYMENT"/>

        then no matter how you search the relationship is there...

        Show
        Scott Gray added a comment - What's wrong with just having an eeca creating the reciprocal relationship? You'd need to add a few more relationshipTypeIds like Employer, Principal etc. then its just a matter of: New relationship: <PartyRelationship partyIdFrom="JSmith" partyIdTo="Company" roleTypeIdFrom="EMPLOYEE" roleTypeIdTo="EMPLOYER" partyRelationshipTypeId="EMPLOYMENT"/> upon being saved automatically creates: <PartyRelationship partyIdFrom="Company" partyIdTo="JSmith" roleTypeIdFrom="EMPLOYER" roleTypeIdTo="EMPLOYEE" partyRelationshipTypeId="EMPLOYMENT"/> then no matter how you search the relationship is there...
        Hide
        David E. Jones added a comment -

        Why woud we need a symmetrical relationship anyway? We already have a convention that determines the direction of relationship to use...

        Show
        David E. Jones added a comment - Why woud we need a symmetrical relationship anyway? We already have a convention that determines the direction of relationship to use...
        Hide
        Scott Gray added a comment -

        Good point, I think I'll go back to what I was doing...

        Show
        Scott Gray added a comment - Good point, I think I'll go back to what I was doing...
        Hide
        Chris Howe added a comment -

        Daniel,
        The cartesian product here is only non-sensical if you leave out the partyRelationshipId and the context that it provides. If you applied the same relationship structure to say, OrderRoles, but left out the context of orderId, you'd have as much quality information as you do saying that 10000 is inside rep to 10002 Fieldrep.

        In your customer to customer example, in what context would you be modeling a relationship that had two customers? Each of the role types, once used, have specific connotations that should be defined in a data dictionary. The partyRelationshipTypeId specified in the related PartyRelationship entity gives the basis of the data dictionary.
        The partyRelationshipTypeId also is providing the idea of "hub". In the example we're discussing, we're modeling a relationship of type "SALES_RELATIONSHIP". The idea of a sales relationship is a bit more complex than the idea of a B2C customer relationship. B2C customer relationship is two parties with each party in one role. All other roles are specifically to events. (ie the person manning the register is not the checkout person for the customer/company relationship, but rather the checkout person for an order). In a sales relationship (as exampled here) there are several people acting in potentially several roles. The roles need to be defined on the relationship level because a field rep is responsible for the customer - company relationship even when he's not involved in the transaction (ie a field rep receives a commission and is responsible for the followup if the customer places the order with the insideRep).

        David,
        I'm not seeing a convention in the current system. If there is one it seems the EditPartyRelationship screen requires the user to know the convention.
        Alos, if you could clarify, I don't think it's been explained what direction means outside of being an arbitrary designation.

        re: my PartyGroup question earlier. I had a brain lapse on what a PartyGroup was. I apologize for misspeaking there.
        A party group is an organized body and is subset of Party, it is not appropriate to describe a sales relationship or continuity of care relationship that I described in my business story as a PartyGroup. If you were to make the sales relationship a group, you would need to make the group a party to the sales transaction, which the group isn't a party of the transaction, only select members in select roles are. The participants in the business story don't act as a group. You can infer that a relationship exists from a membership in a party group, however in the business story, these are explicit relationships, not infered ones.
        As far as the application logic goes, you can look at it in this light.
        The "Party Relationship Roles" provide a set of default values for the "Order Roles". The "Order Roles" provide some default values for "Invoice Roles". (This is a bit different than the busines logic that is employed in OFBiz as the creation of Invoice Roles is not selective of the Order Roles, it currently just copies them all).

        Show
        Chris Howe added a comment - Daniel, The cartesian product here is only non-sensical if you leave out the partyRelationshipId and the context that it provides. If you applied the same relationship structure to say, OrderRoles, but left out the context of orderId, you'd have as much quality information as you do saying that 10000 is inside rep to 10002 Fieldrep. In your customer to customer example, in what context would you be modeling a relationship that had two customers? Each of the role types, once used, have specific connotations that should be defined in a data dictionary. The partyRelationshipTypeId specified in the related PartyRelationship entity gives the basis of the data dictionary. The partyRelationshipTypeId also is providing the idea of "hub". In the example we're discussing, we're modeling a relationship of type "SALES_RELATIONSHIP". The idea of a sales relationship is a bit more complex than the idea of a B2C customer relationship. B2C customer relationship is two parties with each party in one role. All other roles are specifically to events. (ie the person manning the register is not the checkout person for the customer/company relationship, but rather the checkout person for an order). In a sales relationship (as exampled here) there are several people acting in potentially several roles. The roles need to be defined on the relationship level because a field rep is responsible for the customer - company relationship even when he's not involved in the transaction (ie a field rep receives a commission and is responsible for the followup if the customer places the order with the insideRep). David, I'm not seeing a convention in the current system. If there is one it seems the EditPartyRelationship screen requires the user to know the convention. Alos, if you could clarify, I don't think it's been explained what direction means outside of being an arbitrary designation. re: my PartyGroup question earlier. I had a brain lapse on what a PartyGroup was. I apologize for misspeaking there. A party group is an organized body and is subset of Party, it is not appropriate to describe a sales relationship or continuity of care relationship that I described in my business story as a PartyGroup. If you were to make the sales relationship a group, you would need to make the group a party to the sales transaction, which the group isn't a party of the transaction, only select members in select roles are. The participants in the business story don't act as a group. You can infer that a relationship exists from a membership in a party group, however in the business story, these are explicit relationships, not infered ones. As far as the application logic goes, you can look at it in this light. The "Party Relationship Roles" provide a set of default values for the "Order Roles". The "Order Roles" provide some default values for "Invoice Roles". (This is a bit different than the busines logic that is employed in OFBiz as the creation of Invoice Roles is not selective of the Order Roles, it currently just copies them all).
        Hide
        Daniel Kunkel added a comment -

        I'm liking this system, with the exception of the unintended relationships. I see it as being FAR more clear and useful than the existing relationship scheme, but it's dangerous, especially as more entries are made in each cluster and without additional safeguards.

        I see having a problem that WILL turn and bite businesses, and it stems from the issue that FOR EACH additional entry you add n-1 bidirectional relationships.

        I'll try to expand my problem senario to show the potential for trouble, by adding an order clerk into the mix in a company where the customer facing order clerks are separate from the internal order clerks.

        All is fine when a user looks at the set of relationships, as the customer and company are clearly the focus of the defined relationships with the exception that the customer order clerk is now defined for each sales representive.

        It won't take but for someone to try to fix the error before internal sales clerks messages could be sent to the customer.

        Duplication of Relationships

        Another lesser issue is the duplication of relationships. This in itself doesn't pose a problem until one wants to make a change or correct a mistake. In a large company the effort to review and revise the complexities of hundreds of multi-party entries to find and fix a mistaken relationships could become untenable.

        In short, I like the idea. It is much more useful to me than

        of the Party with ID ____ in the role of ______ is a ______ of the current party in the role of _____

        which confuses me and my users, but I do see the untintentional relationships being a BIG problem unless safeguards can be used.

        Thanks

        Show
        Daniel Kunkel added a comment - I'm liking this system, with the exception of the unintended relationships. I see it as being FAR more clear and useful than the existing relationship scheme, but it's dangerous, especially as more entries are made in each cluster and without additional safeguards. I see having a problem that WILL turn and bite businesses, and it stems from the issue that FOR EACH additional entry you add n-1 bidirectional relationships. I'll try to expand my problem senario to show the potential for trouble, by adding an order clerk into the mix in a company where the customer facing order clerks are separate from the internal order clerks. All is fine when a user looks at the set of relationships, as the customer and company are clearly the focus of the defined relationships with the exception that the customer order clerk is now defined for each sales representive. It won't take but for someone to try to fix the error before internal sales clerks messages could be sent to the customer. — Duplication of Relationships Another lesser issue is the duplication of relationships. This in itself doesn't pose a problem until one wants to make a change or correct a mistake. In a large company the effort to review and revise the complexities of hundreds of multi-party entries to find and fix a mistaken relationships could become untenable. — In short, I like the idea. It is much more useful to me than of the Party with ID ____ in the role of ______ is a ______ of the current party in the role of _____ which confuses me and my users, but I do see the untintentional relationships being a BIG problem unless safeguards can be used. Thanks
        Hide
        Chris Howe added a comment -

        If in your scenario an "order clerk" is the person who takes a specific order, then they should not be associated with this partyRelationshipId. They should be an entry in the OrderRole entity related to the orderId of the order they entered, not an entry in PartyRelationshipRole.

        In the traditional sense, an order clerk is an attribute of an order, not an attribute of the relationship.

        Unless a customer is assigned an order clerk and should try to place all of their orders with that order clerk, then there should be no PartyRelationship between them.

        Show
        Chris Howe added a comment - If in your scenario an "order clerk" is the person who takes a specific order, then they should not be associated with this partyRelationshipId. They should be an entry in the OrderRole entity related to the orderId of the order they entered, not an entry in PartyRelationshipRole. In the traditional sense, an order clerk is an attribute of an order, not an attribute of the relationship. Unless a customer is assigned an order clerk and should try to place all of their orders with that order clerk, then there should be no PartyRelationship between them.
        Hide
        Chris Howe added a comment -

        Back to the PartyGroup confussion.

        I misspoke again

        The only way to define Party Group membership is through PartyRelationship. So we're talking about the same thing. Except that you're suggesting assigning this partyRelationshipId to a PartyGroup as an INFORMAL_GROUP type. I just find it unncessary for this relationship to have a partyId of its own. Implementing it where your suggesting ends up being the same implementation point as I've suggested, except I'd like to eliminate the need for relationship direction, I guess would be a fair summary.

        Show
        Chris Howe added a comment - Back to the PartyGroup confussion. I misspoke again The only way to define Party Group membership is through PartyRelationship. So we're talking about the same thing. Except that you're suggesting assigning this partyRelationshipId to a PartyGroup as an INFORMAL_GROUP type. I just find it unncessary for this relationship to have a partyId of its own. Implementing it where your suggesting ends up being the same implementation point as I've suggested, except I'd like to eliminate the need for relationship direction, I guess would be a fair summary.
        Hide
        Daniel Kunkel added a comment -

        Chris

        I'm sorry my example wasn't adequate.

        I like the simplicity and power of this system, and that it doesn't directionality.

        I don't like that non intentional and duplicate relationships can be created as more relationships are combined. I see this as therefore being a dangerous feature to adopt.

        Any thoughts?

        Show
        Daniel Kunkel added a comment - Chris I'm sorry my example wasn't adequate. I like the simplicity and power of this system, and that it doesn't directionality. I don't like that non intentional and duplicate relationships can be created as more relationships are combined. I see this as therefore being a dangerous feature to adopt. Any thoughts?
        Hide
        Chris Howe added a comment -

        LOL... I keep rethinking this...

        For my business story, I can accomplish it with what is in the current system by using the Party Group and creating a view-entity of PartyRelationship to PartyRelationship with complex alias that effectively swap the direction so that you end up as a view what Scot Grey suggested with ECA. The question now remains, does direction provide any information about the relationship to warrant the confusion?

        Show
        Chris Howe added a comment - LOL... I keep rethinking this... For my business story, I can accomplish it with what is in the current system by using the Party Group and creating a view-entity of PartyRelationship to PartyRelationship with complex alias that effectively swap the direction so that you end up as a view what Scot Grey suggested with ECA. The question now remains, does direction provide any information about the relationship to warrant the confusion?
        Hide
        Chris Howe added a comment -

        Daniel,
        Perhaps I'm not thinking hard enough, but I can't come up with a scenario where you'd have unintentional or duplicate relationships.
        If you have an unintential relationship then it wasn't modeled correctly. Either it should have been two different PartyRelationships with different partyRelationshipTypes or it should have been one PartyRelationship and one OrderRole, ContentRole, ProductRole, etc

        Show
        Chris Howe added a comment - Daniel, Perhaps I'm not thinking hard enough, but I can't come up with a scenario where you'd have unintentional or duplicate relationships. If you have an unintential relationship then it wasn't modeled correctly. Either it should have been two different PartyRelationships with different partyRelationshipTypes or it should have been one PartyRelationship and one OrderRole, ContentRole, ProductRole, etc
        Hide
        Chris Howe added a comment -

        file: necessaryChangeLog.txt

        After really thinking it over, I've concluded to myself that a polynary relationship or a binary relationship where one party acts in multiple, specific roles or a combination thereof is in fact something different from a party group. While it is possible to hack OFBiz for my current business needs, I don't feel that will always be the case as my users become more and more creative in their uses of OFBiz as an ERP system and will only cause more dificult integrations in the future. Additionaly the complexity that is shown throughout the code and the use of an unknown, inconsistantly followed and apparently arbitrary convention warrants getting rid of the direction associated with relationships. However, there will be a field present to allow for this constraint if necessary (PartyRelationshipRole.directionId) and will be used in the applications that are currently calling for it in specific instances (ie TaxAuthorityServices.getTaxAdjustments) These services will most likely drop the need for direction, but I feel that is outside the scope of this proposed improvement as it requires business logic consideration.

        Outlined is the result of files and sections that would need to be looked at closer as to how they would need to interact with the proposed change. This was compiled by doing a search of the Applications directory for "PartyRelationship" (case insensitve) and ignoring results of PartyRelationshipType by hand. Each of these TODOs need to look a step lower in the hierarchy (and then again lower if necessary) to ensure a change made won't effect their functionality. If there are any that someone feels I missed, please let me know.

        Show
        Chris Howe added a comment - file: necessaryChangeLog.txt After really thinking it over, I've concluded to myself that a polynary relationship or a binary relationship where one party acts in multiple, specific roles or a combination thereof is in fact something different from a party group. While it is possible to hack OFBiz for my current business needs, I don't feel that will always be the case as my users become more and more creative in their uses of OFBiz as an ERP system and will only cause more dificult integrations in the future. Additionaly the complexity that is shown throughout the code and the use of an unknown, inconsistantly followed and apparently arbitrary convention warrants getting rid of the direction associated with relationships. However, there will be a field present to allow for this constraint if necessary (PartyRelationshipRole.directionId) and will be used in the applications that are currently calling for it in specific instances (ie TaxAuthorityServices.getTaxAdjustments) These services will most likely drop the need for direction, but I feel that is outside the scope of this proposed improvement as it requires business logic consideration. Outlined is the result of files and sections that would need to be looked at closer as to how they would need to interact with the proposed change. This was compiled by doing a search of the Applications directory for "PartyRelationship" (case insensitve) and ignoring results of PartyRelationshipType by hand. Each of these TODOs need to look a step lower in the hierarchy (and then again lower if necessary) to ensure a change made won't effect their functionality. If there are any that someone feels I missed, please let me know.
        Hide
        Chris Howe added a comment -

        [[ Old comment, sent by email on Fri, 11 Aug 2006 19:07:12 -0700 (PDT) ]]

        I'm replying to the mailing list instead of commenting
        on the JIRA as it addresses issues much broader than
        the scope of the JIRA and I know you're busy and I
        would like feedback from others on the list as well.

        Chris: do you by change have a copy of "The Data Model
        Resource Book, Revised Edition, Volume 1"? That might
        be the best source, and most effective for everyone,
        of information about these structures.

        I've been meaning to check it out. However I think
        the questions I'm raising here and the questions I've
        raised in the past regarding the data layer are
        relevent. If the structure that is in place for these
        things is supported by The Data Model Resource Book,
        then I think we need to recognize that The Data Model
        Resource Book is a good starting point, but not quite
        generic enough for an international, open source,
        community driven, ERP project.

        "ERP" is supposed to conceptualize that data be stored
        in a manner that allows the enterprise to utilize the
        data without consideration of the initial purpose of
        the data's input.

        So, if a PartyRelationship can be described just as
        effectively using the PartyGroup and PartyGroupRole
        (as it can be described as a PartyGroup of two parties
        who each act in a single role), why would you want to
        describe it in a manner that limits the data's
        utilization to the initial purpose of the input?

        — "David E. Jones (JIRA)" <jira@apache.org> wrote:

        http://issues.apache.org/jira/browse/OFBIZ-149?page=comments#action_12427669
        http://mail-archives.apache.org/mod_mbox/incubator-ofbiz-dev/200608.mbox/%3c20060809155147.18528.qmail@web80615.mail.yahoo.com%3e
        http://issues.apache.org/jira/secure/Administrators.jspa

        Show
        Chris Howe added a comment - [[ Old comment, sent by email on Fri, 11 Aug 2006 19:07:12 -0700 (PDT) ]] I'm replying to the mailing list instead of commenting on the JIRA as it addresses issues much broader than the scope of the JIRA and I know you're busy and I would like feedback from others on the list as well. Chris: do you by change have a copy of "The Data Model Resource Book, Revised Edition, Volume 1"? That might be the best source, and most effective for everyone, of information about these structures. I've been meaning to check it out. However I think the questions I'm raising here and the questions I've raised in the past regarding the data layer are relevent. If the structure that is in place for these things is supported by The Data Model Resource Book, then I think we need to recognize that The Data Model Resource Book is a good starting point, but not quite generic enough for an international, open source, community driven, ERP project. "ERP" is supposed to conceptualize that data be stored in a manner that allows the enterprise to utilize the data without consideration of the initial purpose of the data's input. So, if a PartyRelationship can be described just as effectively using the PartyGroup and PartyGroupRole (as it can be described as a PartyGroup of two parties who each act in a single role), why would you want to describe it in a manner that limits the data's utilization to the initial purpose of the input? — "David E. Jones (JIRA)" <jira@apache.org> wrote: http://issues.apache.org/jira/browse/OFBIZ-149?page=comments#action_12427669 http://mail-archives.apache.org/mod_mbox/incubator-ofbiz-dev/200608.mbox/%3c20060809155147.18528.qmail@web80615.mail.yahoo.com%3e http://issues.apache.org/jira/secure/Administrators.jspa
        Hide
        Marco Risaliti added a comment -

        Does this issue can be closed ?

        Thanks
        Marco

        Show
        Marco Risaliti added a comment - Does this issue can be closed ? Thanks Marco
        Hide
        Chris Howe added a comment -

        No. I have this working quite nicely in our company's installation, I just need to find the time to seperate it into it's own patch and add the constraints that will allow constraining the number of times a roleTypeId can be associated.

        Show
        Chris Howe added a comment - No. I have this working quite nicely in our company's installation, I just need to find the time to seperate it into it's own patch and add the constraints that will allow constraining the number of times a roleTypeId can be associated.
        Hide
        BJ Freeman added a comment -

        there has been a lot of changes since this issue.
        can this be closed and use
        https://issues.apache.org/jira/browse/OFBIZ-3851

        Show
        BJ Freeman added a comment - there has been a lot of changes since this issue. can this be closed and use https://issues.apache.org/jira/browse/OFBIZ-3851

          People

          • Assignee:
            David E. Jones
            Reporter:
            Chris Howe
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development