PSOhub OData Data Model: Table Relationships & Cardinality
Understand how PSOhub tables connect so you can join them correctly in Power BI, Excel, and other reporting tools.
Published: 14 July 2026
Audience
- Admin
Objective
Understand how your PSOhub data is structured and connected across modules, so you can join tables correctly and build accurate reports. This article covers the relationships and cardinality between tables. For field-level definitions of any table, see the PSOhub OData Reference.
Introduction
PSOhub's OData feed gives you direct access to your organization's data for advanced reporting and analysis with tools like Power BI and Excel.
To build meaningful reports, it helps to understand how the tables connect. Most of the model hangs off a small number of central tables: Projects sit at the center of delivery and financials, UserAccounts represent your people, Companies represent your customers, and ContractLines carry the budget and billing detail. Almost every other table links back to one of these.
This article walks through each module, shows the key relationships, and links to the full field definitions in the Reference.
How to Read This Article
Each module below has a short introduction and a relationship table. The relationship table lists the join keys you use to connect data across tables:
- Field Name — the field on the current table that holds the link
- Related Table — the table it points to (linked to its full field definitions in the Reference)
- Related Field — the field on the related table (almost always its ID)
- Cardinality — how many records relate to how many
Cardinality tells you how records match up, which matters when joining so you don't accidentally duplicate or lose rows:
- 1:1 — one record matches exactly one record
- 1:* — one record matches many (e.g. one project has many time entries)
- *:1 — many records match one (e.g. many time entries belong to one project)
- 0..1 — the link is optional; it may be empty
💡 Tip: When joining a 1:many relationship in Power BI, aggregate the "many" side (for example, sum hours per project) before combining, to avoid inflating totals.
What changed in the Resource Management model
The Resource Management tables have been redesigned. The previous model stored planning and capacity as annual and monthly aggregate rows (one row per year with twelve monthly columns). The new model stores this data at a daily and monthly grain — one row per resource per day or per month — which is far easier to work with in reporting tools.
If you built reports on the previous Calculation or Workload tables, those reports will need to be rebuilt against the new tables described in the Resource Management section below.
Smart Quotes
The Quotes table holds each formal offer sent to a client. A quote is tied to the project it will create, and to the sales rep, contract total, and other supporting records.
Quotes
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| Quote_Project | Projects | ID | 1:1 |
| Quote_AccountSalesRep | UserAccounts | ID | 0..1 |
| ContractTotal_OneEngagement | ContractTotals | ID | 0..1 |
| Calculation_OneEngagement | *Calculations (deprecated) | ID | 0..1 |
| TaskBoard_OneEngagement | Plans | ID | 0..1 |
| OneEngagement_BusinessUnit | BusinessUnits | ID | 0..1 |
| OneEngagement_ProjectType | ProjectTypes | ID | 0..1 |
Project Management
Projects are the central engagement record. Each project links to its customer, project manager, contract structure, and budget.
Projects
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| ProjectManager | UserAccounts | ID | 0..1 |
| Customer | Companies | ID | 1 |
| ProjectType | ProjectTypes | ID | 0..1 |
| OneEngagement_BusinessUnit | BusinessUnits | ID | 1 |
| OneEngagement_ContractTemplate | ContractTemplates | ID | 0..1 |
| OneEngagement_ProjectStage | ProjectStages | ID | 0..1 |
| OneEngagement_Contact_MainContact | Contacts | ID | 0..1 |
| OneEngagement_MultiCurrency | Currencies | ID | 0..1 |
| ContractTotal_OneEngagement | ContractTotals | ID | 0..1 |
ContractTotals
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| ContractTotal_OneEngagement | Projects | ID | 1:1 |
| ContractTotal_ContractTemplate | ContractTemplates | ID | *:1 |
| owner | UserAccounts | ID | 1:1 |
| changedBy | UserAccounts | ID | 1:1 |
ContractGroups and ContractLines
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| ContractGroup_OneEngagement | Projects | ID | 1:1 |
| SubTotalGroup_ContractGroup | SubTotalGroups | ID | 0..1 |
| Project | Projects | ID | 1 |
| RecurringInvoiceSchema | Recurrings | ID | 0..1 |
| ContractGroupLine_ContractGroup | ContractGroups | ID | 1 |
| ContractGroupLine_TaxCategory | TaxCategories | ID | 0..1 |
| ContractGroupLine_GLAccount | GLAccounts | ID | 0..1 |
| ContractGroupLine_TransactionClasses | TransactionClasses | ID | 0..1 |
| BudgetGridLine_ContractGroupLine | BudgetGridLines | ID | 0..1 |
| ContractGroupLine_Product | Products | ID | 0..1 |
| ContractGroupLine_ProductPriceList | ProductPriceLists | ID | 0..1 |
ContractTemplates
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| ContractTotal_ContractTemplate | ContractTotals | ID | 0..1 |
| owner | UserAccounts | ID | 0..1 |
| changedBy | UserAccounts | ID | 0..1 |
| ContractGroupTemplate_ContractTemplate | ContractTemplates | ID | *:1 |
| ContractLineTemplate_ContractGroupTemplate | ContractGroupTemplates | ID | *:1 |
| ContractLineTemplate_TaxCategory | TaxCategories | ID | 0..1 |
BudgetGridLines
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| BudgetGridLine_ContractGroupLine | ContractLines | ID | *:1 |
| BudgetGridLineResource_BudgetGridLine | BudgetGridLines | ID | *:1 |
| BudgetGridLineResource_ProjectMember | ProjectMembers | ID | 0..1 |
| BudgetGridLineResource_ProjectRole_ForFiltering | ProjectRoles | ID | 0..1 |
Work Management
Plans structure the work to be delivered. A plan belongs to a project or quote and contains task lists, which contain tasks.
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| TaskProgress_TaskBoardProgress | PlanStages | ID | 0..1 |
| TaskBoard_OneEngagement | Projects / Quotes | ID | 0..1 |
| TaskBoard_PlanStage | PlanStages | ID | 0..1 |
| TaskList_TaskBoard | Plans | ID | *:1 |
| TaskList_ContractGroupLine | ContractLines | ID | 0..1 |
| Task_TaskList | TaskLists | ID | *:1 |
| Task_KanbanLanes | KanbanLanes | ID | 0..1 |
| Task_Task_Dependency | Tasks | ID | 0..1 |
| Task_ProjectRole | ProjectRoles | ID | 0..1 |
| Task_BusinessUnit | BusinessUnits | ID | 0..1 |
| SubTask_Task | Tasks | ID | *:1 |
Resource Management
The Resource Management tables track planning, capacity, and absence at a daily and monthly grain. Planning tables record planned versus used effort per resource; capacity tables record how much capacity a resource has and how much is consumed; the working-days calendar provides the basis for monthly capacity.
PlanningPerDays
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| PlanningPerDay_Account | UserAccounts | ID | *:1 |
| PlanningPerDay_ProjectMember | ProjectMembers | ID | 0..1 |
| PlanningPerDay_Project | Projects | ID | 0..1 |
| PlanningPerDay_ContractLine | ContractLines | ID | 0..1 |
| PlanningPerDay_WorkloadPeriod | *WorkloadPeriods (deprecated) | ID | 0..1 |
| PlanningPerDay_CalculationPeriod | *CalculationPeriods (deprecated) | ID | 0..1 |
PlanningPerdayProjectMembers
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| PlanningPerdayProjectMember_ProjectMember | ProjectMembers | ID | *:1 |
| PlanningPerdayProjectMember_ContractGroupLine | ContractLines | ID | 0..1 |
ResourceMonthlyCapacities
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| ResourceMonthlyCapacity_Account | UserAccounts | ID | *:1 |
| ResourceMonthlyCapacity_MasterDataWorkingDaysPerMonth | MasterDataWorkingDaysPerMonths | ID | *:1 |
ResourceDailyCapacity
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| ResourceDailyCapacity_Account | UserAccounts | ID | *:1 |
ResourceAbsenceHolidayDayTotals
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| ResourceAbsenceHolidayDayTotals_Account | UserAccounts | ID | *:1 |
Events
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| Event_Account | UserAccounts | ID | *:1 |
| Event_OneEngagement | Projects / Quotes | ID | 0..1 |
| Event_ContractGroupLine | ContractLines | ID | 0..1 |
| Event_Company | Companies | ID | 0..1 |
| Event_ProjectRole | ProjectRoles | ID | 0..1 |
Time & Expenses
Time entries and expenses record actual effort and cost. Each links back to a project, a resource, and often a contract line and invoice.
TimeSheets
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| Project | Projects | ID | *:1 |
| Account | UserAccounts | ID | 0..1 |
| ProjectRole | ProjectRoles | ID | 0..1 |
| Company | Companies | ID | 0..1 |
| Invoice | Invoices | ID | 0..1 |
| ContractLine | ContractLines | ID | 0..1 |
| TimeSheet_ProjectMember | ProjectMembers | ID | *:1 |
| TimeSheet_Task | Tasks | ID | 0..1 |
| TimeSheet_BusinessUnit | BusinessUnits | ID | 0..1 |
| Comment_TimeSheet | Comments | ID | 0..1 |
Comments
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| Comment_TimeSheet | TimeSheets | ID | *:1 |
| Comment_Account | UserAccounts | ID | *:1 |
Expenses
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| Expense_ExpenseCategory | ExpenseCategories | ID | 0..1 |
| Expense_ContractGroupLine | ContractLines | ID | 0..1 |
| Expense_OneEngagement | Projects / Quotes | ID | 0..1 |
| Expense_Account | UserAccounts | ID | *:1 |
| Expense_Company | Companies | ID | 0..1 |
| Expense_Invoice | Invoices | ID | 0..1 |
| Expense_BusinessUnit | BusinessUnits | ID | 0..1 |
Invoicing
Invoices are generated from project activity. An invoice contains contract lines, which contain detailed line items, and carries its own tax breakdown.
Invoices
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| Project | Projects | ID | 0..1 |
| Company | Companies | ID | 0..1 |
| InvoiceSchema | RetainersAndInstallments | ID | 0..1 |
| Invoice_Contact_Main | Contacts | ID | 0..1 |
| InvoiceTax_Invoice | InvoiceTaxes | ID | 1:* |
InvoiceContractLines
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| InvoiceContractLine_Invoice | Invoices | ID | *:1 |
| InvoiceContractLine_ContractGroupLine | ContractLines | ID | 0..1 |
| InvoiceContractLine_InvoiceSchema | RetainersAndInstallments | ID | 0..1 |
InvoiceLines
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| InvoiceLine_InvoiceContractLine | InvoiceContractLines | ID | *:1 |
| InvoiceLine_Account | UserAccounts | ID | 0..1 |
| InvoiceLine_ProjectRole | ProjectRoles | ID | 0..1 |
Customers
Companies represent your customers. A company can have many contacts and many addresses.
Companies & Contacts
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| Company_DefaultAddress | Addresss | ID | 0..1 |
| Contact_Company | Companies | ID | 1:* |
| Address_Company | Companies | ID | 1:* |
Users & Business Units
User accounts represent your people. Each can belong to a business unit and have a default project role. Business units can be nested.
UserAccounts
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| Account_BusinessUnit | BusinessUnits | ID | 0..1 |
| Account_ProjectRole_Default | ProjectRoles | ID | 0..1 |
| BusinessUnit_Account_TeamLead | BusinessUnits | ID | 1:* |
BusinessUnits
| Field Name | Related Table | Related Field | Cardinality |
|---|---|---|---|
| BusinessUnit_SubBusinessUnit | BusinessUnits | ID | 0..1 (self) |
| BusinessUnit_Account_TeamLead | UserAccounts | ID | 0..1 |
| BusinessUnit_AccountingAuthorization | UserAccounts | ID | 0..1 |