1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-17 06:52:27 +01:00

Merge branch 'dev' of git.sleede.com:projets/fab-manager into dev

This commit is contained in:
Nicolas Florentin 2016-09-27 12:25:14 +02:00
commit 0e0ffa3668
92 changed files with 5037 additions and 1767 deletions

1
.fabmanager-version Normal file
View File

@ -0,0 +1 @@
2.4.0-dev

View File

@ -1,6 +1,10 @@
# Changelog Fab Manager
## next release
- Project images will show in full-size on a click
- Add a checkbox "I accept to receive informations from the FabLab" on Sign-up dialog and user's profile
- Share project with Facebook/Twitter
- Display fab-manager's version in "Powered by" label, when logged as admin
- Load translation locales from subdirectories
- Add wallet to user, client can pay total/partial reservation or subscription by wallet
- Public calendar for show all trainings/machines/events
@ -34,10 +38,20 @@
- Admins can toggle reminders on/off and customize the delay
- More file types allowed as project CAD attachements
- Project CAD attachements are now checked by MIME type in addition of extension check
- Display strategy's name in SSO providers list
- SSO: documentation improved with an usage example
- SSO: mapped fields display their data type. Integers, booleans and dates allow some transformations.
- Fix a bug: project drafts are shown on public profiles
- Fix a bug: event category disappear when editing the event
- Fix a bug: machine name is not shown in plan edition
- Fix a bug: machine slots with tags are not displayed correctly on reservation calendar
- Fix a bug: avatar, address and organization details mapping from SSO were broken
- Fix a bug: in SSO configuration some valid endpoints were recognized as erroneous
- Fix a bug: clicking on the text in stripe's payment modal, does not validate the checkbox
- Fix a bug: move event reservation is not limited by admin settings (prior-delay & disable)
- Fix a bug: UI issues on small devices (dashboard + admin views)
- Fix a bug: embedded video not working in training/machine description
- Fix a bug: reordering project's steps trigger the unsaved-warning dialog
- [TODO DEPLOY] `rake fablab:es_build_availabilities_index`
- [TODO DEPLOY] `rake fablab:es_add_event_filters`
- [TODO DEPLOY] `rake db:migrate`
@ -45,6 +59,10 @@
- [TODO DEPLOY] add `EXCEL_DATE_FORMAT` environment variable in `application.yml`
- [OPTIONAL] `rake fablab:fix:assign_category_to_uncategorized_events` (will put every non-categorized events into a new category called "No Category", to ease re-categorization)
## v2.3.1 2016 September 26
- Fix a bug: group cache filename too long
## v2.3.0 2016 June 28
- Public API with access management and online documentation

View File

@ -29,8 +29,9 @@ FabManager is the FabLab management solution. It is web-based, open-source and t
7.2.2. [Applying changes](#i18n-apply)
8. [Open Projects](#open-projects)
9. [Plugins](#plugins)
10. [Known issues](#known-issues)
11. [Related Documentation](#related-documentation)
10. [Single Sign-On](#sso)
11. [Known issues](#known-issues)
12. [Related Documentation](#related-documentation)
@ -359,6 +360,8 @@ To create it, please follow these instructions:
- `app/controllers/api/invoices_controllers.rb@list` is using `ILIKE` and `date_trunc()`
- `db/migrate/20160613093842_create_unaccent_function.rb` is using [unaccent](https://www.postgresql.org/docs/current/static/unaccent.html) and [trigram](https://www.postgresql.org/docs/current/static/pgtrgm.html) modules and defines a PL/pgSQL function (`f_unaccent()`)
- `app/controllers/api/members_controllers.rb@search` is using `f_unaccent()` (see above) and `regexp_replace()`
- `db/migrate/20150604131525_add_meta_data_to_notifications.rb` is using [jsonb](https://www.postgresql.org/docs/9.4/static/datatype-json.html), a PostgreSQL 9.4+ datatype.
- `db/migrate/20160915105234_add_transformation_to_o_auth2_mapping.rb` is using [jsonb](https://www.postgresql.org/docs/9.4/static/datatype-json.html), a PostgreSQL 9.4+ datatype.
- If you intend to contribute to the project code, you will need to run the test suite with `rake test`.
This also requires your user to have the _SUPERUSER_ role.
Please see the [known issues](#known-issues) section for more informations about this.
@ -619,6 +622,15 @@ To install a plugin, you just have to copy the plugin folder which contains its
You can see an example on the [repo of navinum gamification plugin](https://github.com/LaCasemate/navinum-gamification)
<a name="sso"></a>
## Single Sign-On
Fab-manager can be connected to a [Single Sign-On](https://en.wikipedia.org/wiki/Single_sign-on) server which will provide its own authentication for the platform's users.
Currently OAuth 2 is the only supported protocol for SSO authentication.
For an example of how to use configure a SSO in Fab-manager, please read [sso_with_github.md](doc/sso_with_github.md).
Developers may find informations on how to implement their own authentication protocol in [sso_authentication.md](doc/sso_authentication.md).
<a name="known-issues"></a>
## Known issues

View File

@ -34,6 +34,102 @@ check_oauth2_id_is_mapped = (mappings) ->
return false
##
# Provides a set of common callback methods and data to the $scope parameter. These methods are used
# in the various authentication providers' controllers.
#
# Provides :
# - $scope.authMethods
# - $scope.mappingFields
# - $scope.cancel()
# - $scope.defineDataMapping(mapping)
#
# Requires :
# - mappingFieldsPromise: retrieved by AuthProvider.mapping_fields()
# - $state (Ui-Router) [ 'app.admin.members' ]
##
class AuthenticationController
constructor: ($scope, $state, $uibModal, mappingFieldsPromise)->
## list of supported authentication methods
$scope.authMethods = METHODS
## list of fields that can be mapped through the SSO
$scope.mappingFields = mappingFieldsPromise
##
# Changes the admin's view to the members list page
##
$scope.cancel = ->
$state.go('app.admin.members')
##
# Open a modal allowing to specify the data mapping for the given field
##
$scope.defineDataMapping = (mapping) ->
$uibModal.open
templateUrl: '<%= asset_path "admin/authentications/_data_mapping.html" %>'
size: 'md'
resolve:
field: -> mapping
datatype: ->
for field in $scope.mappingFields[mapping.local_model]
if field[0] == mapping.local_field
return field[1]
controller: ['$scope', '$uibModalInstance', 'field', 'datatype', ($scope, $uibModalInstance, field, datatype) ->
## parent field
$scope.field = field
## expected data type
$scope.datatype = datatype
## data transformation rules
$scope.transformation =
rules: field.transformation || {type: datatype}
## available transformation formats
$scope.formats =
date: [
{
label: 'ISO 8601',
value: 'iso8601'
},
{
label: 'RFC 2822',
value: 'rfc2822'
},
{
label: 'RFC 3339',
value: 'rfc3339'
},
{
label: 'Timestamp (s)'
value: 'timestamp-s'
},
{
label: 'Timestamp (ms)',
value: 'timestamp-ms'
}
]
## Create a new mapping between anything and an expected integer
$scope.addIntegerMapping = ->
unless angular.isArray $scope.transformation.rules.mapping
$scope.transformation.rules.mapping = []
$scope.transformation.rules.mapping.push({from:'', to:0})
## close and save the modifications
$scope.ok = ->
$uibModalInstance.close($scope.transformation.rules)
## do not save the modifications
$scope.cancel = ->
$uibModalInstance.dismiss()
]
.result['finally'](null).then (transfo_rules) ->
mapping.transformation = transfo_rules
##
# Page listing all authentication providers
@ -103,15 +199,12 @@ Application.Controllers.controller "AuthentificationController", ["$scope", "$st
##
# Page to add a new authentication provider
##
Application.Controllers.controller "NewAuthenticationController", ["$scope", "$state", "$rootScope", "dialogs", "growl", "mappingFieldsPromise", "authProvidersPromise", "AuthProvider", '_t'
, ($scope, $state, $rootScope, dialogs, growl, mappingFieldsPromise, authProvidersPromise, AuthProvider, _t) ->
$scope.authMethods = METHODS
$scope.mappingFields = mappingFieldsPromise
Application.Controllers.controller "NewAuthenticationController", ["$scope", "$state", "$rootScope", "$uibModal", "dialogs", "growl", "mappingFieldsPromise", "authProvidersPromise", "AuthProvider", '_t'
, ($scope, $state, $rootScope, $uibModal, dialogs, growl, mappingFieldsPromise, authProvidersPromise, AuthProvider, _t) ->
$scope.mode = 'creation'
## default parameters for the new authentication provider
$scope.provider = {
name: '',
providable_type: '',
@ -172,12 +265,8 @@ Application.Controllers.controller "NewAuthenticationController", ["$scope", "$s
##
# Changes the admin's view to the members list page
##
$scope.cancel = ->
$state.go('app.admin.members')
## Using the AuthenticationController
new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise)
]
@ -185,17 +274,14 @@ Application.Controllers.controller "NewAuthenticationController", ["$scope", "$s
##
# Page to edit an already added authentication provider
##
Application.Controllers.controller "EditAuthenticationController", ["$scope", "$state", "$stateParams", "$rootScope", "dialogs", "growl", 'providerPromise', 'mappingFieldsPromise', 'AuthProvider', '_t'
, ($scope, $state, $stateParams, $rootScope, dialogs, growl, providerPromise, mappingFieldsPromise, AuthProvider, _t) ->
Application.Controllers.controller "EditAuthenticationController", ["$scope", "$state", "$stateParams", "$rootScope", "$uibModal", "dialogs", "growl", 'providerPromise', 'mappingFieldsPromise', 'AuthProvider', '_t'
, ($scope, $state, $stateParams, $rootScope, $uibModal, dialogs, growl, providerPromise, mappingFieldsPromise, AuthProvider, _t) ->
## parameters of the currently edited authentication provider
$scope.provider = providerPromise
$scope.authMethods = METHODS
$scope.mode = 'edition'
$scope.mappingFields = mappingFieldsPromise
##
# Update the current provider with the new inputs
##
@ -210,10 +296,8 @@ Application.Controllers.controller "EditAuthenticationController", ["$scope", "$
, ->
growl.error(_t('an_error_occurred_unable_to_update_the_provider'))
##
# Changes the admin's view to the members list page
##
$scope.cancel = ->
$state.go('app.admin.members')
## Using the AuthenticationController
new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise)
]

View File

@ -133,8 +133,9 @@ Application.Controllers.controller "InvoicesController", ["$scope", "$state", 'I
sample = sample.replace(/X\[([^\]]+)\]/g, (match, p1, offset, string) ->
p1
)
# information about wallet (W[text]) - does not apply here
sample = sample.replace(/W\[([^\]]+)\]/g, "")
# # information about wallet (W[text]) - does not apply here
# sample = sample.replace(/W\[([^\]]+)\]/g, "")
# information about refunds (R[text]) - does not apply here
sample = sample.replace(/R\[([^\]]+)\]/g, "")
sample

View File

@ -1,7 +1,7 @@
'use strict'
Application.Controllers.controller 'ApplicationController', ["$rootScope", "$scope", "$window", "Session", "AuthService", "Auth", "$uibModal", "$state", 'growl', 'Notification', '$interval', "Setting", '_t'
, ($rootScope, $scope, $window, Session, AuthService, Auth, $uibModal, $state, growl, Notification, $interval, Setting, _t) ->
Application.Controllers.controller 'ApplicationController', ["$rootScope", "$scope", "$window", "Session", "AuthService", "Auth", "$uibModal", "$state", 'growl', 'Notification', '$interval', "Setting", '_t', 'Version'
, ($rootScope, $scope, $window, Session, AuthService, Auth, $uibModal, $state, growl, Notification, $interval, Setting, _t, Version) ->
@ -14,6 +14,10 @@ Application.Controllers.controller 'ApplicationController', ["$rootScope", "$sco
### PUBLIC SCOPE ###
## Fab-manager's version
$scope.version =
version: ''
##
# Set the current user to the provided value and initialize the session
# @param user {Object} Rails/Devise user
@ -22,6 +26,11 @@ Application.Controllers.controller 'ApplicationController', ["$rootScope", "$sco
$rootScope.currentUser = user
Session.create(user);
getNotifications()
# fab-manager's app-version
if user.role == 'admin'
$scope.version = Version.get()
else
$scope.version = {version: ''}
##
@ -205,6 +214,7 @@ Application.Controllers.controller 'ApplicationController', ["$rootScope", "$sco
# try to retrieve any currently logged user
Auth.login().then (user) ->
$scope.setCurrentUser(user)
# force users to complete their profile if they are not
if user.need_completion
$state.transitionTo('app.logged.profileCompletion')
, (error) ->

View File

@ -132,8 +132,8 @@ Application.Controllers.controller "EventsController", ["$scope", "$state", 'Eve
Application.Controllers.controller "ShowEventController", ["$scope", "$state", "$stateParams", "Event", '$uibModal', 'Member', 'Reservation', 'Price', 'CustomAsset', 'eventPromise', 'growl', '_t', 'Wallet', 'helpers', 'priceCategoriesPromise',
($scope, $state, $stateParams, Event, $uibModal, Member, Reservation, Price, CustomAsset, eventPromise, growl, _t, Wallet, helpers, priceCategoriesPromise) ->
Application.Controllers.controller "ShowEventController", ["$scope", "$state", "$stateParams", "Event", '$uibModal', 'Member', 'Reservation', 'Price', 'CustomAsset', 'eventPromise', 'growl', '_t', 'Wallet', 'helpers', 'priceCategoriesPromise', 'settingsPromise',
($scope, $state, $stateParams, Event, $uibModal, Member, Reservation, Price, CustomAsset, eventPromise, growl, _t, Wallet, helpers, priceCategoriesPromise, settingsPromise) ->
@ -166,6 +166,12 @@ Application.Controllers.controller "ShowEventController", ["$scope", "$state", "
## List of price categories for the events
$scope.priceCategories = priceCategoriesPromise
## Global config: is the user authorized to change his bookings slots?
$scope.enableBookingMove = (settingsPromise.booking_move_enable == "true")
## Global config: delay in hours before a booking while changing the booking slot is forbidden
$scope.moveBookingDelay = parseInt(settingsPromise.booking_move_delay)
##
@ -374,10 +380,13 @@ Application.Controllers.controller "ShowEventController", ["$scope", "$state", "
# @param reservation {{total_booked_seats:number}}
##
$scope.reservationCanModify = (reservation)->
slotStart = moment(reservation.slots[0].start_at)
now = moment()
isAble = false
angular.forEach $scope.event.recurrence_events, (e)->
isAble = true if e.nb_free_places >= reservation.total_booked_seats
isAble
return (isAble and $scope.enableBookingMove and slotStart.diff(now, "hours") >= $scope.moveBookingDelay)
@ -408,7 +417,7 @@ Application.Controllers.controller "ShowEventController", ["$scope", "$state", "
# Return the URL allowing to share the current project on the Twitter social network
##
$scope.shareOnTwitter = ->
'https://twitter.com/intent/tweet?url='+encodeURIComponent($state.href('app.public.events_show', {id: $scope.event.id}, {absolute: true}));
'https://twitter.com/intent/tweet?url='+encodeURIComponent($state.href('app.public.events_show', {id: $scope.event.id}, {absolute: true}))+'&text='+encodeURIComponent($scope.event.title)

View File

@ -83,7 +83,7 @@ Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScop
##
$scope.openSubscribePlanModal = ->
Wallet.getWalletByUser {user_id: $scope.ctrl.member.id}, (wallet) ->
amountToPay = helpers.getAmountToPay($scope.selectedPlan.amount, wallet.amount)
amountToPay = helpers.getAmountToPay($scope.cart.total, wallet.amount)
if $scope.currentUser.role isnt 'admin' and amountToPay > 0
payByStripe()
else
@ -232,7 +232,7 @@ Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScop
else
$scope.attempting = true
Subscription.save
coupon_code: coupon.code
coupon_code: (coupon.code if coupon)
subscription:
plan_id: selectedPlan.id
user_id: member.id
@ -305,7 +305,7 @@ Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScop
$scope.ok = ->
$scope.attempting = true
Subscription.save
coupon_code: coupon.code
coupon_code: (coupon.code if coupon)
subscription:
plan_id: selectedPlan.id
user_id: member.id

View File

@ -155,15 +155,18 @@ class ProjectsController
##
# Change the step_nb property of the given step to the new value provided. The step that was previously at this
# index will be assigned to the old position of the provided step.
# @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
# @param step {Object} the project's step to reindex
# @param newIdx {number} the new index to assign to the step
##
$scope.changeStepIndex = (step, newIdx) ->
$scope.changeStepIndex = (event, step, newIdx) ->
event.preventDefault() if event
for s in $scope.project.project_steps_attributes
if s.step_nb == newIdx
s.step_nb = step.step_nb
step.step_nb = newIdx
break
false
$scope.autoCompleteName = (nameLookup) ->
@ -471,5 +474,5 @@ Application.Controllers.controller "ShowProjectController", ["$scope", "$state",
# Return the URL allowing to share the current project on the Twitter social network
##
$scope.shareOnTwitter = ->
'https://twitter.com/intent/tweet?url='+encodeURIComponent($state.href('app.public.projects_show', {id: $scope.project.slug}, {absolute: true}));
'https://twitter.com/intent/tweet?url='+encodeURIComponent($state.href('app.public.projects_show', {id: $scope.project.slug}, {absolute: true}))+'&text='+encodeURIComponent($scope.project.name)
]

View File

@ -400,6 +400,7 @@ Application.Controllers.controller "ReserveTrainingController", ["$scope", "$sta
if $scope.ctrl.member
# reserve a training if this training will not be reserved and is not about to move and not is completed
if !event.is_reserved && !$scope.slotToModify && !event.is_completed
$scope.coupon.applied = null
if event != $scope.selectedTraining
$scope.selectedTraining = event
$scope.selectedTraining.offered = false

View File

@ -5,6 +5,7 @@ Application.Directives.directive 'coupon', [ 'Coupon', 'growl', '_t', (Coupon, g
show: '='
coupon: '='
userId: '@'
hasSelectSlot: '='
templateUrl: '<%= asset_path "shared/_coupon.html" %>'
link: ($scope, element, attributes) ->
@ -18,6 +19,11 @@ Application.Directives.directive 'coupon', [ 'Coupon', 'growl', '_t', (Coupon, g
# Binding for the code inputed
$scope.couponCode = null
$scope.$watch 'hasSelectSlot', (newValue) ->
unless newValue
$scope.coupon = null
$scope.couponCode = null
$scope.code.input = false
##

View File

@ -18,7 +18,7 @@ Application.Directives.directive 'url', [ ->
Application.Directives.directive 'endpoint', [ ->
ENDPOINT_REGEXP = /^\/([-._~:?#\[\]@!$&'()*+,;=%\w]+\/?)*$/
ENDPOINT_REGEXP = /^\/?([-._~:?#\[\]@!$&'()*+,;=%\w]+\/?)*$/
{
require: 'ngModel'
link: (scope, element, attributes, ctrl) ->

View File

@ -515,6 +515,9 @@ angular.module('application.router', ['ui.router']).
priceCategoriesPromise: ['PriceCategory', (PriceCategory) ->
PriceCategory.query().$promise
]
settingsPromise: ['Setting', (Setting)->
Setting.query(names: "['booking_move_enable', 'booking_move_delay']").$promise
]
translations: [ 'Translations', (Translations) ->
Translations.query(['app.public.events_show', 'app.shared.member_select', 'app.shared.stripe',
'app.shared.valid_reservation_modal', 'app.shared.wallet', 'app.shared.coupon_input']).$promise

View File

@ -0,0 +1,5 @@
'use strict'
Application.Services.factory 'Version', ["$resource", ($resource)->
$resource "/api/version"
]

View File

@ -62,11 +62,9 @@ p {
line-height: rem-calc(24);
&.intro, .intro {
font-family: $font-proxima-condensed;
font-size: rem-calc(16);
line-height: rem-calc(24);
margin: 1.038em 0 30px 0;
font-weight: 600;
}
}

View File

@ -499,6 +499,11 @@ padding: 10px;
@media only screen and (max-width: 768px) {
display: none;
}
.app-version {
margin-right: 10px;
color: #999;
}
}
.disabling-overlay {

View File

@ -88,7 +88,7 @@
color: black;
}
.heading-title {
overflow: hidden;
//overflow: hidden;
height: 94px;
h1 {
margin: 0 0 0 15px;

View File

@ -125,6 +125,7 @@ p, .widget p {
.pull-in{margin-left: -15px;margin-right: -15px;}
.pull-out{margin:-10px -15px;}
.width-35 { width: 35% !important; }
.width-70 { width: 70%; }
.b{border: 1px solid rgba(0, 0, 0, 0.05)}
@ -171,6 +172,7 @@ p, .widget p {
}
.r-n { border-radius: 0 0 0 0; }
.p-xs { padding: 5px;}
.p-lg { padding: 30px; }
.p-l { padding: 16px; }

View File

@ -0,0 +1,65 @@
<div class="modal-header">
<h3 class="modal-title"><span translate>{{ 'data_mapping' }}</span> : {{field.local_field}}</h3>
</div>
<div class="modal-body m-lg">
<div>
<span translate>{{ 'expected_data_type' }}</span> : {{datatype}}
</div>
<form name="mappingForm" class="m-t-md">
<ng-switch on="datatype">
<!-- BOOLEAN -->
<div ng-switch-when="boolean">
<label for="add_mapping" translate>{{ 'mappings' }}</label>
<ul class="list-unstyled">
<li class="m-t-sm m-l">
<input type="text"
name="true_value"
id="true_value"
class="form-control inline width-35 m-r "
ng-model="transformation.rules.false_value">
<i class="fa fa-arrows-h"></i>
<label for="true_value" class="m-l">true</label>
</li>
<li class="m-t-sm m-l">
<input type="text"
name="false_value"
id="false_value"
class="form-control inline width-35 m-r "
ng-model="transformation.rules.true_value">
<i class="fa fa-arrows-h"></i>
<label for="false_value" class="m-l">false</label>
</li>
</ul>
</div>
<!-- DATE -->
<div ng-switch-when="date">
<label for="date_format" translate>{{ 'input_format' }}</label>
<select name="date_format"
id="date_format"
class="form-control"
ng-model="transformation.rules.format"
ng-options="format.value as format.label for format in formats.date">
</select>
</div>
<!-- INTEGER -->
<div ng-switch-when="integer">
<label for="add_mapping" translate>{{ 'mappings' }}</label>
<button class="btn btn-default pull-right" ng-click="addIntegerMapping()"><i class="fa fa-plus"></i></button>
<ul class="list-unstyled">
<li ng-repeat="map in transformation.rules.mapping" class="m-t-sm m-l">
<input type="text" class="form-control inline width-35 m-r " ng-model="map.from">
<i class="fa fa-arrows-h"></i>
<input type="number" class="form-control inline width-35 m-l" ng-model="map.to">
</li>
</ul>
</div>
</ng-switch>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()" ng-disabled="!mappingForm.$valid" ng-if="datatype != 'string' && datatype != 'text'" translate>{{ 'confirm' }}</button>
<button class="btn btn-warning" ng-click="cancel()" translate>{{ 'cancel' }}</button>
</div>

View File

@ -21,6 +21,9 @@
<td>{{m.api_data_type}}</td>
<td>{{m.api_field}}</td>
<td>
<button class="btn btn-info" ng-click="defineDataMapping(m)">
<i class="fa fa-info-circle"></i>
</button>
<button class="btn btn-danger" ng-click="m._destroy = true">
<i class="fa fa-trash-o"></i>
</button>
@ -38,7 +41,7 @@
<td ng-class="{'has-error': mappingForm['auth_mapping[local_field]'].$dirty && mappingForm['auth_mapping[local_field]'].$invalid}">
<select class="form-control"
name="auth_mapping[local_field]"
ng-options="field for field in mappingFields[newMapping.local_model]"
ng-options="field[0] as field[0] for field in mappingFields[newMapping.local_model]"
ng-model="newMapping.local_field"
required>
</select>

View File

@ -14,6 +14,8 @@
<tr>
<th style="width:15%" translate>{{ 'name' }}</th>
<th style="width:15%" translate>{{ 'strategy_name' }}</th>
<th style="width:15%" translate>{{ 'type' }}</th>
<th style="width:15%" translate>{{ 'state' }}</th>
@ -24,6 +26,7 @@
<tbody>
<tr ng-repeat="provider in providers | filter:searchFilter">
<td>{{ provider.name }}</td>
<td>{{ provider.strategy_name }}</td>
<td>{{ getType(provider.providable_type) }}</td>
<td>{{ getState(provider.status) }}</td>
<td>

View File

@ -5,13 +5,13 @@
<a href="#" ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left "></i></a>
</section>
</div>
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
<div class="col-xs-7 col-sm-7 col-md-8 b-l">
<section class="heading-title">
<h1>{{ 'coupon' | translate }} {{ coupon.name }}</h1>
<h1>{{ 'coupon' | translate }} : {{ coupon.name }}</h1>
</section>
</div>
<div class="col-md-3">
<div class="col-xs-3 col-md-3">
<section class="heading-actions wrapper">
<a class="btn btn-lg btn-block btn-default m-t-xs" ui-sref="app.admin.pricing" translate>{{ 'cancel' }}</a>
</section>

View File

@ -210,7 +210,7 @@
<li ng-click="invoice.reference.help = 'addDay.html'">{{ 'day' | translate }}</li>
<li ng-click="invoice.reference.help = 'addInvoiceNumber.html'">{{ '#_of_invoice' | translate }}</li>
<li ng-click="invoice.reference.help = 'addOnlineInfo.html'">{{ 'online_sales' | translate }}</li>
<li ng-click="invoice.reference.help = 'addWalletInfo.html'">{{ 'wallet' | translate }}</li>
<%# <li ng-click="invoice.reference.help = 'addWalletInfo.html'">{{ 'wallet' | translate }}</li> %>
<li ng-click="invoice.reference.help = 'addRefundInfo.html'">{{ 'refund' | translate }}</li>
</ul>
</div>

View File

@ -27,10 +27,10 @@
<tr>
<th style="width:15%"><a href="" ng-click="setOrderMember('last_name')">{{ 'surname' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='last_name', 'fa fa-sort-alpha-desc': member.order=='-last_name', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:15%"><a href="" ng-click="setOrderMember('first_name')">{{ 'first_name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='first_name', 'fa fa-sort-alpha-desc': member.order=='-first_name', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:15%"><a href="" ng-click="setOrderMember('email')">{{ 'email' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='email', 'fa fa-sort-alpha-desc': member.order=='-email', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:10%"><a href="" ng-click="setOrderMember('phone')">{{ 'phone' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': member.order=='phone', 'fa fa-sort-numeric-desc': member.order=='-phone', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:20%"><a href="" ng-click="setOrderMember('group')">{{ 'user_type' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='group', 'fa fa-sort-alpha-desc': member.order=='-group', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:15%"><a href="" ng-click="setOrderMember('plan')">{{ 'subscription' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='plan', 'fa fa-sort-alpha-desc': member.order=='-plan', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:15%" class="hidden-xs"><a href="" ng-click="setOrderMember('email')">{{ 'email' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='email', 'fa fa-sort-alpha-desc': member.order=='-email', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:10%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('phone')">{{ 'phone' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': member.order=='phone', 'fa fa-sort-numeric-desc': member.order=='-phone', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:20%" class="hidden-xs hidden-sm"><a href="" ng-click="setOrderMember('group')">{{ 'user_type' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='group', 'fa fa-sort-alpha-desc': member.order=='-group', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:15%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('plan')">{{ 'subscription' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='plan', 'fa fa-sort-alpha-desc': member.order=='-plan', 'fa fa-arrows-v': member.order }"></i></a></th>
<th style="width:10%"></th>
</tr>
</thead>
@ -38,10 +38,10 @@
<tr ng-repeat="m in members">
<td class="text-c">{{ m.profile.last_name }}</td>
<td class="text-c">{{ m.profile.first_name }}</td>
<td>{{ m.email }}</td>
<td>{{ m.profile.phone }}</td>
<td class="text-u-c text-sm">{{ m.group.name }}</td>
<td>{{ m.subscribed_plan | humanReadablePlanName }}</td>
<td class="hidden-xs">{{ m.email }}</td>
<td class="hidden-xs hidden-sm hidden-md">{{ m.profile.phone }}</td>
<td class="text-u-c text-sm hidden-xs hidden-sm">{{ m.group.name }}</td>
<td class="hidden-xs hidden-sm hidden-md">{{ m.subscribed_plan | humanReadablePlanName }}</td>
<td>
<div class="buttons">
<button class="btn btn-default" ui-sref="app.admin.members_edit({id: m.id})">

View File

@ -14,7 +14,7 @@
<th><a href="" ng-click="setOrderPlans('name')">{{ 'name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderPlans=='name', 'fa fa-sort-alpha-desc': orderPlans=='-name', 'fa fa-arrows-v': orderPlans }"></i></a></th>
<th><a href="" ng-click="setOrderPlans('interval')">{{ 'duration' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-amount-asc': orderPlans=='interval', 'fa fa-sort-amount-desc': orderPlans=='-interval', 'fa fa-arrows-v': orderPlans }"></i></a></th>
<th><a href="" ng-click="setOrderPlans('group_id')">{{ 'group' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderPlans=='group_id', 'fa fa-sort-alpha-desc': orderPlans=='-group_id', 'fa fa-arrows-v': orderPlans }"></i></a></th>
<th><a href="" ng-click="setOrderPlans('ui_weight')">{{ 'prominence' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderPlans=='ui_weight', 'fa fa-sort-numeric-desc': orderPlans=='-ui_weight', 'fa fa-arrows-v': orderPlans }"></i></a></th>
<th class="hidden-xs"><a href="" ng-click="setOrderPlans('ui_weight')">{{ 'prominence' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderPlans=='ui_weight', 'fa fa-sort-numeric-desc': orderPlans=='-ui_weight', 'fa fa-arrows-v': orderPlans }"></i></a></th>
<th><a href="" ng-click="setOrderPlans('amount')">{{ 'price' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderPlans=='amount', 'fa fa-sort-numeric-desc': orderPlans=='-amount', 'fa fa-arrows-v': orderPlans }"></i></a></th>
<th></th>
</tr>
@ -25,7 +25,7 @@
<td>{{plan.base_name}}</td>
<td>{{ plan.interval | planIntervalFilter:plan.interval_count }}</td>
<td>{{getGroupFromId(groups, plan.group_id).name}}</td>
<td>{{plan.ui_weight}}</td>
<td class="hidden-xs">{{plan.ui_weight}}</td>
<td>{{plan.amount | currency}}</td>
<td><button type="button" class="btn btn-default" ui-sref="app.admin.plans.edit({id:plan.id})"><i class="fa fa-pencil-square-o"></i></button> <button type="button" class="btn btn-danger" ng-click="deletePlan(plans, plan.id)"><i class="fa fa-trash"></i></button></td>
</tr>

View File

@ -15,7 +15,7 @@
{{ licence.name }}
</span>
</td>
<td class="hidden-xs">
<td class="hidden-xs">
<span editable-textarea="licence.description" e-rows="5" e-cols="100" e-name="description" e-form="rowform" e-required>
<div class="text-sm">{{ licence.description }}</div>
</span>

View File

@ -28,7 +28,7 @@
<uib-tabset justified="true">
<uib-tab ng-repeat="stat in statistics" heading="{{stat.label}}" select="setActiveTab(stat)" ng-if="stat.table && !(stat.es_type_key == 'subscription' && fablabWithoutPlans)">
<form id="filters_form" name="filters_form" class="form-inline m-t-md m-b-lg" novalidate="novalidate">
<div id="agePickerPane" class="form-group datepicker-container">
<div id="agePickerPane" class="form-group datepicker-container" style="z-index:102;">
<button id="agePickerExpand" class="btn btn-default" type="button" ng-click="agePicker.show = !agePicker.show">
<i class="fa fa-birthday-cake"></i>
<span ng-show="agePicker.start || agePicker.end">
@ -69,7 +69,7 @@
<select ng-model="type.selected" ng-options="type.label for type in stat.types" class="form-control"> </select>
</div>
<div id="customFilterPane" class="form-group datepicker-container m-l-md">
<div id="customFilterPane" class="form-group datepicker-container m-l-md" style="z-index:101;">
<button id="customFilterExpand" class="btn btn-default customMenuButton" type="button" ng-click="customFilter.show = !customFilter.show">
<i class="fa fa-filter"></i>
<span ng-show="!customFilter.criterion.key" class="text-gray" translate>{{ 'custom_filter' }}</span>
@ -172,7 +172,7 @@
<i class="fa fa-caret-up" ng-show="datePicker.show"></i>
</button>
<div class="datepicker-dropdown" ng-show="datePicker.show">
<ul class="list-unstyled">
<ul class="list-unstyled p-xs">
<li class="row">
<span class="col-md-4" translate>{{ 'start' }}</span>
<div class="input-group black col-md-7 m-r" id="date_pick_start">

View File

@ -27,15 +27,14 @@
<div class="col-xs-12 col-sm-6 col-md-4" ng-repeat="machine in machines.slice(3*$index, 3*$index + 3)">
<div class="widget panel panel-default" ng-click="showMachine(machine)">
<div class="panel-heading picture" ng-if="!machine.machine_image">
<div class="widget panel panel-default">
<div class="panel-heading picture" ng-if="!machine.machine_image" ng-click="showMachine(machine)">
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:&#xf03e;/font:FontAwesome/icon" bs-holder class="img-responsive">
</div>
<div class="panel-heading picture" style="background-image:url({{machine.machine_image}})" ng-if="machine.machine_image">
<div class="panel-heading picture" style="background-image:url({{machine.machine_image}})" ng-if="machine.machine_image" ng-click="showMachine(machine)">
</div>
<div class="panel-body" style="heigth:170px;">
<h1 class="m-b">{{machine.name}}</h1>
<p ng-bind-html="machine.description | simpleText | humanize : 140 | breakFilter"></p>
<div class="panel-body">
<h1 class="text-center m-b">{{machine.name}}</h1>
</div>
<div class="panel-footer no-padder">

View File

@ -78,7 +78,7 @@
<div class="clear"><a class="pull-right m-b-sm text-u-l ng-scope m-r-sm" href="#" ng-click="removeMachineSlot(machineSlot, $event)" ng-if="machineSlot.isValid" translate>{{ 'remove_this_slot' }}</a></div>
</div>
<coupon show="machineSlotsValid() && (!plansAreShown || selectedPlan)" coupon="coupon.applied" user-id="{{ctrl.member.id}}"></coupon>
<coupon show="machineSlotsValid() && (!plansAreShown || selectedPlan)" coupon="coupon.applied" has-select-slot="machineSlotsValid()" user-id="{{ctrl.member.id}}"></coupon>
<span ng-hide="fablabWithoutPlans">
<div ng-if="machineSlotsValid() && !ctrl.member.subscribed_plan" ng-show="!plansAreShown">

View File

@ -34,7 +34,7 @@
<img ng-src="{{machine.machine_image}}" alt="{{machine.name}}" class="img-responsive">
</div>
<p class="intro" ng-bind-html="machine.description | breakFilter"></p>
<p class="intro" ng-bind-html="machine.description | toTrusted"></p>
</div>
@ -48,7 +48,7 @@
</div>
<div class="widget-content no-bg wrapper">
<h3></h3>
<p ng-bind-html="machine.spec"></p>
<p ng-bind-html="machine.spec | toTrusted"></p>
</div>
</div>

View File

@ -79,13 +79,13 @@
{{ 'step_N' | translate:{ INDEX:step.step_nb } }}/{{totalSteps}} <i class="fa fa-caret-down" aria-hidden="true"></i>
</button>
<ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="single-button">
<li role="menuitem" ng-repeat="step_idx in intArray(1, totalSteps +1)"><a href="#" ng-click="changeStepIndex(step, step_idx)">{{ 'step_N' | translate:{ INDEX:step_idx } }}</a></li>
<li role="menuitem" ng-repeat="step_idx in intArray(1, totalSteps +1)"><a href="#" ng-click="changeStepIndex($event, step, step_idx)">{{ 'step_N' | translate:{ INDEX:step_idx } }}</a></li>
</ul>
</div>
<span class="label label-warning m-t m-b"></span>
<input type="hidden" name="project[project_steps_attributes][][id]" ng-value="step.id" />
<input type="hidden" name="project[project_steps_attributes][][_destroy]" ng-value="step._destroy" />
<input type="hidden" name="project[project_steps_attributes][][step_nb]" ng-value="step.step_nb" />
<input type="hidden" name="project[project_steps_attributes][][step_nb]" ng-value="step.step_nb"/>
<input ng-model="step.title"
type="text"
name="project[project_steps_attributes][][title]"
@ -97,7 +97,7 @@
<summernote ng-model="step.description" placeholder="" config="summernoteOpts" name=project[project_steps_attributes][][description]></summernote>
<div class="fileinput" data-provides="fileinput" ng-class="fileinputClass(step.project_step_image)">
<span class="btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'add_a_picture' }}</span><span class="fileinput-exists" translate>{{ 'change_the_picture' }}</span>
<span class="btn btn-default btn-file"><span class="fileinput-new">{{ 'add_a_picture' | translate }} <i class="fa fa-file-image-o m-l-sm" aria-hidden="true"></i></span><span class="fileinput-exists" translate>{{ 'change_the_picture' }}</span>
<input type="file"
name="project[project_steps_attributes][][project_step_image_attributes][attachment]"></span>
<span class="fileinput-filename">{{step.project_step_image}}</span>
@ -105,11 +105,13 @@
</div>
<div>
<a class="btn btn-sm btn-danger" ng-click="deleteStep(step)" role="button"><i class="fa fa-trash-o"></i> {{ 'delete_the_step' | translate }}</a>
<a class="btn btn-sm btn-danger" ng-click="deleteStep(step)" role="button"><i class="fa fa-trash-o m-r-xs"></i> {{ 'delete_the_step' | translate }}</a>
</div>
</div>
</div>
<a class="btn btn-default m-b" ng-click="addStep()" role="button" translate>{{ 'add_a_new_step' }}</a>
<a class="btn btn-default m-b" ng-click="addStep()" role="button">
<i class="fa fa-plus m-r-sm" aria-hidden="true"></i>
<span translate>{{ 'add_a_new_step' }}</span></a>
</div>
</div>

View File

@ -31,7 +31,7 @@
<div class="article wrapper-lg">
<div class="article-thumbnail" ng-if="project.project_image">
<a href="{{project.project_image}}" target="_blank"><img ng-src="{{project.project_image}}" alt="{{project.name}}" class="img-responsive"></a>
<a href="{{project.project_full_image}}" target="_blank"><img ng-src="{{project.project_image}}" alt="{{project.name}}" class="img-responsive"></a>
</div>
<h3 translate>{{ 'project_description' }}</h3>
@ -43,7 +43,7 @@
<h3 class="well well-simple step-title">{{ 'step_N' | translate:{INDEX:step.step_nb} }} : {{step.title}}</h3>
</div>
<div class="col-md-4" ng-if="step.project_step_image">
<a href="{{step.project_step_image_url}}" target="_blank"><img class="img-responsive m-b" ng-src="{{step.project_step_image_url}}" alt="{{step.title}}" ></a>
<a href="{{step.project_step_full_image_url}}" target="_blank"><img class="img-responsive m-b" ng-src="{{step.project_step_image_url}}" alt="{{step.title}}" ></a>
</div>
<div class="col-md-8" ng-class="{'col-md-12' : step.project_step_image == undefined}">

View File

@ -1,5 +1,5 @@
<div class="form-group m-b-lg" ng-show="show">
<a ng-click="code. input = true" ng-hide="code.input" class="b-b" translate>{{ 'i_have_a_coupon' }}</a>
<a ng-click="code.input = true" ng-hide="code.input" class="b-b" translate>{{ 'i_have_a_coupon' }}</a>
<div ng-show="code.input">
<label for="coupon_code" translate>{{ 'code_' }}</label>
@ -18,4 +18,4 @@
</span>
</div>
</div>
</div>
</div>

View File

@ -1,10 +1,10 @@
<div ng-if="currentUser.role != 'admin'">
<h3 class="m-t-xs" ng-if="walletAmount > 0 && price > 0">{{ 'you_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol } }}</h3>
<h3 class="m-t-xs" ng-if="walletAmount > 0 && price > 0" ng-bind-html="'you_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol }"></h3>
<p ng-if="walletAmount > 0 && price > 0 && amount === 0" class="text-italic">{{'wallet_pay_reservation' | translate}}</p>
<p ng-if="walletAmount > 0 && amount !== 0" class="text-italic">{{'credit_amount_for_pay_reservation' | translate:{ amount: numberFilter(amount, 2), currency: currencySymbol } }}</p>
<p ng-if="walletAmount > 0 && amount !== 0" class="text-italic" ng-bind-html="'credit_amount_for_pay_reservation' | translate:{ amount: numberFilter(amount, 2), currency: currencySymbol }"></p>
</div>
<div ng-if="currentUser.role == 'admin'">
<h3 class="m-t-xs" ng-if="walletAmount > 0 && price > 0">{{ 'client_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol } }}</h3>
<h3 class="m-t-xs" ng-if="walletAmount > 0 && price > 0" ng-bind-html="'client_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol }"></h3>
<p ng-if="walletAmount > 0 && price > 0 && amount === 0" class="text-italic">{{'client_wallet_pay_reservation' | translate}}</p>
<p ng-if="walletAmount > 0 && amount !== 0" class="text-italic">{{'client_credit_amount_for_pay_reservation' | translate:{ amount: numberFilter(amount, 2), currency: currencySymbol } }}</p>
<p ng-if="walletAmount > 0 && amount !== 0" class="text-italic" ng-bind-html="'client_credit_amount_for_pay_reservation' | translate:{ amount: numberFilter(amount, 2), currency: currencySymbol }"></p>
</div>

View File

@ -27,11 +27,11 @@
</li>
<li class="dropdown user-profile-nav" ng-if="isAuthenticated()" uib-dropdown>
<a href="#" class="dropdown-toggle" uib-dropdown-toggle>
<span class="avatar text-center">
<fab-user-avatar ng-model="currentUser.profile.user_avatar" avatar-class="thumb-50"></fab-user-avatar>
<!-- <i class="on b-white bottom"></i> -->
<span class="user-name m-l-sm text-black-light font-sbold hidden-sm">{{currentUser.name}} <b class="caret"></b></span>
</span>
<span class="avatar text-center">
<fab-user-avatar ng-model="currentUser.profile.user_avatar" avatar-class="thumb-50"></fab-user-avatar>
<span class="user-name m-l-sm text-black-light font-sbold hidden-sm">{{currentUser.name}} </span>
<b class="caret"></b>
</span>
</a>
<ul class="uib-dropdown-menu animated fadeInRight">
<li><a href="#" ui-sref="app.logged.dashboard.profile" translate>{{ 'my_profile' }}</a></li>

View File

@ -10,8 +10,8 @@
<form name="stripeForm" stripe:form="payment" class="form-horizontal">
<div class="panel-body">
<h3 class="m-t-xs" ng-if="walletAmount">{{ 'you_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol } }}</h3>
<p ng-if="walletAmount > 0 && amount !== 0" class="text-italic">{{'credit_amount_for_pay_reservation' | translate:{ amount: numberFilter(amount, 2), currency: currencySymbol } }}</p>
<h3 class="m-t-xs" ng-if="walletAmount" ng-bind-html="'you_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol }"></h3>
<p ng-if="walletAmount > 0 && amount !== 0" class="text-italic" ng-bind-html="'credit_amount_for_pay_reservation' | translate:{ amount: numberFilter(amount, 2), currency: currencySymbol }"></p>
<div class="form-group" ng-class="{'has-error': stripeForm.number.$dirty && stripeForm.number.$invalid}">
<div class="col-sm-12">
@ -32,8 +32,9 @@
</div>
<div class="form-group" ng-class="{'has-error': stripeForm.acceptCondition.$dirty && stripeForm.acceptCondition.$invalid}" ng-show="cgv">
<div class="col-sm-12 text-sm">
<input type="checkbox" name="acceptCondition" ng-model="acceptCondition" value="true" ng-required="cgv != null"/> {{ 'i_have_read_and_accept_' | translate }} <a href="{{cgv.custom_asset_file_attributes.attachment_url}}" target="_blank" translate>{{ '_the_general_terms_and_conditions' }}</a>
<div class="col-sm-12 text-sm checkbox-group">
<input type="checkbox" name="acceptCondition" id="acceptCondition" ng-model="acceptCondition" value="true" ng-required="cgv != null"/>
<label for="acceptCondition">{{ 'i_have_read_and_accept_' | translate }} <a href="{{cgv.custom_asset_file_attributes.attachment_url}}" target="_blank" translate>{{ '_the_general_terms_and_conditions' }}</a></label>
</div>
<div ng-if="!cgv">
<input type="hidden" name="acceptCondition" ng-model="acceptCondition" value="true">

View File

@ -23,16 +23,13 @@
<div class="widget panel panel-default">
<div class="panel-heading picture" ng-if="!training.training_image">
<div class="panel-heading picture" ng-if="!training.training_image" ng-click="showTraining(training)">
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:&#xf03e;/font:FontAwesome/icon" bs-holder class="img-responsive">
</div>
<div class="panel-heading picture" style="background-image:url({{training.training_image}})" ng-if="training.training_image">
<div class="panel-heading picture" style="background-image:url({{training.training_image}})" ng-if="training.training_image" ng-click="showTraining(training)">
</div>
<div class="panel-body" style="heigth:170px;">
<h1 class="m-b">{{training.name}}</h1>
<div ng-if="training.description">
<p ng-bind-html="training.description | simpleText | humanize : 140 | breakFilter"></p>
</div>
<div class="panel-body">
<h1 class="m-b text-center">{{training.name}}</h1>
</div>
<div class="panel-footer no-padder">

View File

@ -82,7 +82,7 @@
<a class="pull-right m-t-xs text-u-l" href="#" ng-click="removeTraining($event)" ng-if="trainingIsValid" translate>{{ 'remove_this_slot' }}</a>
</div>
<coupon show="trainingIsValid && (!plansIsShow || selectedPlan)" coupon="coupon.applied" user-id="{{ctrl.member.id}}"></coupon>
<coupon show="trainingIsValid && (!plansIsShow || selectedPlan)" coupon="coupon.applied" has-select-slot="trainingIsValid" user-id="{{ctrl.member.id}}"></coupon>
<span ng-hide="fablabWithoutPlans">
<div ng-if="trainingIsValid && !ctrl.member.subscribed_plan" ng-show="!plansIsShow">

View File

@ -15,7 +15,9 @@
<div class="col-xs-12 col-sm-12 col-md-4 b-t hide-b-md">
<section class="heading-actions wrapper">
<a ng-click="reserveTraining(training, $event)" class="btn btn-lg btn-warning bg-white b-2x rounded m-t-xs" translate>{{ 'book_this_training' }}</a>
<a ng-click="reserveTraining(training, $event)" class="btn btn-lg btn-warning bg-white b-2x rounded m-t-xs" ng-if="!isAuthorized('admin')" translate>{{ 'book_this_training' }}</a>
<a ui-sref="app.admin.trainings_edit({id: training.id})" ng-if="isAuthorized('admin')" class="btn btn-lg btn-warning bg-white b-2x rounded m-t-xs"><i class="fa fa-edit"></i> {{ 'edit' | translate }}</a>
</section>
</div>
</div>
@ -30,7 +32,7 @@
<img ng-src="{{training.training_image}}" alt="{{training.name}}" class="img-responsive">
</div>
<p class="intro" ng-bind-html="training.description | breakFilter"></p>
<p class="intro" ng-bind-html="training.description | toTrusted"></p>
</div>

View File

@ -31,8 +31,11 @@ class API::AuthProvidersController < API::ApiController
def destroy
authorize AuthProvider
@provider.destroy
head :no_content
if @provider.safe_destroy
head :no_content
else
render json: @provider.errors, status: :unprocessable_entity
end
end
def mapping_fields
@ -56,9 +59,10 @@ class API::AuthProvidersController < API::ApiController
params.require(:auth_provider).permit(:name, :providable_type)
elsif params['auth_provider']['providable_type'] == OAuth2Provider.name
params.require(:auth_provider).permit(:name, :providable_type, providable_attributes: [
:id, :base_url, :token_endpoint, :authorization_endpoint, :profile_url, :client_id, :client_secret,
:id, :base_url, :token_endpoint, :authorization_endpoint, :logout_endpoint, :profile_url, :client_id, :client_secret,
o_auth2_mappings_attributes: [
:id, :local_model, :local_field, :api_field, :api_endpoint, :api_data_type, :_destroy
:id, :local_model, :local_field, :api_field, :api_endpoint, :api_data_type, :_destroy,
transformation: [:type, :format, :true_value, :false_value, mapping: [:from, :to]]
]
])
end

View File

@ -20,19 +20,23 @@ class API::ReservationsController < API::ApiController
end
def create
if current_user.is_admin?
@reservation = Reservation.new(reservation_params)
is_reserve = @reservation.save_with_local_payment(coupon_params[:coupon_code])
else
@reservation = Reservation.new(reservation_params.merge(user_id: current_user.id))
is_reserve = @reservation.save_with_payment(coupon_params[:coupon_code])
end
if is_reserve
SubscriptionExtensionAfterReservation.new(@reservation).extend_subscription_if_eligible
begin
if current_user.is_admin?
@reservation = Reservation.new(reservation_params)
is_reserve = @reservation.save_with_local_payment(coupon_params[:coupon_code])
else
@reservation = Reservation.new(reservation_params.merge(user_id: current_user.id))
is_reserve = @reservation.save_with_payment(coupon_params[:coupon_code])
end
if is_reserve
SubscriptionExtensionAfterReservation.new(@reservation).extend_subscription_if_eligible
render :show, status: :created, location: @reservation
else
render json: @reservation.errors, status: :unprocessable_entity
render :show, status: :created, location: @reservation
else
render json: @reservation.errors, status: :unprocessable_entity
end
rescue InvalidCouponError
render json: {coupon_code: 'wrong coupon code or expired'}, status: :unprocessable_entity
end
end

View File

@ -14,20 +14,12 @@ class API::SubscriptionsController < API::ApiController
else
if current_user.is_admin?
@subscription = Subscription.find_or_initialize_by(user_id: subscription_params[:user_id])
@subscription.update_column(:expired_at, nil) unless @subscription.new_record? # very important
@subscription.attributes = subscription_params
is_subscribe = @subscription.save_with_local_payment(!User.find(subscription_params[:user_id]).invoicing_disabled?, coupon_params[:coupon_code])
else
member = User.find(subscription_params[:user_id])
plan = Plan.find(subscription_params[:plan_id])
@subscription = Subscription.find_or_initialize_by(user_id: current_user.id)
if valid_card_token?(subscription_params[:card_token]) or (member.wallet.amount >= plan.amount / 100.0)
@subscription.update_column(:expired_at, nil) unless @subscription.new_record? # very important
@subscription.attributes = subscription_params.merge(user_id: current_user.id)
is_subscribe = @subscription.save_with_payment(true, coupon_params[:coupon_code])
else
is_subscribe = false
end
@subscription.attributes = subscription_params
is_subscribe = @subscription.save_with_payment(true, coupon_params[:coupon_code])
end
if is_subscribe
render :show, status: :created, location: @subscription

View File

@ -0,0 +1,10 @@
class API::VersionController < API::ApiController
before_action :authenticate_user!
def show
authorize :version
version = File.read('.fabmanager-version')
render json: {version: version}, status: :ok
end
end

View File

@ -14,7 +14,7 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
@user.username = generate_unique_username(@user.username)
end
# If the email is mapped, we check its uniqueness. If the email is already in use, we mark it as duplicate with an
# unique random string because.
# unique random string, because:
# - if it is the same user, his email will be filled from the SSO when he merge his accounts
# - if it is not the same user, this will prevent the raise of PG::UniqueViolation
if active_provider.sso_fields.include?('user.email') and email_exists?(@user.email)
@ -22,7 +22,7 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
@user.email = "<#{old_mail}>#{Devise.friendly_token}-duplicate"
flash[:alert] = t('omniauth.email_already_linked_to_another_account_please_input_your_authentication_code', OLD_MAIL: old_mail)
end
else
else # => update of an existing user
if username_exists?(@user.username, @user.id)
flash[:alert] = t('omniauth.your_username_is_already_linked_to_another_account_unable_to_update_it', USERNAME: @user.username)
@user.username = User.find(@user.id).username

View File

@ -0,0 +1,3 @@
# Raised when using a coupon expired or invalid
class InvalidCouponError < StandardError
end

View File

@ -80,6 +80,14 @@ class AuthProvider < ActiveRecord::Base
providable.profile_url
end
def safe_destroy
if self.status != 'active'
destroy
else
false
end
end
private
def set_initial_state
# the initial state of a new AuthProvider will be 'pending', except if there is currently

View File

@ -69,7 +69,7 @@ class Invoice < ActiveRecord::Base
end
# information about wallet (W[text])
reference.gsub!(/W\[([^\]]+)\]/, ''.to_s)
#reference.gsub!(/W\[([^\]]+)\]/, ''.to_s)
# remove information about refunds (R[text])
reference.gsub!(/R\[([^\]]+)\]/, ''.to_s)

View File

@ -37,4 +37,16 @@ class Profile < ActiveRecord::Base
def str_gender
gender ? 'male' : 'female'
end
def self.mapping
# we protect some fields as they are designed to be managed by the system and must not be updated externally
blacklist = %w(id user_id created_at updated_at)
# model-relationships must be added manually
additional = [%w(avatar string), %w(address string), %w(organization_name string), %w(organization_address string)]
Profile.column_types
.map{|k,v| [k, v.type.to_s]}
.delete_if { |col| blacklist.include?(col[0]) }
.concat(additional)
end
end

View File

@ -131,14 +131,19 @@ class Reservation < ActiveRecord::Base
# === Coupon ===
unless coupon_code.nil?
cp = Coupon.find_by_code(coupon_code)
total = invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+)
unless on_site
invoice_items << Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: -(total * cp.percent_off / 100).to_i,
currency: Rails.application.secrets.stripe_currency,
description: "coupon #{cp.code}"
)
if not cp.nil? and cp.status(user.id) == 'active'
@coupon = cp
total = invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+)
unless on_site
invoice_items << Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: -(total * cp.percent_off / 100).to_i,
currency: Rails.application.secrets.stripe_currency,
description: "coupon #{cp.code} - reservation"
)
end
else
raise InvalidCouponError
end
end
@ -385,6 +390,9 @@ class Reservation < ActiveRecord::Base
plan = Plan.find(plan_id)
total += plan.amount
end
if @coupon
total = (total - (total * @coupon.percent_off / 100.0)).to_i
end
wallet_amount = (user.wallet.amount * 100).to_i
wallet_amount >= total ? total : wallet_amount
@ -410,8 +418,12 @@ class Reservation < ActiveRecord::Base
unless coupon_code.nil?
cp = Coupon.find_by_code(coupon_code)
total = total - (total * cp.percent_off / 100.0)
self.invoice.coupon_id = cp.id
if not cp.nil? and cp.status(user.id) == 'active'
total = total - (total * cp.percent_off / 100.0)
self.invoice.coupon_id = cp.id
else
raise InvalidCouponError
end
end
self.invoice.total = total

View File

@ -20,44 +20,45 @@ class Subscription < ActiveRecord::Base
# Stripe subscription payment
def save_with_payment(invoice = true, coupon_code = nil)
if valid?
customer = Stripe::Customer.retrieve(user.stp_customer_id)
begin
# dont add a wallet invoice item if pay subscription by reservation
customer = Stripe::Customer.retrieve(user.stp_customer_id)
invoice_items = []
unless coupon_code.nil?
cp = Coupon.find_by_code(coupon_code)
if not cp.nil? and cp.status(user.id) == 'active'
@coupon = cp
total = plan.amount
invoice_items << Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: -(total * cp.percent_off / 100.0).to_i,
currency: Rails.application.secrets.stripe_currency,
description: "coupon #{cp.code} - subscription"
)
else
raise InvalidCouponError
end
end
# only add a wallet invoice item if pay subscription
# dont add if pay subscription + reservation
if invoice
@wallet_amount_debit = get_wallet_amount_debit
if @wallet_amount_debit != 0
Stripe::InvoiceItem.create(
invoice_items << Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: -@wallet_amount_debit,
currency: Rails.application.secrets.stripe_currency,
description: "wallet -#{@wallet_amount_debit / 100.0}"
)
end
unless coupon_code.nil?
cp = Coupon.find_by_code(coupon_code)
total = plan.amount
Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: -(total * cp.percent_off / 100.0).to_i,
currency: Rails.application.secrets.stripe_currency,
description: "coupon #{cp.code}"
)
end
elsif coupon_code != nil
# this case applies if a subscription was took in addition of a reservation, so we create a second
# stripe coupon to apply the discount on the subscription item for the stripe's invoice.
cp = Coupon.find_by_code(coupon_code)
total = plan.amount
Stripe::InvoiceItem.create(
customer: user.stp_customer_id,
amount: -(total * cp.percent_off / 100.0).to_i,
currency: Rails.application.secrets.stripe_currency,
description: "coupon #{cp.code}"
)
end
new_subscription = customer.subscriptions.create(plan: plan.stp_plan_id, source: card_token)
# very important to set expired_at to nil that can allow method is_new? to return true
# for send the notification
# TODO: Refactoring
update_column(:expired_at, nil) unless new_record?
self.stp_subscription_id = new_subscription.id
self.canceled_at = nil
self.expired_at = Time.at(new_subscription.current_period_end)
@ -81,32 +82,38 @@ class Subscription < ActiveRecord::Base
cancel
return true
rescue Stripe::CardError => card_error
clear_wallet_and_goupon_invoice_items(invoice_items)
logger.error card_error
errors[:card] << card_error.message
return false
rescue Stripe::InvalidRequestError => e
clear_wallet_and_goupon_invoice_items(invoice_items)
# Invalid parameters were supplied to Stripe's API
logger.error e
errors[:payment] << e.message
return false
rescue Stripe::AuthenticationError => e
clear_wallet_and_goupon_invoice_items(invoice_items)
# Authentication with Stripe's API failed
# (maybe you changed API keys recently)
logger.error e
errors[:payment] << e.message
return false
rescue Stripe::APIConnectionError => e
clear_wallet_and_goupon_invoice_items(invoice_items)
# Network communication with Stripe failed
logger.error e
errors[:payment] << e.message
return false
rescue Stripe::StripeError => e
clear_wallet_and_goupon_invoice_items(invoice_items)
# Display a very generic error to the user, and maybe send
# yourself an email
logger.error e
errors[:payment] << e.message
return false
rescue => e
clear_wallet_and_goupon_invoice_items(invoice_items)
# Something else happened, completely unrelated to Stripe
logger.error e
errors[:payment] << e.message
@ -117,24 +124,31 @@ class Subscription < ActiveRecord::Base
def save_with_local_payment(invoice = true, coupon_code = nil)
if valid?
@wallet_amount_debit = get_wallet_amount_debit if invoice
# very important to set expired_at to nil that can allow method is_new? to return true
# for send the notification
# TODO: Refactoring
update_column(:expired_at, nil) unless new_record?
self.stp_subscription_id = nil
self.canceled_at = nil
set_expired_at
save!
UsersCredits::Manager.new(user: self.user).reset_credits if expired_date_changed
if invoice
invoc = generate_invoice(nil, coupon_code)
# debit wallet
wallet_transaction = debit_user_wallet
if wallet_transaction
invoc.wallet_amount = @wallet_amount_debit
invoc.wallet_transaction_id = wallet_transaction.id
if save
UsersCredits::Manager.new(user: self.user).reset_credits if expired_date_changed
if invoice
invoc = generate_invoice(nil, coupon_code)
@wallet_amount_debit = get_wallet_amount_debit
# debit wallet
wallet_transaction = debit_user_wallet
if wallet_transaction
invoc.wallet_amount = @wallet_amount_debit
invoc.wallet_transaction_id = wallet_transaction.id
end
invoc.save
end
invoc.save
return true
else
return false
end
return true
else
return false
end
@ -145,9 +159,12 @@ class Subscription < ActiveRecord::Base
total = plan.amount
unless coupon_code.nil?
coupon = Coupon.find_by_code(coupon_code)
coupon_id = coupon.id
total = plan.amount - (plan.amount * coupon.percent_off / 100.0)
cp = Coupon.find_by_code(coupon_code)
if not cp.nil? and cp.status(user.id) == 'active'
@coupon = cp
coupon_id = cp.id
total = plan.amount - (plan.amount * cp.percent_off / 100.0)
end
end
invoice = Invoice.new(invoiced_id: id, invoiced_type: 'Subscription', user: user, total: total, stp_invoice_id: stp_invoice_id, coupon_id: coupon_id)
@ -275,6 +292,9 @@ class Subscription < ActiveRecord::Base
def get_wallet_amount_debit
total = plan.amount
if @coupon
total = (total - (total * @coupon.percent_off / 100.0)).to_i
end
wallet_amount = (user.wallet.amount * 100).to_i
return wallet_amount >= total ? total : wallet_amount
end
@ -285,4 +305,20 @@ class Subscription < ActiveRecord::Base
return WalletService.new(user: user, wallet: user.wallet).debit(amount, self)
end
end
def clear_wallet_and_goupon_invoice_items(invoice_items)
begin
invoice_items.each(&:delete)
rescue Stripe::InvalidRequestError => e
logger.error e
rescue Stripe::AuthenticationError => e
logger.error e
rescue Stripe::APIConnectionError => e
logger.error e
rescue Stripe::StripeError => e
logger.error e
rescue => e
logger.error e
end
end
end

View File

@ -234,7 +234,18 @@ class User < ActiveRecord::Base
if parsed[1] == 'user'
self[parsed[2].to_sym]
elsif parsed[1] == 'profile'
self.profile[parsed[2].to_sym]
case sso_mapping
when 'profile.avatar'
self.profile.user_avatar.remote_attachment_url
when 'profile.address'
self.profile.address.address
when 'profile.organization_name'
self.profile.organization.name
when 'profile.organization_address'
self.profile.organization.address.address
else
self.profile[parsed[2].to_sym]
end
end
end
@ -325,6 +336,17 @@ class User < ActiveRecord::Base
end
end
def self.mapping
# we protect some fields as they are designed to be managed by the system and must not be updated externally
blacklist = %w(id encrypted_password reset_password_token reset_password_sent_at remember_created_at
sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip confirmation_token confirmed_at
confirmation_sent_at unconfirmed_email failed_attempts unlock_token locked_at created_at updated_at stp_customer_id slug
provider auth_token merged_at)
User.column_types
.map{|k,v| [k, v.type.to_s]}
.delete_if { |col| blacklist.include?(col[0]) }
end
protected
def confirmation_required?
false

View File

@ -0,0 +1,5 @@
class VersionPolicy < ApplicationPolicy
def show?
user.is_admin?
end
end

View File

@ -1 +1 @@
json.extract! auth_provider, :id, :name, :status, :providable_type
json.extract! auth_provider, :id, :name, :status, :providable_type, :strategy_name

View File

@ -1,9 +1,4 @@
# we protect some fields are they are designed to be managed by the system and must not be updated externally
json.user User.mapping
json.user User.column_names - %w(id encrypted_password reset_password_token reset_password_sent_at remember_created_at
sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip confirmation_token confirmed_at
confirmation_sent_at unconfirmed_email failed_attempts unlock_token locked_at created_at updated_at stp_customer_id slug
provider auth_token merged_at)
json.profile Profile.column_names - %w(id user_id created_at updated_at) + %w(avatar address organization_name organization_address)
json.profile Profile.mapping

View File

@ -6,7 +6,7 @@ if @provider.providable_type == OAuth2Provider.name
json.providable_attributes do
json.extract! @provider.providable, :id, :base_url, :token_endpoint, :authorization_endpoint, :profile_url, :client_id, :client_secret
json.o_auth2_mappings_attributes @provider.providable.o_auth2_mappings do |m|
json.extract! m, :id, :local_model, :local_field, :api_field, :api_endpoint, :api_data_type
json.extract! m, :id, :local_model, :local_field, :api_field, :api_endpoint, :api_data_type, :transformation
end
end
end

View File

@ -1,3 +1,3 @@
json.cache! @groups do
json.cache! ['v1', @groups] do
json.partial! 'api/groups/group', collection: @groups, as: :group
end

View File

@ -1,5 +1,6 @@
json.extract! @project, :id, :name, :description, :tags, :created_at, :updated_at, :author_id, :licence_id, :slug
json.project_image @project.project_image.attachment.large.url if @project.project_image
json.project_full_image @project.project_image.attachment.url if @project.project_image
json.author do
json.id @project.author_id
json.first_name @project.author.profile.first_name
@ -52,6 +53,7 @@ json.project_steps_attributes @project.project_steps.order('project_steps.step_n
json.title s.title
json.project_step_image s.project_step_image.attachment_identifier if s.project_step_image
json.project_step_image_url s.project_step_image.attachment.medium.url if s.project_step_image
json.project_step_full_image_url s.project_step_image.attachment.url if s.project_step_image
json.step_nb s.step_nb
end
json.state @project.state

View File

@ -101,7 +101,12 @@
</section> <!-- /.vbox -->
<div class="app-generator"><span class="text-sm">Powered by <a href="http://www.fab-manager.com" target="_blank">Fab Manager</a></span></div>
<div class="app-generator">
<span class="app-version" ng-if="currentUser && currentUser.role == 'admin'" uib-tooltip="{{'version' | translate}} {{version.version}}">
<i class="fa fa-question-circle" aria-label="Version ?"></i>
</span>
<span class="text-sm">Powered by <a href="http://www.fab-manager.com" target="_blank">Fab Manager</a></span>
</div>
<%= javascript_include_tag 'application' %>

View File

@ -7,7 +7,7 @@ Devise.setup do |config|
# Devise will use the `secret_key_base` on Rails 4+ applications as its `secret_key`
# by default. You can change it below and use your own secret key.
# config.secret_key = 'f0ad7aadec8086b90c0427e734602262e5d211147f3d93b5b94b5263ffd245e9fd9fcd672dcadea1d9ee2b1bffbf2712cdb013883d66943ef5bed93a263fe11a'
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class

View File

@ -354,6 +354,7 @@ en:
an_error_occurred_and_the_tag_deletion_failed: "An error occurred and the tag deletion failed."
search_for_an_authentication_provider: "Search for an authentication provider"
add_a_new_authentication_provider: "Add a new authentication provider"
strategy_name: "Strategy's name"
state: "State"
unknown: "Unknown: "
active: "Active"

View File

@ -354,6 +354,7 @@ fr:
an_error_occurred_and_the_tag_deletion_failed: "Une erreur est survenue et l'étiquette n'a pas pu être supprimé."
search_for_an_authentication_provider: "Recherchez un fournisseur d'authentification"
add_a_new_authentication_provider: "Ajouter un nouveau fournisseur d'authentification"
strategy_name: "Nom de la stratégie"
state: "État"
unknown: "Inconnu : "
active: "Actif"

View File

@ -100,6 +100,9 @@ en:
your_email_address_is_unknown: "Your e-mail address is unknown."
you_will_receive_in_a_moment_an_email_with_instructions_to_reset_your_password: "You will receive in a moment, an e-mail with instructions to reset your password."
# Fab-manager's version
version: "Version:"
about:
# about page
read_the_fablab_policy: "Read the FabLab policy"

View File

@ -100,6 +100,8 @@ fr:
your_email_address_is_unknown: "Votre adresse de courriel est inconnue."
you_will_receive_in_a_moment_an_email_with_instructions_to_reset_your_password: "Vous allez recevoir sous quelques minutes un courriel vous indiquant comment réinitialiser votre mot de passe."
# Fab-manager's version
version: "Version :"
about:
# page à propos
read_the_fablab_policy: "Consulter les règles d'utilisation du Fab Lab"

View File

@ -248,6 +248,10 @@ en:
provider_name_is_required: "Provider name is required."
authentication_type: "Authentication type"
authentication_type_is_required: "Authentication type is required."
data_mapping: "Data mapping"
expected_data_type: "Expected data type"
input_format: "Input format"
mappings: "Mappings"
oauth2:
# edition/creation form of an OAuth2 authentication provider

View File

@ -248,6 +248,10 @@ fr:
provider_name_is_required: "Le nom du fournisseur est requis."
authentication_type: "Type d'authentification"
authentication_type_is_required: "Le type d'authentification est requis."
data_mapping: "Correspondance des données"
expected_data_type: "Type de données attendues"
input_format: "Format d'entrée"
mappings: "Correspondances"
oauth2:
# formulaire d'édition/création d'un fournisseur d'authentification de type OAuth2

View File

@ -214,7 +214,7 @@ en:
is_changing_its_auth_system_and_will_now_use: "is actually changing its user identification system and will use"
instead_of: "instead of"
consequence_of_the_modification: "Because of this change you won't be able to login to the website with your actual usernames"
to_use_the_platform_thanks_for: "to keep on using the website, please"
to_use_the_platform_thanks_for: "To keep on using the website, please"
create_an_account_on: "create an account on"
or_use_an_existing_account_clicking_here: "or use an existing account by clicking here"
in_case_of_problem_enter_the_following_code: "In case of problem with this link, you can enter the following code at your first connection attempt in order to migrate your actual account into the new authentification system:"

View File

@ -126,6 +126,9 @@ Rails.application.routes.draw do
# XLSX exports
get 'exports/:id/download' => 'exports#download'
post 'exports/status' => 'exports#status'
# Fab-manager's version
get 'version' => 'version#show'
end
# open_api

View File

@ -0,0 +1,5 @@
class AddTransformationToOAuth2Mapping < ActiveRecord::Migration
def change
add_column :o_auth2_mappings, :transformation, :jsonb
end
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160906145713) do
ActiveRecord::Schema.define(version: 20160915105234) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -305,6 +305,7 @@ ActiveRecord::Schema.define(version: 20160906145713) do
t.string "local_model"
t.string "api_endpoint"
t.string "api_data_type"
t.jsonb "transformation"
end
add_index "o_auth2_mappings", ["o_auth2_provider_id"], name: "index_o_auth2_mappings_on_o_auth2_provider_id", using: :btree

View File

@ -12,8 +12,8 @@
<!-- _diagram_info -->
<g id="node1" class="node"><title>_diagram_info</title>
<text text-anchor="start" x="-136" y="-207.6" font-family="Times,serif" font-size="13.00">Controllers diagram</text>
<text text-anchor="start" x="-136" y="-193.6" font-family="Times,serif" font-size="13.00">Date: Aug 31 2016 &#45; 12:07</text>
<text text-anchor="start" x="-136" y="-179.6" font-family="Times,serif" font-size="13.00">Migration version: 20160831084519</text>
<text text-anchor="start" x="-136" y="-193.6" font-family="Times,serif" font-size="13.00">Date: Sep 15 2016 &#45; 17:48</text>
<text text-anchor="start" x="-136" y="-179.6" font-family="Times,serif" font-size="13.00">Migration version: 20160915105234</text>
<text text-anchor="start" x="-136" y="-165.6" font-family="Times,serif" font-size="13.00">Generated by RailRoady 1.4.0</text>
<text text-anchor="start" x="-136" y="-151.6" font-family="Times,serif" font-size="13.00">http://railroady.prestonlee.com</text>
</g>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -12,8 +12,8 @@
<!-- _diagram_info -->
<g id="node1" class="node"><title>_diagram_info</title>
<text text-anchor="start" x="654" y="-310.6" font-family="Times,serif" font-size="13.00">Controllers diagram</text>
<text text-anchor="start" x="654" y="-296.6" font-family="Times,serif" font-size="13.00">Date: Aug 31 2016 &#45; 12:07</text>
<text text-anchor="start" x="654" y="-282.6" font-family="Times,serif" font-size="13.00">Migration version: 20160831084519</text>
<text text-anchor="start" x="654" y="-296.6" font-family="Times,serif" font-size="13.00">Date: Sep 15 2016 &#45; 17:48</text>
<text text-anchor="start" x="654" y="-282.6" font-family="Times,serif" font-size="13.00">Migration version: 20160915105234</text>
<text text-anchor="start" x="654" y="-268.6" font-family="Times,serif" font-size="13.00">Generated by RailRoady 1.4.0</text>
<text text-anchor="start" x="654" y="-254.6" font-family="Times,serif" font-size="13.00">http://railroady.prestonlee.com</text>
</g>

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@ -4,16 +4,16 @@
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: models_diagram Pages: 1 -->
<svg width="5469pt" height="782pt"
viewBox="0.00 0.00 5468.75 782.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="5366pt" height="782pt"
viewBox="0.00 0.00 5365.75 782.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 778)">
<title>models_diagram</title>
<polygon fill="none" stroke="none" points="-4,4 -4,-778 5464.75,-778 5464.75,4 -4,4"/>
<polygon fill="none" stroke="none" points="-4,4 -4,-778 5361.75,-778 5361.75,4 -4,4"/>
<!-- _diagram_info -->
<g id="node1" class="node"><title>_diagram_info</title>
<text text-anchor="start" x="1417" y="-759.6" font-family="Times,serif" font-size="13.00">Models diagram</text>
<text text-anchor="start" x="1417" y="-745.6" font-family="Times,serif" font-size="13.00">Date: Aug 31 2016 &#45; 12:07</text>
<text text-anchor="start" x="1417" y="-731.6" font-family="Times,serif" font-size="13.00">Migration version: 20160831084519</text>
<text text-anchor="start" x="1417" y="-745.6" font-family="Times,serif" font-size="13.00">Date: Sep 15 2016 &#45; 17:48</text>
<text text-anchor="start" x="1417" y="-731.6" font-family="Times,serif" font-size="13.00">Migration version: 20160915105234</text>
<text text-anchor="start" x="1417" y="-717.6" font-family="Times,serif" font-size="13.00">Generated by RailRoady 1.4.0</text>
<text text-anchor="start" x="1417" y="-703.6" font-family="Times,serif" font-size="13.00">http://railroady.prestonlee.com</text>
</g>
@ -29,9 +29,9 @@
</g>
<!-- Group&#45;&gt;Price -->
<g id="edge4" class="edge"><title>Group&#45;&gt;Price</title>
<path fill="none" stroke="#03d34b" d="M1715.11,-730.884C1831.04,-719.622 2160.87,-669.975 2296,-464 2304.78,-450.622 2300.73,-443.284 2296,-428 2287.39,-400.209 2245.03,-337.779 2222,-320 2168.92,-279.021 2141.65,-295.375 2080,-269 2078.84,-268.504 2077.66,-267.986 2076.48,-267.454"/>
<ellipse fill="none" stroke="#03d34b" cx="1710.8" cy="-731.287" rx="4" ry="4"/>
<polygon fill="#03d34b" stroke="#03d34b" points="2076.45,-267.441 2069.32,-259.111 2071.93,-265.312 2067.4,-263.183 2067.4,-263.183 2067.4,-263.183 2071.93,-265.312 2065.49,-267.255 2076.45,-267.441 2076.45,-267.441"/>
<path fill="none" stroke="#006630" d="M1715.11,-730.884C1831.04,-719.622 2160.87,-669.975 2296,-464 2304.78,-450.622 2300.73,-443.284 2296,-428 2287.39,-400.209 2245.03,-337.779 2222,-320 2168.92,-279.021 2141.65,-295.375 2080,-269 2078.84,-268.504 2077.66,-267.986 2076.48,-267.454"/>
<ellipse fill="none" stroke="#006630" cx="1710.8" cy="-731.287" rx="4" ry="4"/>
<polygon fill="#006630" stroke="#006630" points="2076.45,-267.441 2069.32,-259.111 2071.93,-265.312 2067.4,-263.183 2067.4,-263.183 2067.4,-263.183 2071.93,-265.312 2065.49,-267.255 2076.45,-267.441 2076.45,-267.441"/>
<text text-anchor="middle" x="2327.5" y="-496.3" font-family="Times,serif" font-size="14.00">machines_prices</text>
</g>
<!-- TrainingsPricing -->
@ -41,9 +41,9 @@
</g>
<!-- Group&#45;&gt;TrainingsPricing -->
<g id="edge3" class="edge"><title>Group&#45;&gt;TrainingsPricing</title>
<path fill="none" stroke="#413fd3" d="M1685.84,-710.312C1702.88,-673.545 1731.48,-600.276 1724,-536 1721.55,-514.975 1715.96,-491.709 1711.16,-474.24"/>
<ellipse fill="none" stroke="#413fd3" cx="1684.11" cy="-713.971" rx="4.00002" ry="4.00002"/>
<polygon fill="#413fd3" stroke="#413fd3" points="1711.04,-473.804 1712.64,-462.956 1709.67,-468.994 1708.31,-464.183 1708.31,-464.183 1708.31,-464.183 1709.67,-468.994 1703.98,-465.411 1711.04,-473.804 1711.04,-473.804"/>
<path fill="none" stroke="#58cc84" d="M1685.84,-710.312C1702.88,-673.545 1731.48,-600.276 1724,-536 1721.55,-514.975 1715.96,-491.709 1711.16,-474.24"/>
<ellipse fill="none" stroke="#58cc84" cx="1684.11" cy="-713.971" rx="4.00002" ry="4.00002"/>
<polygon fill="#58cc84" stroke="#58cc84" points="1711.04,-473.804 1712.64,-462.956 1709.67,-468.994 1708.31,-464.183 1708.31,-464.183 1708.31,-464.183 1709.67,-468.994 1703.98,-465.411 1711.04,-473.804 1711.04,-473.804"/>
</g>
<!-- Plan -->
<g id="node34" class="node"><title>Plan</title>
@ -52,9 +52,9 @@
</g>
<!-- Group&#45;&gt;Plan -->
<g id="edge1" class="edge"><title>Group&#45;&gt;Plan</title>
<path fill="none" stroke="#d5a4a0" d="M1653.27,-712.806C1632.95,-691.087 1605,-658.264 1605,-642 1605,-642 1605,-642 1605,-445 1605,-361.586 1731.68,-343.615 1796.6,-339.882"/>
<ellipse fill="none" stroke="#d5a4a0" cx="1656.28" cy="-715.983" rx="4.00002" ry="4.00002"/>
<polygon fill="#d5a4a0" stroke="#d5a4a0" points="1796.84,-339.87 1807.05,-343.877 1801.84,-339.626 1806.83,-339.382 1806.83,-339.382 1806.83,-339.382 1801.84,-339.626 1806.61,-334.888 1796.84,-339.87 1796.84,-339.87"/>
<path fill="none" stroke="#11750a" d="M1653.27,-712.806C1632.95,-691.087 1605,-658.264 1605,-642 1605,-642 1605,-642 1605,-445 1605,-361.586 1731.68,-343.615 1796.6,-339.882"/>
<ellipse fill="none" stroke="#11750a" cx="1656.28" cy="-715.983" rx="4.00002" ry="4.00002"/>
<polygon fill="#11750a" stroke="#11750a" points="1796.84,-339.87 1807.05,-343.877 1801.84,-339.626 1806.83,-339.382 1806.83,-339.382 1806.83,-339.382 1801.84,-339.626 1806.61,-334.888 1796.84,-339.87 1796.84,-339.87"/>
</g>
<!-- User -->
<g id="node41" class="node"><title>User</title>
@ -63,20 +63,20 @@
</g>
<!-- Group&#45;&gt;User -->
<g id="edge2" class="edge"><title>Group&#45;&gt;User</title>
<path fill="none" stroke="#680b0c" d="M1655.09,-712.48C1648.43,-706.183 1640.46,-699.94 1632,-696 1568.68,-666.524 1359.68,-649.961 1274.07,-644.271"/>
<ellipse fill="none" stroke="#680b0c" cx="1658" cy="-715.387" rx="4.00002" ry="4.00002"/>
<polygon fill="#680b0c" stroke="#680b0c" points="1274,-644.266 1264.31,-639.125 1269.01,-643.941 1264.02,-643.615 1264.02,-643.615 1264.02,-643.615 1269.01,-643.941 1263.72,-648.106 1274,-644.266 1274,-644.266"/>
<path fill="none" stroke="#329972" d="M1655.09,-712.48C1648.43,-706.183 1640.46,-699.94 1632,-696 1568.68,-666.524 1359.68,-649.961 1274.07,-644.271"/>
<ellipse fill="none" stroke="#329972" cx="1658" cy="-715.387" rx="4.00002" ry="4.00002"/>
<polygon fill="#329972" stroke="#329972" points="1274,-644.266 1264.31,-639.125 1269.01,-643.941 1264.02,-643.615 1264.02,-643.615 1264.02,-643.615 1269.01,-643.941 1263.72,-648.106 1274,-644.266 1274,-644.266"/>
</g>
<!-- InvoiceItem -->
<g id="node3" class="node"><title>InvoiceItem</title>
<ellipse fill="none" stroke="black" cx="1703" cy="-18" rx="53.8905" ry="18"/>
<text text-anchor="middle" x="1703" y="-14.3" font-family="Times,serif" font-size="14.00">InvoiceItem</text>
<ellipse fill="none" stroke="black" cx="1553" cy="-18" rx="53.8905" ry="18"/>
<text text-anchor="middle" x="1553" y="-14.3" font-family="Times,serif" font-size="14.00">InvoiceItem</text>
</g>
<!-- InvoiceItem&#45;&gt;InvoiceItem -->
<g id="edge5" class="edge"><title>InvoiceItem&#45;&gt;InvoiceItem</title>
<path fill="none" stroke="#147835" d="M1761.5,-24.0146C1769.56,-23.0195 1774.95,-21.0146 1774.95,-18 1774.95,-14.9854 1769.56,-12.9805 1761.5,-11.9854"/>
<ellipse fill="none" stroke="#147835" cx="1757.42" cy="-24.3334" rx="4" ry="4"/>
<ellipse fill="#147835" stroke="#147835" cx="1757.42" cy="-11.6666" rx="4" ry="4"/>
<path fill="none" stroke="#31cfee" d="M1611.5,-24.0146C1619.56,-23.0195 1624.95,-21.0146 1624.95,-18 1624.95,-14.9854 1619.56,-12.9805 1611.5,-11.9854"/>
<ellipse fill="none" stroke="#31cfee" cx="1607.42" cy="-24.3334" rx="4" ry="4"/>
<ellipse fill="#31cfee" stroke="#31cfee" cx="1607.42" cy="-11.6666" rx="4" ry="4"/>
</g>
<!-- AvailabilityTag -->
<g id="node5" class="node"><title>AvailabilityTag</title>
@ -85,8 +85,8 @@
</g>
<!-- OpenAPI -->
<g id="node6" class="node"><title>OpenAPI</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="2583,-753 2515,-753 2515,-717 2583,-717 2583,-753"/>
<text text-anchor="middle" x="2549" y="-731.3" font-family="Times,serif" font-size="14.00">OpenAPI</text>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="2640,-753 2572,-753 2572,-717 2640,-717 2640,-753"/>
<text text-anchor="middle" x="2606" y="-731.3" font-family="Times,serif" font-size="14.00">OpenAPI</text>
</g>
<!-- TrainingImage -->
<g id="node7" class="node"><title>TrainingImage</title>
@ -95,24 +95,24 @@
</g>
<!-- OpenAPI::Client -->
<g id="node8" class="node"><title>OpenAPI::Client</title>
<ellipse fill="none" stroke="black" cx="3010" cy="-735" rx="70.3881" ry="18"/>
<text text-anchor="middle" x="3010" y="-731.3" font-family="Times,serif" font-size="14.00">OpenAPI::Client</text>
<ellipse fill="none" stroke="black" cx="2962" cy="-735" rx="70.3881" ry="18"/>
<text text-anchor="middle" x="2962" y="-731.3" font-family="Times,serif" font-size="14.00">OpenAPI::Client</text>
</g>
<!-- OpenAPI::CallsCountTracing -->
<g id="node9" class="node"><title>OpenAPI::CallsCountTracing</title>
<ellipse fill="none" stroke="black" cx="3010" cy="-641" rx="115.88" ry="18"/>
<text text-anchor="middle" x="3010" y="-637.3" font-family="Times,serif" font-size="14.00">OpenAPI::CallsCountTracing</text>
<ellipse fill="none" stroke="black" cx="2962" cy="-641" rx="115.88" ry="18"/>
<text text-anchor="middle" x="2962" y="-637.3" font-family="Times,serif" font-size="14.00">OpenAPI::CallsCountTracing</text>
</g>
<!-- OpenAPI::Client&#45;&gt;OpenAPI::CallsCountTracing -->
<g id="edge6" class="edge"><title>OpenAPI::Client&#45;&gt;OpenAPI::CallsCountTracing</title>
<path fill="none" stroke="#fedab6" d="M3010,-708.451C3010,-696.315 3010,-681.795 3010,-669.427"/>
<ellipse fill="none" stroke="#fedab6" cx="3010" cy="-712.696" rx="4" ry="4"/>
<polygon fill="#fedab6" stroke="#fedab6" points="3010,-669.227 3014.5,-659.227 3010,-664.227 3010,-659.227 3010,-659.227 3010,-659.227 3010,-664.227 3005.5,-659.227 3010,-669.227 3010,-669.227"/>
<path fill="none" stroke="#b4eee0" d="M2962,-708.451C2962,-696.315 2962,-681.795 2962,-669.427"/>
<ellipse fill="none" stroke="#b4eee0" cx="2962" cy="-712.696" rx="4" ry="4"/>
<polygon fill="#b4eee0" stroke="#b4eee0" points="2962,-669.227 2966.5,-659.227 2962,-664.227 2962,-659.227 2962,-659.227 2962,-659.227 2962,-664.227 2957.5,-659.227 2962,-669.227 2962,-669.227"/>
</g>
<!-- OpenAPI::ParameterError -->
<g id="node10" class="node"><title>OpenAPI::ParameterError</title>
<polygon fill="none" stroke="black" points="3305.5,-753 3146.5,-753 3146.5,-717 3305.5,-717 3305.5,-753"/>
<text text-anchor="middle" x="3226" y="-731.3" font-family="Times,serif" font-size="14.00">OpenAPI::ParameterError</text>
<polygon fill="none" stroke="black" points="3212.5,-753 3053.5,-753 3053.5,-717 3212.5,-717 3212.5,-753"/>
<text text-anchor="middle" x="3133" y="-731.3" font-family="Times,serif" font-size="14.00">OpenAPI::ParameterError</text>
</g>
<!-- UserAvatar -->
<g id="node11" class="node"><title>UserAvatar</title>
@ -126,20 +126,20 @@
</g>
<!-- Tag -->
<g id="node13" class="node"><title>Tag</title>
<ellipse fill="none" stroke="black" cx="2214" cy="-735" rx="27" ry="18"/>
<text text-anchor="middle" x="2214" y="-731.3" font-family="Times,serif" font-size="14.00">Tag</text>
<ellipse fill="none" stroke="black" cx="2292" cy="-735" rx="27" ry="18"/>
<text text-anchor="middle" x="2292" y="-731.3" font-family="Times,serif" font-size="14.00">Tag</text>
</g>
<!-- Tag&#45;&gt;AvailabilityTag -->
<g id="edge9" class="edge"><title>Tag&#45;&gt;AvailabilityTag</title>
<path fill="none" stroke="#14982f" d="M2248.25,-729.261C2301.12,-720.915 2404.68,-700.409 2483,-659 2521.24,-638.781 2556.97,-603.238 2578.41,-579.407"/>
<ellipse fill="none" stroke="#14982f" cx="2244.17" cy="-729.89" rx="4.00001" ry="4.00001"/>
<polygon fill="#14982f" stroke="#14982f" points="2578.49,-579.31 2588.48,-574.792 2581.8,-575.562 2585.11,-571.813 2585.11,-571.813 2585.11,-571.813 2581.8,-575.562 2581.74,-568.835 2578.49,-579.31 2578.49,-579.31"/>
<path fill="none" stroke="#5ef550" d="M2324.31,-724.872C2363.52,-713.009 2430.86,-690.077 2483,-659 2514.97,-639.945 2519.35,-629.911 2547,-605 2556.36,-596.571 2566.38,-587.05 2575.11,-578.596"/>
<ellipse fill="none" stroke="#5ef550" cx="2320.22" cy="-726.092" rx="4.00001" ry="4.00001"/>
<polygon fill="#5ef550" stroke="#5ef550" points="2575.24,-578.473 2585.54,-574.717 2578.82,-574.984 2582.4,-571.494 2582.4,-571.494 2582.4,-571.494 2578.82,-574.984 2579.26,-568.271 2575.24,-578.473 2575.24,-578.473"/>
</g>
<!-- Tag&#45;&gt;User -->
<g id="edge8" class="edge"><title>Tag&#45;&gt;User</title>
<path fill="none" stroke="#2040b5" d="M2177.22,-730.537C2022.94,-716.009 1428.81,-660.062 1274.04,-645.488"/>
<polygon fill="#2040b5" stroke="#2040b5" points="2177.4,-730.554 2186.94,-735.972 2182.38,-731.023 2187.36,-731.492 2187.36,-731.492 2187.36,-731.492 2182.38,-731.023 2187.78,-727.011 2177.4,-730.554 2177.4,-730.554"/>
<polygon fill="#2040b5" stroke="#2040b5" points="1274.03,-645.487 1264.5,-640.069 1269.05,-645.018 1264.08,-644.55 1264.08,-644.55 1264.08,-644.55 1269.05,-645.018 1263.65,-649.03 1274.03,-645.487 1274.03,-645.487"/>
<path fill="none" stroke="#63a808" d="M2255.18,-730.79C2092.31,-716.586 1437.41,-659.476 1274.05,-645.231"/>
<polygon fill="#63a808" stroke="#63a808" points="2255.43,-730.811 2265,-736.163 2260.41,-731.245 2265.39,-731.68 2265.39,-731.68 2265.39,-731.68 2260.41,-731.245 2265.78,-727.197 2255.43,-730.811 2255.43,-730.811"/>
<polygon fill="#63a808" stroke="#63a808" points="1273.98,-645.225 1264.41,-639.873 1269,-644.79 1264.02,-644.356 1264.02,-644.356 1264.02,-644.356 1269,-644.79 1263.62,-648.839 1273.98,-645.225 1273.98,-645.225"/>
</g>
<!-- Availability -->
<g id="node53" class="node"><title>Availability</title>
@ -148,9 +148,9 @@
</g>
<!-- Tag&#45;&gt;Availability -->
<g id="edge10" class="edge"><title>Tag&#45;&gt;Availability</title>
<path fill="none" stroke="#2339f9" d="M2245.09,-720.183C2281.27,-704.103 2341.11,-677.505 2380.8,-659.867"/>
<polygon fill="#2339f9" stroke="#2339f9" points="2244.9,-720.267 2233.93,-720.216 2240.33,-722.298 2235.76,-724.328 2235.76,-724.328 2235.76,-724.328 2240.33,-722.298 2237.59,-728.44 2244.9,-720.267 2244.9,-720.267"/>
<polygon fill="#2339f9" stroke="#2339f9" points="2381.04,-659.759 2392.01,-659.809 2385.61,-657.728 2390.18,-655.697 2390.18,-655.697 2390.18,-655.697 2385.61,-657.728 2388.35,-651.585 2381.04,-659.759 2381.04,-659.759"/>
<path fill="none" stroke="#45ee79" d="M2318.2,-715.315C2339.3,-700.27 2368.96,-679.113 2391.01,-663.391"/>
<polygon fill="#45ee79" stroke="#45ee79" points="2318.08,-715.401 2307.32,-717.544 2314.01,-718.305 2309.94,-721.208 2309.94,-721.208 2309.94,-721.208 2314.01,-718.305 2312.55,-724.872 2318.08,-715.401 2318.08,-715.401"/>
<polygon fill="#45ee79" stroke="#45ee79" points="2391.2,-663.251 2401.96,-661.108 2395.27,-660.347 2399.34,-657.444 2399.34,-657.444 2399.34,-657.444 2395.27,-660.347 2396.73,-653.78 2391.2,-663.251 2391.2,-663.251"/>
</g>
<!-- UserTag -->
<g id="node66" class="node"><title>UserTag</title>
@ -159,9 +159,9 @@
</g>
<!-- Tag&#45;&gt;UserTag -->
<g id="edge7" class="edge"><title>Tag&#45;&gt;UserTag</title>
<path fill="none" stroke="#b3a663" d="M2182.61,-723.594C2090.25,-692.979 1819.44,-603.21 1715.38,-568.718"/>
<ellipse fill="none" stroke="#b3a663" cx="2186.65" cy="-724.935" rx="4.00001" ry="4.00001"/>
<polygon fill="#b3a663" stroke="#b3a663" points="1715.34,-568.703 1707.26,-561.285 1710.59,-567.129 1705.85,-565.556 1705.85,-565.556 1705.85,-565.556 1710.59,-567.129 1704.43,-569.828 1715.34,-568.703 1715.34,-568.703"/>
<path fill="none" stroke="#a0a58f" d="M2259.97,-724.724C2157.02,-694.903 1834.4,-601.46 1717.15,-567.497"/>
<ellipse fill="none" stroke="#a0a58f" cx="2263.93" cy="-725.87" rx="4.00001" ry="4.00001"/>
<polygon fill="#a0a58f" stroke="#a0a58f" points="1717.03,-567.464 1708.68,-560.36 1712.23,-566.073 1707.43,-564.682 1707.43,-564.682 1707.43,-564.682 1712.23,-566.073 1706.18,-569.005 1717.03,-567.464 1717.03,-567.464"/>
</g>
<!-- Event -->
<g id="node14" class="node"><title>Event</title>
@ -175,9 +175,9 @@
</g>
<!-- Event&#45;&gt;PriceCategory -->
<g id="edge16" class="edge"><title>Event&#45;&gt;PriceCategory</title>
<path fill="none" stroke="#efc87f" d="M2810.41,-544.337C2836.12,-538.092 2870.52,-528.87 2900,-518 2939.73,-503.352 2983.32,-482.282 3013.41,-466.901"/>
<polygon fill="#efc87f" stroke="#efc87f" points="2810.39,-544.342 2799.61,-542.286 2805.52,-545.503 2800.66,-546.664 2800.66,-546.664 2800.66,-546.664 2805.52,-545.503 2801.7,-551.041 2810.39,-544.342 2810.39,-544.342"/>
<polygon fill="#efc87f" stroke="#efc87f" points="3013.8,-466.703 3024.75,-466.122 3018.24,-464.412 3022.68,-462.122 3022.68,-462.122 3022.68,-462.122 3018.24,-464.412 3020.62,-458.122 3013.8,-466.703 3013.8,-466.703"/>
<path fill="none" stroke="#f73fa0" d="M2810.41,-544.337C2836.12,-538.092 2870.52,-528.87 2900,-518 2939.73,-503.352 2983.32,-482.282 3013.41,-466.901"/>
<polygon fill="#f73fa0" stroke="#f73fa0" points="2810.39,-544.342 2799.61,-542.286 2805.52,-545.503 2800.66,-546.664 2800.66,-546.664 2800.66,-546.664 2805.52,-545.503 2801.7,-551.041 2810.39,-544.342 2810.39,-544.342"/>
<polygon fill="#f73fa0" stroke="#f73fa0" points="3013.8,-466.703 3024.75,-466.122 3018.24,-464.412 3022.68,-462.122 3022.68,-462.122 3022.68,-462.122 3018.24,-464.412 3020.62,-458.122 3013.8,-466.703 3013.8,-466.703"/>
</g>
<!-- EventTheme -->
<g id="node38" class="node"><title>EventTheme</title>
@ -186,9 +186,9 @@
</g>
<!-- Event&#45;&gt;EventTheme -->
<g id="edge14" class="edge"><title>Event&#45;&gt;EventTheme</title>
<path fill="none" stroke="#5ed08a" d="M2746.96,-532.261C2725.19,-514.234 2693.72,-488.172 2671.31,-469.614"/>
<polygon fill="#5ed08a" stroke="#5ed08a" points="2747.04,-532.326 2751.87,-542.17 2750.89,-535.515 2754.74,-538.704 2754.74,-538.704 2754.74,-538.704 2750.89,-535.515 2757.61,-535.239 2747.04,-532.326 2747.04,-532.326"/>
<polygon fill="#5ed08a" stroke="#5ed08a" points="2671.2,-469.524 2666.37,-459.68 2667.35,-466.335 2663.5,-463.146 2663.5,-463.146 2663.5,-463.146 2667.35,-466.335 2660.63,-466.612 2671.2,-469.524 2671.2,-469.524"/>
<path fill="none" stroke="#9f59df" d="M2746.96,-532.261C2725.19,-514.234 2693.72,-488.172 2671.31,-469.614"/>
<polygon fill="#9f59df" stroke="#9f59df" points="2747.04,-532.326 2751.87,-542.17 2750.89,-535.515 2754.74,-538.704 2754.74,-538.704 2754.74,-538.704 2750.89,-535.515 2757.61,-535.239 2747.04,-532.326 2747.04,-532.326"/>
<polygon fill="#9f59df" stroke="#9f59df" points="2671.2,-469.524 2666.37,-459.68 2667.35,-466.335 2663.5,-463.146 2663.5,-463.146 2663.5,-463.146 2667.35,-466.335 2660.63,-466.612 2671.2,-469.524 2671.2,-469.524"/>
</g>
<!-- EventImage -->
<g id="node43" class="node"><title>EventImage</title>
@ -197,9 +197,9 @@
</g>
<!-- Event&#45;&gt;EventImage -->
<g id="edge11" class="edge"><title>Event&#45;&gt;EventImage</title>
<path fill="none" stroke="#9a454c" d="M2772,-527.795C2772,-511.123 2772,-489.335 2772,-472.586"/>
<ellipse fill="none" stroke="#9a454c" cx="2772" cy="-531.969" rx="4" ry="4"/>
<ellipse fill="#9a454c" stroke="#9a454c" cx="2772" cy="-468.341" rx="4" ry="4"/>
<path fill="none" stroke="#a81f13" d="M2772,-527.795C2772,-511.123 2772,-489.335 2772,-472.586"/>
<ellipse fill="none" stroke="#a81f13" cx="2772" cy="-531.969" rx="4" ry="4"/>
<ellipse fill="#a81f13" stroke="#a81f13" cx="2772" cy="-468.341" rx="4" ry="4"/>
</g>
<!-- Reservation -->
<g id="node58" class="node"><title>Reservation</title>
@ -208,9 +208,9 @@
</g>
<!-- Event&#45;&gt;Reservation -->
<g id="edge13" class="edge"><title>Event&#45;&gt;Reservation</title>
<path fill="none" stroke="#a1cece" d="M2735.73,-544.355C2693.35,-532.604 2623.39,-507.851 2579,-464 2550.76,-436.105 2532.21,-393.35 2522.4,-365.782"/>
<ellipse fill="none" stroke="#a1cece" cx="2739.7" cy="-545.426" rx="4.00001" ry="4.00001"/>
<polygon fill="#a1cece" stroke="#a1cece" points="2522.3,-365.486 2523.33,-354.568 2520.69,-360.754 2519.07,-356.022 2519.07,-356.022 2519.07,-356.022 2520.69,-360.754 2514.82,-357.475 2522.3,-365.486 2522.3,-365.486"/>
<path fill="none" stroke="#38da31" d="M2735.73,-544.355C2693.35,-532.604 2623.39,-507.851 2579,-464 2550.76,-436.105 2532.21,-393.35 2522.4,-365.782"/>
<ellipse fill="none" stroke="#38da31" cx="2739.7" cy="-545.426" rx="4.00001" ry="4.00001"/>
<polygon fill="#38da31" stroke="#38da31" points="2522.3,-365.486 2523.33,-354.568 2520.69,-360.754 2519.07,-356.022 2519.07,-356.022 2519.07,-356.022 2520.69,-360.754 2514.82,-357.475 2522.3,-365.486 2522.3,-365.486"/>
</g>
<!-- EventPriceCategory -->
<g id="node64" class="node"><title>EventPriceCategory</title>
@ -219,9 +219,9 @@
</g>
<!-- Event&#45;&gt;EventPriceCategory -->
<g id="edge15" class="edge"><title>Event&#45;&gt;EventPriceCategory</title>
<path fill="none" stroke="#5acf5d" d="M2791.8,-531.281C2806.17,-514.246 2824.81,-489.263 2835,-464 2847.86,-432.116 2852.1,-392.456 2853.45,-366.47"/>
<ellipse fill="none" stroke="#5acf5d" cx="2788.94" cy="-534.597" rx="4.00002" ry="4.00002"/>
<polygon fill="#5acf5d" stroke="#5acf5d" points="2853.46,-366.225 2858.36,-356.417 2853.66,-361.229 2853.87,-356.233 2853.87,-356.233 2853.87,-356.233 2853.66,-361.229 2849.37,-356.049 2853.46,-366.225 2853.46,-366.225"/>
<path fill="none" stroke="#c7e71d" d="M2791.8,-531.281C2806.17,-514.246 2824.81,-489.263 2835,-464 2847.86,-432.116 2852.1,-392.456 2853.45,-366.47"/>
<ellipse fill="none" stroke="#c7e71d" cx="2788.94" cy="-534.597" rx="4.00002" ry="4.00002"/>
<polygon fill="#c7e71d" stroke="#c7e71d" points="2853.46,-366.225 2858.36,-356.417 2853.66,-361.229 2853.87,-356.233 2853.87,-356.233 2853.87,-356.233 2853.66,-361.229 2849.37,-356.049 2853.46,-366.225 2853.46,-366.225"/>
</g>
<!-- EventFile -->
<g id="node65" class="node"><title>EventFile</title>
@ -230,36 +230,36 @@
</g>
<!-- Event&#45;&gt;EventFile -->
<g id="edge12" class="edge"><title>Event&#45;&gt;EventFile</title>
<path fill="none" stroke="#85104b" d="M2808.6,-544.58C2827.49,-539.064 2850.23,-530.512 2868,-518 2885.31,-505.812 2900.46,-487.302 2911.08,-472.237"/>
<ellipse fill="none" stroke="#85104b" cx="2804.62" cy="-545.689" rx="4.00001" ry="4.00001"/>
<polygon fill="#85104b" stroke="#85104b" points="2911.16,-472.109 2920.51,-466.368 2913.97,-467.974 2916.78,-463.838 2916.78,-463.838 2916.78,-463.838 2913.97,-467.974 2913.06,-461.309 2911.16,-472.109 2911.16,-472.109"/>
<path fill="none" stroke="#b901f0" d="M2808.6,-544.58C2827.49,-539.064 2850.23,-530.512 2868,-518 2885.31,-505.812 2900.46,-487.302 2911.08,-472.237"/>
<ellipse fill="none" stroke="#b901f0" cx="2804.62" cy="-545.689" rx="4.00001" ry="4.00001"/>
<polygon fill="#b901f0" stroke="#b901f0" points="2911.16,-472.109 2920.51,-466.368 2913.97,-467.974 2916.78,-463.838 2916.78,-463.838 2916.78,-463.838 2913.97,-467.974 2913.06,-461.309 2911.16,-472.109 2911.16,-472.109"/>
</g>
<!-- StatisticSubType -->
<g id="node15" class="node"><title>StatisticSubType</title>
<ellipse fill="none" stroke="black" cx="3418" cy="-735" rx="70.6878" ry="18"/>
<text text-anchor="middle" x="3418" y="-731.3" font-family="Times,serif" font-size="14.00">StatisticSubType</text>
<ellipse fill="none" stroke="black" cx="3305" cy="-735" rx="70.6878" ry="18"/>
<text text-anchor="middle" x="3305" y="-731.3" font-family="Times,serif" font-size="14.00">StatisticSubType</text>
</g>
<!-- StatisticType -->
<g id="node32" class="node"><title>StatisticType</title>
<ellipse fill="none" stroke="black" cx="3355" cy="-641" rx="57.3905" ry="18"/>
<text text-anchor="middle" x="3355" y="-637.3" font-family="Times,serif" font-size="14.00">StatisticType</text>
<ellipse fill="none" stroke="black" cx="3327" cy="-641" rx="57.3905" ry="18"/>
<text text-anchor="middle" x="3327" y="-637.3" font-family="Times,serif" font-size="14.00">StatisticType</text>
</g>
<!-- StatisticSubType&#45;&gt;StatisticType -->
<g id="edge18" class="edge"><title>StatisticSubType&#45;&gt;StatisticType</title>
<path fill="none" stroke="#cb62c0" d="M3400.73,-708.781C3391.87,-695.848 3381.12,-680.14 3372.26,-667.208"/>
<polygon fill="#cb62c0" stroke="#cb62c0" points="3400.79,-708.875 3402.73,-719.668 3403.62,-713 3406.44,-717.126 3406.44,-717.126 3406.44,-717.126 3403.62,-713 3410.16,-714.583 3400.79,-708.875 3400.79,-708.875"/>
<polygon fill="#cb62c0" stroke="#cb62c0" points="3372.13,-667.018 3370.19,-656.225 3369.31,-662.893 3366.48,-658.767 3366.48,-658.767 3366.48,-658.767 3369.31,-662.893 3362.77,-661.31 3372.13,-667.018 3372.13,-667.018"/>
<path fill="none" stroke="#ef9784" d="M3311.53,-706.691C3314.38,-694.795 3317.7,-680.889 3320.54,-669.025"/>
<polygon fill="#ef9784" stroke="#ef9784" points="3311.46,-706.97 3304.76,-715.649 3310.3,-711.833 3309.14,-716.696 3309.14,-716.696 3309.14,-716.696 3310.3,-711.833 3313.51,-717.742 3311.46,-706.97 3311.46,-706.97"/>
<polygon fill="#ef9784" stroke="#ef9784" points="3320.55,-668.953 3327.26,-660.274 3321.72,-664.09 3322.88,-659.227 3322.88,-659.227 3322.88,-659.227 3321.72,-664.09 3318.5,-658.18 3320.55,-668.953 3320.55,-668.953"/>
</g>
<!-- StatisticTypeSubType -->
<g id="node76" class="node"><title>StatisticTypeSubType</title>
<ellipse fill="none" stroke="black" cx="3495" cy="-554" rx="89.0842" ry="18"/>
<text text-anchor="middle" x="3495" y="-550.3" font-family="Times,serif" font-size="14.00">StatisticTypeSubType</text>
<ellipse fill="none" stroke="black" cx="3161" cy="-554" rx="89.0842" ry="18"/>
<text text-anchor="middle" x="3161" y="-550.3" font-family="Times,serif" font-size="14.00">StatisticTypeSubType</text>
</g>
<!-- StatisticSubType&#45;&gt;StatisticTypeSubType -->
<g id="edge17" class="edge"><title>StatisticSubType&#45;&gt;StatisticTypeSubType</title>
<path fill="none" stroke="#f79830" d="M3428.74,-709.024C3443.2,-675.414 3468.81,-615.885 3483.6,-581.507"/>
<ellipse fill="none" stroke="#f79830" cx="3426.96" cy="-713.162" rx="4.00001" ry="4.00001"/>
<polygon fill="#f79830" stroke="#f79830" points="3483.69,-581.297 3491.77,-573.89 3485.66,-576.704 3487.64,-572.111 3487.64,-572.111 3487.64,-572.111 3485.66,-576.704 3483.51,-570.333 3483.69,-581.297 3483.69,-581.297"/>
<path fill="none" stroke="#b88034" d="M3286.29,-710.739C3259.17,-677.032 3209.15,-614.853 3181.21,-580.128"/>
<ellipse fill="none" stroke="#b88034" cx="3288.95" cy="-714.043" rx="4.00002" ry="4.00002"/>
<polygon fill="#b88034" stroke="#b88034" points="3180.88,-579.717 3178.12,-569.105 3177.75,-575.821 3174.62,-571.926 3174.62,-571.926 3174.62,-571.926 3177.75,-575.821 3171.11,-574.746 3180.88,-579.717 3180.88,-579.717"/>
</g>
<!-- Project -->
<g id="node16" class="node"><title>Project</title>
@ -268,15 +268,15 @@
</g>
<!-- Project&#45;&gt;ProjectImage -->
<g id="edge19" class="edge"><title>Project&#45;&gt;ProjectImage</title>
<path fill="none" stroke="#fe5da0" d="M882.033,-533.098C904.327,-514.636 937.409,-487.239 960.24,-468.332"/>
<ellipse fill="none" stroke="#fe5da0" cx="878.879" cy="-535.71" rx="4.00002" ry="4.00002"/>
<ellipse fill="#fe5da0" stroke="#fe5da0" cx="963.6" cy="-465.55" rx="4.00002" ry="4.00002"/>
<path fill="none" stroke="#ac40b3" d="M882.033,-533.098C904.327,-514.636 937.409,-487.239 960.24,-468.332"/>
<ellipse fill="none" stroke="#ac40b3" cx="878.879" cy="-535.71" rx="4.00002" ry="4.00002"/>
<ellipse fill="#ac40b3" stroke="#ac40b3" cx="963.6" cy="-465.55" rx="4.00002" ry="4.00002"/>
</g>
<!-- Project&#45;&gt;User -->
<g id="edge25" class="edge"><title>Project&#45;&gt;User</title>
<path fill="none" stroke="#bee553" d="M886.916,-574.853C903.947,-585.553 926.339,-597.97 948,-605 1034.94,-633.214 1143.27,-639.032 1199.38,-640.016"/>
<polygon fill="#bee553" stroke="#bee553" points="886.448,-574.551 880.485,-565.348 882.247,-571.84 878.045,-569.129 878.045,-569.129 878.045,-569.129 882.247,-571.84 875.606,-572.911 886.448,-574.551 886.448,-574.551"/>
<polygon fill="#bee553" stroke="#bee553" points="1199.56,-640.019 1209.5,-644.651 1204.56,-640.085 1209.56,-640.151 1209.56,-640.151 1209.56,-640.151 1204.56,-640.085 1209.62,-635.652 1199.56,-640.019 1199.56,-640.019"/>
<path fill="none" stroke="#1a1cdd" d="M886.916,-574.853C903.947,-585.553 926.339,-597.97 948,-605 1034.94,-633.214 1143.27,-639.032 1199.38,-640.016"/>
<polygon fill="#1a1cdd" stroke="#1a1cdd" points="886.448,-574.551 880.485,-565.348 882.247,-571.84 878.045,-569.129 878.045,-569.129 878.045,-569.129 882.247,-571.84 875.606,-572.911 886.448,-574.551 886.448,-574.551"/>
<polygon fill="#1a1cdd" stroke="#1a1cdd" points="1199.56,-640.019 1209.5,-644.651 1204.56,-640.085 1209.56,-640.151 1209.56,-640.151 1209.56,-640.151 1204.56,-640.085 1209.62,-635.652 1199.56,-640.019 1199.56,-640.019"/>
</g>
<!-- Theme -->
<g id="node47" class="node"><title>Theme</title>
@ -285,9 +285,9 @@
</g>
<!-- Project&#45;&gt;Theme -->
<g id="edge23" class="edge"><title>Project&#45;&gt;Theme</title>
<path fill="none" stroke="#dc52d6" d="M821.856,-537.867C807.782,-531.848 791.565,-524.757 777,-518 739.048,-500.394 696.138,-478.867 667.31,-464.164"/>
<polygon fill="#dc52d6" stroke="#dc52d6" points="822.008,-537.932 829.449,-545.986 826.609,-539.888 831.21,-541.845 831.21,-541.845 831.21,-541.845 826.609,-539.888 832.971,-537.704 822.008,-537.932 822.008,-537.932"/>
<polygon fill="#dc52d6" stroke="#dc52d6" points="667.004,-464.007 660.15,-455.448 662.553,-461.731 658.101,-459.454 658.101,-459.454 658.101,-459.454 662.553,-461.731 656.052,-463.461 667.004,-464.007 667.004,-464.007"/>
<path fill="none" stroke="#8e0c53" d="M821.856,-537.867C807.782,-531.848 791.565,-524.757 777,-518 739.048,-500.394 696.138,-478.867 667.31,-464.164"/>
<polygon fill="#8e0c53" stroke="#8e0c53" points="822.008,-537.932 829.449,-545.986 826.609,-539.888 831.21,-541.845 831.21,-541.845 831.21,-541.845 826.609,-539.888 832.971,-537.704 822.008,-537.932 822.008,-537.932"/>
<polygon fill="#8e0c53" stroke="#8e0c53" points="667.004,-464.007 660.15,-455.448 662.553,-461.731 658.101,-459.454 658.101,-459.454 658.101,-459.454 662.553,-461.731 656.052,-463.461 667.004,-464.007 667.004,-464.007"/>
</g>
<!-- ProjectCao -->
<g id="node48" class="node"><title>ProjectCao</title>
@ -296,9 +296,9 @@
</g>
<!-- Project&#45;&gt;ProjectCao -->
<g id="edge20" class="edge"><title>Project&#45;&gt;ProjectCao</title>
<path fill="none" stroke="#f8092e" d="M834.909,-532.603C814.512,-514.585 784.809,-488.348 763.672,-469.677"/>
<ellipse fill="none" stroke="#f8092e" cx="838.064" cy="-535.389" rx="4.00002" ry="4.00002"/>
<polygon fill="#f8092e" stroke="#f8092e" points="763.523,-469.545 759.007,-459.552 759.775,-466.235 756.028,-462.925 756.028,-462.925 756.028,-462.925 759.775,-466.235 753.049,-466.297 763.523,-469.545 763.523,-469.545"/>
<path fill="none" stroke="#327797" d="M834.909,-532.603C814.512,-514.585 784.809,-488.348 763.672,-469.677"/>
<ellipse fill="none" stroke="#327797" cx="838.064" cy="-535.389" rx="4.00002" ry="4.00002"/>
<polygon fill="#327797" stroke="#327797" points="763.523,-469.545 759.007,-459.552 759.775,-466.235 756.028,-462.925 756.028,-462.925 756.028,-462.925 759.775,-466.235 753.049,-466.297 763.523,-469.545 763.523,-469.545"/>
</g>
<!-- ProjectStep -->
<g id="node57" class="node"><title>ProjectStep</title>
@ -307,9 +307,9 @@
</g>
<!-- Project&#45;&gt;ProjectStep -->
<g id="edge26" class="edge"><title>Project&#45;&gt;ProjectStep</title>
<path fill="none" stroke="#7ed8a1" d="M816.494,-545.566C784.993,-539.459 740.806,-529.892 703,-518 655.491,-503.056 602.773,-480.689 567.951,-465.066"/>
<ellipse fill="none" stroke="#7ed8a1" cx="820.692" cy="-546.368" rx="4.00001" ry="4.00001"/>
<polygon fill="#7ed8a1" stroke="#7ed8a1" points="567.735,-464.968 560.476,-456.749 563.179,-462.909 558.623,-460.849 558.623,-460.849 558.623,-460.849 563.179,-462.909 556.769,-464.95 567.735,-464.968 567.735,-464.968"/>
<path fill="none" stroke="#2e99d6" d="M816.494,-545.566C784.993,-539.459 740.806,-529.892 703,-518 655.491,-503.056 602.773,-480.689 567.951,-465.066"/>
<ellipse fill="none" stroke="#2e99d6" cx="820.692" cy="-546.368" rx="4.00001" ry="4.00001"/>
<polygon fill="#2e99d6" stroke="#2e99d6" points="567.735,-464.968 560.476,-456.749 563.179,-462.909 558.623,-460.849 558.623,-460.849 558.623,-460.849 563.179,-462.909 556.769,-464.95 567.735,-464.968 567.735,-464.968"/>
</g>
<!-- ProjectUser -->
<g id="node74" class="node"><title>ProjectUser</title>
@ -318,133 +318,133 @@
</g>
<!-- Project&#45;&gt;ProjectUser -->
<g id="edge24" class="edge"><title>Project&#45;&gt;ProjectUser</title>
<path fill="none" stroke="#8fa071" d="M814.457,-549.806C763.445,-545.422 676.66,-535.954 604,-518 548.775,-504.355 487.477,-480.7 448.382,-464.471"/>
<ellipse fill="none" stroke="#8fa071" cx="818.649" cy="-550.158" rx="4" ry="4"/>
<polygon fill="#8fa071" stroke="#8fa071" points="448.162,-464.379 440.677,-456.365 443.55,-462.447 438.939,-460.516 438.939,-460.516 438.939,-460.516 443.55,-462.447 437.2,-464.666 448.162,-464.379 448.162,-464.379"/>
<path fill="none" stroke="#45e07f" d="M814.457,-549.806C763.445,-545.422 676.66,-535.954 604,-518 574.417,-510.69 498.943,-482.275 450.753,-463.684"/>
<ellipse fill="none" stroke="#45e07f" cx="818.649" cy="-550.158" rx="4" ry="4"/>
<polygon fill="#45e07f" stroke="#45e07f" points="450.533,-463.599 442.829,-455.794 445.869,-461.795 441.206,-459.991 441.206,-459.991 441.206,-459.991 445.869,-461.795 439.582,-464.188 450.533,-463.599 450.533,-463.599"/>
</g>
<!-- Machine -->
<g id="node82" class="node"><title>Machine</title>
<g id="node83" class="node"><title>Machine</title>
<ellipse fill="none" stroke="black" cx="1909" cy="-446" rx="42.4939" ry="18"/>
<text text-anchor="middle" x="1909" y="-442.3" font-family="Times,serif" font-size="14.00">Machine</text>
</g>
<!-- Project&#45;&gt;Machine -->
<g id="edge21" class="edge"><title>Project&#45;&gt;Machine</title>
<path fill="none" stroke="#87e863" d="M903.626,-549.208C1038.22,-537.892 1445.3,-502.738 1782,-464 1807.6,-461.054 1836.04,-457.293 1859.51,-454.058"/>
<polygon fill="#87e863" stroke="#87e863" points="903.262,-549.238 892.921,-545.59 898.28,-549.656 893.297,-550.075 893.297,-550.075 893.297,-550.075 898.28,-549.656 893.674,-554.559 903.262,-549.238 903.262,-549.238"/>
<polygon fill="#87e863" stroke="#87e863" points="1859.67,-454.036 1870.19,-457.118 1864.62,-453.348 1869.57,-452.66 1869.57,-452.66 1869.57,-452.66 1864.62,-453.348 1868.96,-448.203 1859.67,-454.036 1859.67,-454.036"/>
<path fill="none" stroke="#6b2f6b" d="M903.626,-549.208C1038.22,-537.892 1445.3,-502.738 1782,-464 1807.6,-461.054 1836.04,-457.293 1859.51,-454.058"/>
<polygon fill="#6b2f6b" stroke="#6b2f6b" points="903.262,-549.238 892.921,-545.59 898.28,-549.656 893.297,-550.075 893.297,-550.075 893.297,-550.075 898.28,-549.656 893.674,-554.559 903.262,-549.238 903.262,-549.238"/>
<polygon fill="#6b2f6b" stroke="#6b2f6b" points="1859.67,-454.036 1870.19,-457.118 1864.62,-453.348 1869.57,-452.66 1869.57,-452.66 1869.57,-452.66 1864.62,-453.348 1868.96,-448.203 1859.67,-454.036 1859.67,-454.036"/>
</g>
<!-- Component -->
<g id="node84" class="node"><title>Component</title>
<g id="node85" class="node"><title>Component</title>
<ellipse fill="none" stroke="black" cx="858" cy="-446" rx="51.9908" ry="18"/>
<text text-anchor="middle" x="858" y="-442.3" font-family="Times,serif" font-size="14.00">Component</text>
</g>
<!-- Project&#45;&gt;Component -->
<g id="edge22" class="edge"><title>Project&#45;&gt;Component</title>
<path fill="none" stroke="#88f692" d="M858,-525.931C858,-510.187 858,-490.393 858,-474.566"/>
<polygon fill="#88f692" stroke="#88f692" points="858,-525.969 853.5,-535.969 858,-530.969 858,-535.969 858,-535.969 858,-535.969 858,-530.969 862.5,-535.969 858,-525.969 858,-525.969"/>
<polygon fill="#88f692" stroke="#88f692" points="858,-474.341 862.5,-464.341 858,-469.341 858,-464.341 858,-464.341 858,-464.341 858,-469.341 853.5,-464.341 858,-474.341 858,-474.341"/>
<path fill="none" stroke="#c6e330" d="M858,-525.931C858,-510.187 858,-490.393 858,-474.566"/>
<polygon fill="#c6e330" stroke="#c6e330" points="858,-525.969 853.5,-535.969 858,-530.969 858,-535.969 858,-535.969 858,-535.969 858,-530.969 862.5,-535.969 858,-525.969 858,-525.969"/>
<polygon fill="#c6e330" stroke="#c6e330" points="858,-474.341 862.5,-464.341 858,-469.341 858,-464.341 858,-464.341 858,-464.341 858,-469.341 853.5,-464.341 858,-474.341 858,-474.341"/>
</g>
<!-- CustomAsset -->
<g id="node17" class="node"><title>CustomAsset</title>
<ellipse fill="none" stroke="black" cx="3577" cy="-735" rx="57.6901" ry="18"/>
<text text-anchor="middle" x="3577" y="-731.3" font-family="Times,serif" font-size="14.00">CustomAsset</text>
<ellipse fill="none" stroke="black" cx="3474" cy="-735" rx="57.6901" ry="18"/>
<text text-anchor="middle" x="3474" y="-731.3" font-family="Times,serif" font-size="14.00">CustomAsset</text>
</g>
<!-- CustomAssetFile -->
<g id="node85" class="node"><title>CustomAssetFile</title>
<ellipse fill="none" stroke="black" cx="3577" cy="-641" rx="71.4873" ry="18"/>
<text text-anchor="middle" x="3577" y="-637.3" font-family="Times,serif" font-size="14.00">CustomAssetFile</text>
<g id="node86" class="node"><title>CustomAssetFile</title>
<ellipse fill="none" stroke="black" cx="3474" cy="-641" rx="71.4873" ry="18"/>
<text text-anchor="middle" x="3474" y="-637.3" font-family="Times,serif" font-size="14.00">CustomAssetFile</text>
</g>
<!-- CustomAsset&#45;&gt;CustomAssetFile -->
<g id="edge27" class="edge"><title>CustomAsset&#45;&gt;CustomAssetFile</title>
<path fill="none" stroke="#b8b65d" d="M3577,-708.451C3577,-695.702 3577,-680.322 3577,-667.57"/>
<ellipse fill="none" stroke="#b8b65d" cx="3577" cy="-712.696" rx="4" ry="4"/>
<ellipse fill="#b8b65d" stroke="#b8b65d" cx="3577" cy="-663.227" rx="4" ry="4"/>
<path fill="none" stroke="#6fa331" d="M3474,-708.451C3474,-695.702 3474,-680.322 3474,-667.57"/>
<ellipse fill="none" stroke="#6fa331" cx="3474" cy="-712.696" rx="4" ry="4"/>
<ellipse fill="#6fa331" stroke="#6fa331" cx="3474" cy="-663.227" rx="4" ry="4"/>
</g>
<!-- AgeRange -->
<g id="node18" class="node"><title>AgeRange</title>
<ellipse fill="none" stroke="black" cx="2685" cy="-641" rx="48.1917" ry="18"/>
<text text-anchor="middle" x="2685" y="-637.3" font-family="Times,serif" font-size="14.00">AgeRange</text>
<ellipse fill="none" stroke="black" cx="2671" cy="-641" rx="48.1917" ry="18"/>
<text text-anchor="middle" x="2671" y="-637.3" font-family="Times,serif" font-size="14.00">AgeRange</text>
</g>
<!-- AgeRange&#45;&gt;Event -->
<g id="edge28" class="edge"><title>AgeRange&#45;&gt;Event</title>
<path fill="none" stroke="#4efd70" d="M2707.28,-618.234C2720.28,-605.531 2736.63,-589.555 2749.65,-576.839"/>
<ellipse fill="none" stroke="#4efd70" cx="2704.23" cy="-621.217" rx="4.00002" ry="4.00002"/>
<polygon fill="#4efd70" stroke="#4efd70" points="2749.72,-576.767 2760.02,-572.997 2753.3,-573.273 2756.87,-569.779 2756.87,-569.779 2756.87,-569.779 2753.3,-573.273 2753.73,-566.56 2749.72,-576.767 2749.72,-576.767"/>
<path fill="none" stroke="#f20c3b" d="M2696.47,-618.567C2711.96,-605.532 2731.65,-588.957 2747.05,-576.001"/>
<ellipse fill="none" stroke="#f20c3b" cx="2693.06" cy="-621.437" rx="4.00002" ry="4.00002"/>
<polygon fill="#f20c3b" stroke="#f20c3b" points="2747.45,-575.66 2758,-572.664 2751.28,-572.441 2755.1,-569.221 2755.1,-569.221 2755.1,-569.221 2751.28,-572.441 2752.2,-565.778 2747.45,-575.66 2747.45,-575.66"/>
</g>
<!-- Wallet -->
<g id="node19" class="node"><title>Wallet</title>
<ellipse fill="none" stroke="black" cx="362" cy="-500" rx="34.394" ry="18"/>
<text text-anchor="middle" x="362" y="-496.3" font-family="Times,serif" font-size="14.00">Wallet</text>
<ellipse fill="none" stroke="black" cx="340" cy="-500" rx="34.394" ry="18"/>
<text text-anchor="middle" x="340" y="-496.3" font-family="Times,serif" font-size="14.00">Wallet</text>
</g>
<!-- WalletTransaction -->
<g id="node62" class="node"><title>WalletTransaction</title>
<ellipse fill="none" stroke="black" cx="378" cy="-392" rx="76.0865" ry="18"/>
<text text-anchor="middle" x="378" y="-388.3" font-family="Times,serif" font-size="14.00">WalletTransaction</text>
<ellipse fill="none" stroke="black" cx="353" cy="-392" rx="76.0865" ry="18"/>
<text text-anchor="middle" x="353" y="-388.3" font-family="Times,serif" font-size="14.00">WalletTransaction</text>
</g>
<!-- Wallet&#45;&gt;WalletTransaction -->
<g id="edge29" class="edge"><title>Wallet&#45;&gt;WalletTransaction</title>
<path fill="none" stroke="#8cc7c3" d="M350.2,-474.776C345.027,-460.8 341.287,-443.066 347,-428 348.416,-424.264 350.434,-420.671 352.77,-417.304"/>
<ellipse fill="none" stroke="#8cc7c3" cx="351.843" cy="-478.816" rx="4.00001" ry="4.00001"/>
<polygon fill="#8cc7c3" stroke="#8cc7c3" points="352.813,-417.25 362.579,-412.262 355.94,-413.349 359.068,-409.448 359.068,-409.448 359.068,-409.448 355.94,-413.349 355.556,-406.633 352.813,-417.25 352.813,-417.25"/>
<path fill="none" stroke="#b0417b" d="M342.079,-473.39C343.29,-459.865 344.977,-443.003 347,-428 347.346,-425.434 347.74,-422.768 348.157,-420.103"/>
<ellipse fill="none" stroke="#b0417b" cx="341.7" cy="-477.759" rx="4" ry="4"/>
<polygon fill="#b0417b" stroke="#b0417b" points="348.188,-419.917 354.264,-410.789 349.006,-414.985 349.825,-410.052 349.825,-410.052 349.825,-410.052 349.006,-414.985 345.386,-409.315 348.188,-419.917 348.188,-419.917"/>
</g>
<!-- Stats::Event -->
<g id="node20" class="node"><title>Stats::Event</title>
<polygon fill="none" stroke="black" points="3735,-753 3653,-753 3653,-717 3735,-717 3735,-753"/>
<text text-anchor="middle" x="3694" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Event</text>
<polygon fill="none" stroke="black" points="3632,-753 3550,-753 3550,-717 3632,-717 3632,-753"/>
<text text-anchor="middle" x="3591" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Event</text>
</g>
<!-- Stats::Project -->
<g id="node21" class="node"><title>Stats::Project</title>
<polygon fill="none" stroke="black" points="3842.5,-753 3753.5,-753 3753.5,-717 3842.5,-717 3842.5,-753"/>
<text text-anchor="middle" x="3798" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Project</text>
<polygon fill="none" stroke="black" points="3739.5,-753 3650.5,-753 3650.5,-717 3739.5,-717 3739.5,-753"/>
<text text-anchor="middle" x="3695" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Project</text>
</g>
<!-- Stats::User -->
<g id="node22" class="node"><title>Stats::User</title>
<polygon fill="none" stroke="black" points="3937,-753 3861,-753 3861,-717 3937,-717 3937,-753"/>
<text text-anchor="middle" x="3899" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::User</text>
<polygon fill="none" stroke="black" points="3834,-753 3758,-753 3758,-717 3834,-717 3834,-753"/>
<text text-anchor="middle" x="3796" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::User</text>
</g>
<!-- Stats::Subscription -->
<g id="node23" class="node"><title>Stats::Subscription</title>
<polygon fill="none" stroke="black" points="4074.5,-753 3955.5,-753 3955.5,-717 4074.5,-717 4074.5,-753"/>
<text text-anchor="middle" x="4015" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Subscription</text>
<polygon fill="none" stroke="black" points="3971.5,-753 3852.5,-753 3852.5,-717 3971.5,-717 3971.5,-753"/>
<text text-anchor="middle" x="3912" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Subscription</text>
</g>
<!-- Stats::Training -->
<g id="node24" class="node"><title>Stats::Training</title>
<polygon fill="none" stroke="black" points="4189.5,-753 4092.5,-753 4092.5,-717 4189.5,-717 4189.5,-753"/>
<text text-anchor="middle" x="4141" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Training</text>
<polygon fill="none" stroke="black" points="4086.5,-753 3989.5,-753 3989.5,-717 4086.5,-717 4086.5,-753"/>
<text text-anchor="middle" x="4038" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Training</text>
</g>
<!-- Stats::Account -->
<g id="node25" class="node"><title>Stats::Account</title>
<polygon fill="none" stroke="black" points="4304,-753 4208,-753 4208,-717 4304,-717 4304,-753"/>
<text text-anchor="middle" x="4256" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Account</text>
<polygon fill="none" stroke="black" points="4201,-753 4105,-753 4105,-717 4201,-717 4201,-753"/>
<text text-anchor="middle" x="4153" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Account</text>
</g>
<!-- Stats::Machine -->
<g id="node26" class="node"><title>Stats::Machine</title>
<polygon fill="none" stroke="black" points="4420,-753 4322,-753 4322,-717 4420,-717 4420,-753"/>
<text text-anchor="middle" x="4371" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Machine</text>
<polygon fill="none" stroke="black" points="4317,-753 4219,-753 4219,-717 4317,-717 4317,-753"/>
<text text-anchor="middle" x="4268" y="-731.3" font-family="Times,serif" font-size="14.00">Stats::Machine</text>
</g>
<!-- PriceCategory&#45;&gt;EventPriceCategory -->
<g id="edge30" class="edge"><title>PriceCategory&#45;&gt;EventPriceCategory</title>
<path fill="none" stroke="#a626df" d="M3015.52,-425.91C2980.87,-407.265 2928.28,-378.967 2892.6,-359.767"/>
<ellipse fill="none" stroke="#a626df" cx="3019.25" cy="-427.917" rx="4.00002" ry="4.00002"/>
<polygon fill="#a626df" stroke="#a626df" points="2892.27,-359.59 2885.59,-350.889 2887.86,-357.221 2883.46,-354.851 2883.46,-354.851 2883.46,-354.851 2887.86,-357.221 2881.33,-358.814 2892.27,-359.59 2892.27,-359.59"/>
<path fill="none" stroke="#7b3b88" d="M3015.52,-425.91C2980.87,-407.265 2928.28,-378.967 2892.6,-359.767"/>
<ellipse fill="none" stroke="#7b3b88" cx="3019.25" cy="-427.917" rx="4.00002" ry="4.00002"/>
<polygon fill="#7b3b88" stroke="#7b3b88" points="2892.27,-359.59 2885.59,-350.889 2887.86,-357.221 2883.46,-354.851 2883.46,-354.851 2883.46,-354.851 2887.86,-357.221 2881.33,-358.814 2892.27,-359.59 2892.27,-359.59"/>
</g>
<!-- Invoice -->
<g id="node28" class="node"><title>Invoice</title>
<ellipse fill="none" stroke="black" cx="1532" cy="-91" rx="37.0935" ry="18"/>
<text text-anchor="middle" x="1532" y="-87.3" font-family="Times,serif" font-size="14.00">Invoice</text>
<ellipse fill="none" stroke="black" cx="1404" cy="-91" rx="37.0935" ry="18"/>
<text text-anchor="middle" x="1404" y="-87.3" font-family="Times,serif" font-size="14.00">Invoice</text>
</g>
<!-- Invoice&#45;&gt;InvoiceItem -->
<g id="edge31" class="edge"><title>Invoice&#45;&gt;InvoiceItem</title>
<path fill="none" stroke="#f58c47" d="M1566.9,-75.5104C1594.2,-64.1725 1632.27,-48.3683 1661.2,-36.3554"/>
<ellipse fill="none" stroke="#f58c47" cx="1563.17" cy="-77.0587" rx="4.00002" ry="4.00002"/>
<polygon fill="#f58c47" stroke="#f58c47" points="1661.4,-36.2734 1672.36,-36.5947 1666.02,-34.356 1670.63,-32.4387 1670.63,-32.4387 1670.63,-32.4387 1666.02,-34.356 1668.91,-28.2827 1661.4,-36.2734 1661.4,-36.2734"/>
<path fill="none" stroke="#ae4ae7" d="M1436.96,-74.2945C1459.77,-63.4254 1490.22,-48.9176 1514.2,-37.4896"/>
<ellipse fill="none" stroke="#ae4ae7" cx="1433.23" cy="-76.074" rx="4.00002" ry="4.00002"/>
<polygon fill="#ae4ae7" stroke="#ae4ae7" points="1514.35,-37.4189 1525.31,-37.1796 1518.86,-35.2681 1523.37,-33.1172 1523.37,-33.1172 1523.37,-33.1172 1518.86,-35.2681 1521.44,-29.0548 1514.35,-37.4189 1514.35,-37.4189"/>
</g>
<!-- Invoice&#45;&gt;Invoice -->
<g id="edge32" class="edge"><title>Invoice&#45;&gt;Invoice</title>
<path fill="none" stroke="#0f8c0d" d="M1574.47,-97.3281C1581.89,-96.4844 1587.05,-94.375 1587.05,-91 1587.05,-87.625 1581.89,-85.5156 1574.47,-84.6719"/>
<ellipse fill="none" stroke="#0f8c0d" cx="1570.4" cy="-97.541" rx="4" ry="4"/>
<ellipse fill="#0f8c0d" stroke="#0f8c0d" cx="1570.4" cy="-84.459" rx="4" ry="4"/>
<text text-anchor="middle" x="1601.05" y="-87.3" font-family="Times,serif" font-size="14.00">avoir</text>
<path fill="none" stroke="#9aef0b" d="M1446.47,-97.3281C1453.89,-96.4844 1459.05,-94.375 1459.05,-91 1459.05,-87.625 1453.89,-85.5156 1446.47,-84.6719"/>
<ellipse fill="none" stroke="#9aef0b" cx="1442.4" cy="-97.541" rx="4" ry="4"/>
<ellipse fill="#9aef0b" stroke="#9aef0b" cx="1442.4" cy="-84.459" rx="4" ry="4"/>
<text text-anchor="middle" x="1473.05" y="-87.3" font-family="Times,serif" font-size="14.00">avoir</text>
</g>
<!-- PlanFile -->
<g id="node29" class="node"><title>PlanFile</title>
@ -453,31 +453,42 @@
</g>
<!-- OfferDay -->
<g id="node30" class="node"><title>OfferDay</title>
<ellipse fill="none" stroke="black" cx="1286" cy="-178" rx="44.393" ry="18"/>
<text text-anchor="middle" x="1286" y="-174.3" font-family="Times,serif" font-size="14.00">OfferDay</text>
<ellipse fill="none" stroke="black" cx="1261" cy="-178" rx="44.393" ry="18"/>
<text text-anchor="middle" x="1261" y="-174.3" font-family="Times,serif" font-size="14.00">OfferDay</text>
</g>
<!-- OfferDay&#45;&gt;Invoice -->
<g id="edge33" class="edge"><title>OfferDay&#45;&gt;Invoice</title>
<path fill="none" stroke="#8b4ae2" d="M1326.32,-163.067C1372.49,-147.116 1447.59,-121.167 1493.13,-105.43"/>
<ellipse fill="none" stroke="#8b4ae2" cx="1322.45" cy="-164.406" rx="4.00001" ry="4.00001"/>
<polygon fill="#8b4ae2" stroke="#8b4ae2" points="1493.21,-105.405 1504.13,-106.392 1497.93,-103.772 1502.66,-102.139 1502.66,-102.139 1502.66,-102.139 1497.93,-103.772 1501.19,-97.8854 1493.21,-105.405 1493.21,-105.405"/>
<path fill="none" stroke="#479ec1" d="M1291.86,-158.656C1315.74,-144.46 1348.68,-124.88 1372.68,-110.615"/>
<ellipse fill="none" stroke="#479ec1" cx="1288.37" cy="-160.729" rx="4.00002" ry="4.00002"/>
<polygon fill="#479ec1" stroke="#479ec1" points="1372.81,-110.541 1383.7,-109.299 1377.11,-107.986 1381.4,-105.431 1381.4,-105.431 1381.4,-105.431 1377.11,-107.986 1379.1,-101.563 1372.81,-110.541 1372.81,-110.541"/>
</g>
<!-- StatisticIndex -->
<g id="node59" class="node"><title>StatisticIndex</title>
<ellipse fill="none" stroke="black" cx="3329" cy="-554" rx="59.2899" ry="18"/>
<text text-anchor="middle" x="3329" y="-550.3" font-family="Times,serif" font-size="14.00">StatisticIndex</text>
<ellipse fill="none" stroke="black" cx="3327" cy="-554" rx="59.2899" ry="18"/>
<text text-anchor="middle" x="3327" y="-550.3" font-family="Times,serif" font-size="14.00">StatisticIndex</text>
</g>
<!-- StatisticType&#45;&gt;StatisticIndex -->
<g id="edge34" class="edge"><title>StatisticType&#45;&gt;StatisticIndex</title>
<path fill="none" stroke="#0e33e6" d="M3341.3,-615.44C3337.17,-604.359 3333.16,-591.284 3330.47,-580.135"/>
<ellipse fill="none" stroke="#0e33e6" cx="3342.89" cy="-619.485" rx="4.00001" ry="4.00001"/>
<ellipse fill="#0e33e6" stroke="#0e33e6" cx="3329.54" cy="-575.955" rx="4.00001" ry="4.00001"/>
<path fill="none" stroke="#81d9fd" d="M3320.77,-614.694C3320.08,-603.869 3320.08,-591.254 3320.76,-580.417"/>
<ellipse fill="none" stroke="#81d9fd" cx="3321.11" cy="-618.813" rx="4" ry="4"/>
<ellipse fill="#81d9fd" stroke="#81d9fd" cx="3321.12" cy="-576.161" rx="4" ry="4"/>
</g>
<!-- StatisticType&#45;&gt;StatisticTypeSubType -->
<g id="edge35" class="edge"><title>StatisticType&#45;&gt;StatisticTypeSubType</title>
<path fill="none" stroke="#2c1691" d="M3387.03,-620.555C3408.63,-607.44 3437.15,-590.125 3459.45,-576.584"/>
<ellipse fill="none" stroke="#2c1691" cx="3383.45" cy="-622.728" rx="4.00002" ry="4.00002"/>
<polygon fill="#2c1691" stroke="#2c1691" points="3459.73,-576.412 3470.62,-575.069 3464.01,-573.817 3468.28,-571.222 3468.28,-571.222 3468.28,-571.222 3464.01,-573.817 3465.95,-567.376 3459.73,-576.412 3459.73,-576.412"/>
<path fill="none" stroke="#1ac5ae" d="M3291.25,-621.692C3264.78,-608.14 3228.7,-589.666 3201.23,-575.599"/>
<ellipse fill="none" stroke="#1ac5ae" cx="3294.9" cy="-623.565" rx="4.00002" ry="4.00002"/>
<polygon fill="#1ac5ae" stroke="#1ac5ae" points="3201.17,-575.568 3194.32,-567.005 3196.72,-573.289 3192.27,-571.01 3192.27,-571.01 3192.27,-571.01 3196.72,-573.289 3190.22,-575.016 3201.17,-575.568 3201.17,-575.568"/>
</g>
<!-- StatisticCustomAggregation -->
<g id="node77" class="node"><title>StatisticCustomAggregation</title>
<ellipse fill="none" stroke="black" cx="3515" cy="-554" rx="110.48" ry="18"/>
<text text-anchor="middle" x="3515" y="-550.3" font-family="Times,serif" font-size="14.00">StatisticCustomAggregation</text>
</g>
<!-- StatisticType&#45;&gt;StatisticCustomAggregation -->
<g id="edge36" class="edge"><title>StatisticType&#45;&gt;StatisticCustomAggregation</title>
<path fill="none" stroke="#912df1" d="M3365.77,-622.47C3395.99,-608.808 3438,-589.812 3469.76,-575.456"/>
<ellipse fill="none" stroke="#912df1" cx="3362.11" cy="-624.125" rx="4.00002" ry="4.00002"/>
<polygon fill="#912df1" stroke="#912df1" points="3470.14,-575.281 3481.11,-575.261 3474.7,-573.221 3479.26,-571.161 3479.26,-571.161 3479.26,-571.161 3474.7,-573.221 3477.4,-567.061 3470.14,-575.281 3470.14,-575.281"/>
</g>
<!-- Address -->
<g id="node33" class="node"><title>Address</title>
@ -485,52 +496,52 @@
<text text-anchor="middle" x="82" y="-334.3" font-family="Times,serif" font-size="14.00">Address</text>
</g>
<!-- Plan&#45;&gt;Price -->
<g id="edge42" class="edge"><title>Plan&#45;&gt;Price</title>
<path fill="none" stroke="#cdf1fe" d="M1866.99,-328.928C1879.76,-325.933 1894.52,-322.628 1908,-320 1957.48,-310.351 1979.12,-331.511 2020,-302 2028.04,-296.196 2033.79,-287.151 2037.8,-278.342"/>
<ellipse fill="none" stroke="#cdf1fe" cx="1862.81" cy="-329.918" rx="4.00001" ry="4.00001"/>
<polygon fill="#cdf1fe" stroke="#cdf1fe" points="2037.8,-278.331 2045.68,-270.701 2039.65,-273.685 2041.5,-269.039 2041.5,-269.039 2041.5,-269.039 2039.65,-273.685 2037.32,-267.376 2037.8,-278.331 2037.8,-278.331"/>
<g id="edge43" class="edge"><title>Plan&#45;&gt;Price</title>
<path fill="none" stroke="#e32396" d="M1866.99,-328.928C1879.76,-325.933 1894.52,-322.628 1908,-320 1957.48,-310.351 1979.12,-331.511 2020,-302 2028.04,-296.196 2033.79,-287.151 2037.8,-278.342"/>
<ellipse fill="none" stroke="#e32396" cx="1862.81" cy="-329.918" rx="4.00001" ry="4.00001"/>
<polygon fill="#e32396" stroke="#e32396" points="2037.8,-278.331 2045.68,-270.701 2039.65,-273.685 2041.5,-269.039 2041.5,-269.039 2041.5,-269.039 2039.65,-273.685 2037.32,-267.376 2037.8,-278.331 2037.8,-278.331"/>
</g>
<!-- Plan&#45;&gt;PlanFile -->
<g id="edge41" class="edge"><title>Plan&#45;&gt;PlanFile</title>
<path fill="none" stroke="#43708a" d="M1867.96,-330.941C1900.06,-323.702 1940.86,-309.643 1923,-287 1921.36,-284.915 1862.62,-271.297 1820.16,-261.677"/>
<ellipse fill="none" stroke="#43708a" cx="1863.93" cy="-331.8" rx="4.00001" ry="4.00001"/>
<ellipse fill="#43708a" stroke="#43708a" cx="1816.07" cy="-260.753" rx="4.00001" ry="4.00001"/>
<g id="edge42" class="edge"><title>Plan&#45;&gt;PlanFile</title>
<path fill="none" stroke="#70107d" d="M1867.96,-330.941C1900.06,-323.702 1940.86,-309.643 1923,-287 1921.36,-284.915 1862.62,-271.297 1820.16,-261.677"/>
<ellipse fill="none" stroke="#70107d" cx="1863.93" cy="-331.8" rx="4.00001" ry="4.00001"/>
<ellipse fill="#70107d" stroke="#70107d" cx="1816.07" cy="-260.753" rx="4.00001" ry="4.00001"/>
</g>
<!-- Credit -->
<g id="node44" class="node"><title>Credit</title>
<ellipse fill="none" stroke="black" cx="1409" cy="-251" rx="32.4942" ry="18"/>
<text text-anchor="middle" x="1409" y="-247.3" font-family="Times,serif" font-size="14.00">Credit</text>
</g>
<!-- Plan&#45;&gt;Credit -->
<g id="edge36" class="edge"><title>Plan&#45;&gt;Credit</title>
<path fill="none" stroke="#5a3fef" d="M1808.98,-320.261C1790.67,-308.894 1764.81,-294.596 1740,-287 1640.03,-256.393 1516.03,-251.567 1451.91,-251.368"/>
<ellipse fill="none" stroke="#5a3fef" cx="1812.46" cy="-322.47" rx="4.00002" ry="4.00002"/>
<polygon fill="#5a3fef" stroke="#5a3fef" points="1451.77,-251.368 1441.77,-246.874 1446.77,-251.371 1441.77,-251.374 1441.77,-251.374 1441.77,-251.374 1446.77,-251.371 1441.77,-255.874 1451.77,-251.368 1451.77,-251.368"/>
<ellipse fill="none" stroke="black" cx="1423" cy="-251" rx="32.4942" ry="18"/>
<text text-anchor="middle" x="1423" y="-247.3" font-family="Times,serif" font-size="14.00">Credit</text>
</g>
<!-- Plan&#45;&gt;Credit -->
<g id="edge37" class="edge"><title>Plan&#45;&gt;Credit</title>
<path fill="none" stroke="#a00c3d" d="M1814.45,-316.219C1803.13,-305.58 1787.99,-293.523 1772,-287 1714.94,-263.719 1534.75,-255.606 1451.69,-253.055"/>
<ellipse fill="none" stroke="#a00c3d" cx="1817.46" cy="-319.149" rx="4.00002" ry="4.00002"/>
<polygon fill="#a00c3d" stroke="#a00c3d" points="1451.58,-253.052 1441.72,-248.26 1446.58,-252.905 1441.58,-252.758 1441.58,-252.758 1441.58,-252.758 1446.58,-252.905 1441.45,-257.256 1451.58,-253.052 1451.58,-253.052"/>
<text text-anchor="middle" x="1839.5" y="-290.8" font-family="Times,serif" font-size="14.00">training_credits</text>
<path fill="none" stroke="#f84fb3" d="M1808.96,-320.296C1790.66,-308.946 1764.79,-294.653 1740,-287 1645.23,-257.744 1527.87,-252.294 1465.94,-251.659"/>
<ellipse fill="none" stroke="#f84fb3" cx="1812.45" cy="-322.501" rx="4.00002" ry="4.00002"/>
<polygon fill="#f84fb3" stroke="#f84fb3" points="1465.76,-251.658 1455.79,-247.093 1460.76,-251.626 1455.76,-251.593 1455.76,-251.593 1455.76,-251.593 1460.76,-251.626 1455.73,-256.093 1465.76,-251.658 1465.76,-251.658"/>
</g>
<!-- Plan&#45;&gt;Credit -->
<g id="edge38" class="edge"><title>Plan&#45;&gt;Credit</title>
<path fill="none" stroke="#094cc2" d="M1799.18,-332.862C1761.03,-327.789 1698.28,-317.856 1646,-302 1629.8,-297.088 1627.23,-291.811 1611,-287 1556.74,-270.911 1491.94,-261.305 1450.64,-256.336"/>
<ellipse fill="none" stroke="#094cc2" cx="1803.44" cy="-333.415" rx="4.00001" ry="4.00001"/>
<polygon fill="#094cc2" stroke="#094cc2" points="1450.6,-256.331 1441.19,-250.702 1445.63,-255.752 1440.66,-255.172 1440.66,-255.172 1440.66,-255.172 1445.63,-255.752 1440.14,-259.641 1450.6,-256.331 1450.6,-256.331"/>
<path fill="none" stroke="#546aa8" d="M1814.44,-316.243C1803.12,-305.611 1787.98,-293.554 1772,-287 1717.54,-264.66 1546.31,-256.101 1465.73,-253.249"/>
<ellipse fill="none" stroke="#546aa8" cx="1817.45" cy="-319.17" rx="4.00002" ry="4.00002"/>
<polygon fill="#546aa8" stroke="#546aa8" points="1465.43,-253.239 1455.59,-248.402 1460.44,-253.069 1455.44,-252.899 1455.44,-252.899 1455.44,-252.899 1460.44,-253.069 1455.29,-257.396 1465.43,-253.239 1465.43,-253.239"/>
<text text-anchor="middle" x="1839.5" y="-290.8" font-family="Times,serif" font-size="14.00">training_credits</text>
</g>
<!-- Plan&#45;&gt;Credit -->
<g id="edge39" class="edge"><title>Plan&#45;&gt;Credit</title>
<path fill="none" stroke="#158006" d="M1799.18,-332.862C1761.03,-327.789 1698.28,-317.856 1646,-302 1629.8,-297.088 1627.2,-291.912 1611,-287 1561.78,-272.071 1503.27,-262.392 1464.75,-257.077"/>
<ellipse fill="none" stroke="#158006" cx="1803.44" cy="-333.415" rx="4.00001" ry="4.00001"/>
<polygon fill="#158006" stroke="#158006" points="1464.35,-257.024 1455.04,-251.233 1459.4,-256.359 1454.44,-255.693 1454.44,-255.693 1454.44,-255.693 1459.4,-256.359 1453.84,-260.153 1464.35,-257.024 1464.35,-257.024"/>
<text text-anchor="middle" x="1691" y="-290.8" font-family="Times,serif" font-size="14.00">machine_credits</text>
</g>
<!-- Subscription -->
<g id="node55" class="node"><title>Subscription</title>
<ellipse fill="none" stroke="black" cx="1209" cy="-251" rx="55.4913" ry="18"/>
<text text-anchor="middle" x="1209" y="-247.3" font-family="Times,serif" font-size="14.00">Subscription</text>
<ellipse fill="none" stroke="black" cx="1178" cy="-251" rx="55.4913" ry="18"/>
<text text-anchor="middle" x="1178" y="-247.3" font-family="Times,serif" font-size="14.00">Subscription</text>
</g>
<!-- Plan&#45;&gt;Subscription -->
<g id="edge39" class="edge"><title>Plan&#45;&gt;Subscription</title>
<path fill="none" stroke="#089b92" d="M1798.96,-334.801C1711.83,-329.218 1487.08,-314.081 1413,-302 1359.47,-293.271 1299.28,-277.807 1258.24,-266.38"/>
<ellipse fill="none" stroke="#089b92" cx="1803.21" cy="-335.072" rx="4" ry="4"/>
<polygon fill="#089b92" stroke="#089b92" points="1258.12,-266.347 1249.71,-259.31 1253.3,-264.995 1248.49,-263.643 1248.49,-263.643 1248.49,-263.643 1253.3,-264.995 1247.27,-267.975 1258.12,-266.347 1258.12,-266.347"/>
<g id="edge40" class="edge"><title>Plan&#45;&gt;Subscription</title>
<path fill="none" stroke="#7c49f4" d="M1799.01,-334.618C1712.55,-328.644 1490.48,-312.729 1417,-302 1352.19,-292.537 1278.55,-276.283 1230.35,-264.883"/>
<ellipse fill="none" stroke="#7c49f4" cx="1803.2" cy="-334.907" rx="4" ry="4"/>
<polygon fill="#7c49f4" stroke="#7c49f4" points="1230.19,-264.845 1221.5,-258.15 1225.32,-263.686 1220.46,-262.528 1220.46,-262.528 1220.46,-262.528 1225.32,-263.686 1219.42,-266.905 1230.19,-264.845 1230.19,-264.845"/>
</g>
<!-- PlanImage -->
<g id="node75" class="node"><title>PlanImage</title>
@ -538,10 +549,10 @@
<text text-anchor="middle" x="1911" y="-247.3" font-family="Times,serif" font-size="14.00">PlanImage</text>
</g>
<!-- Plan&#45;&gt;PlanImage -->
<g id="edge40" class="edge"><title>Plan&#45;&gt;PlanImage</title>
<path fill="none" stroke="#9cb026" d="M1867.5,-330.385C1895.19,-324.158 1931.32,-314.008 1940,-302 1946.34,-293.231 1942.19,-282.978 1935.27,-274.048"/>
<ellipse fill="none" stroke="#9cb026" cx="1863.49" cy="-331.26" rx="4.00001" ry="4.00001"/>
<ellipse fill="#9cb026" stroke="#9cb026" cx="1932.47" cy="-270.836" rx="4.00002" ry="4.00002"/>
<g id="edge41" class="edge"><title>Plan&#45;&gt;PlanImage</title>
<path fill="none" stroke="#8fb631" d="M1867.5,-330.385C1895.19,-324.158 1931.32,-314.008 1940,-302 1946.34,-293.231 1942.19,-282.978 1935.27,-274.048"/>
<ellipse fill="none" stroke="#8fb631" cx="1863.49" cy="-331.26" rx="4.00001" ry="4.00001"/>
<ellipse fill="#8fb631" stroke="#8fb631" cx="1932.47" cy="-270.836" rx="4.00002" ry="4.00002"/>
</g>
<!-- MachineFile -->
<g id="node35" class="node"><title>MachineFile</title>
@ -554,20 +565,20 @@
<text text-anchor="middle" x="123" y="-442.3" font-family="Times,serif" font-size="14.00">Organization</text>
</g>
<!-- Organization&#45;&gt;Address -->
<g id="edge43" class="edge"><title>Organization&#45;&gt;Address</title>
<path fill="none" stroke="#a9d23c" d="M113.435,-420.271C106.869,-403.296 98.1874,-380.85 91.6115,-363.849"/>
<ellipse fill="none" stroke="#a9d23c" cx="114.97" cy="-424.239" rx="4.00001" ry="4.00001"/>
<ellipse fill="#a9d23c" stroke="#a9d23c" cx="90.014" cy="-359.719" rx="4.00001" ry="4.00001"/>
<g id="edge44" class="edge"><title>Organization&#45;&gt;Address</title>
<path fill="none" stroke="#82d164" d="M113.435,-420.271C106.869,-403.296 98.1874,-380.85 91.6115,-363.849"/>
<ellipse fill="none" stroke="#82d164" cx="114.97" cy="-424.239" rx="4.00001" ry="4.00001"/>
<ellipse fill="#82d164" stroke="#82d164" cx="90.014" cy="-359.719" rx="4.00001" ry="4.00001"/>
</g>
<!-- StatisticGraph -->
<g id="node37" class="node"><title>StatisticGraph</title>
<ellipse fill="none" stroke="black" cx="3193" cy="-446" rx="61.1893" ry="18"/>
<text text-anchor="middle" x="3193" y="-442.3" font-family="Times,serif" font-size="14.00">StatisticGraph</text>
<ellipse fill="none" stroke="black" cx="3191" cy="-446" rx="61.1893" ry="18"/>
<text text-anchor="middle" x="3191" y="-442.3" font-family="Times,serif" font-size="14.00">StatisticGraph</text>
</g>
<!-- OAuth2Mapping -->
<g id="node39" class="node"><title>OAuth2Mapping</title>
<ellipse fill="none" stroke="black" cx="4508" cy="-641" rx="71.4873" ry="18"/>
<text text-anchor="middle" x="4508" y="-637.3" font-family="Times,serif" font-size="14.00">OAuth2Mapping</text>
<ellipse fill="none" stroke="black" cx="4405" cy="-641" rx="71.4873" ry="18"/>
<text text-anchor="middle" x="4405" y="-637.3" font-family="Times,serif" font-size="14.00">OAuth2Mapping</text>
</g>
<!-- Licence -->
<g id="node40" class="node"><title>Licence</title>
@ -575,60 +586,60 @@
<text text-anchor="middle" x="858" y="-637.3" font-family="Times,serif" font-size="14.00">Licence</text>
</g>
<!-- Licence&#45;&gt;Project -->
<g id="edge44" class="edge"><title>Licence&#45;&gt;Project</title>
<path fill="none" stroke="#3efb05" d="M858,-614.694C858,-604.512 858,-592.747 858,-582.367"/>
<ellipse fill="none" stroke="#3efb05" cx="858" cy="-618.799" rx="4" ry="4"/>
<polygon fill="#3efb05" stroke="#3efb05" points="858,-582.175 862.5,-572.175 858,-577.175 858,-572.175 858,-572.175 858,-572.175 858,-577.175 853.5,-572.175 858,-582.175 858,-582.175"/>
<g id="edge45" class="edge"><title>Licence&#45;&gt;Project</title>
<path fill="none" stroke="#890dfc" d="M858,-614.694C858,-604.512 858,-592.747 858,-582.367"/>
<ellipse fill="none" stroke="#890dfc" cx="858" cy="-618.799" rx="4" ry="4"/>
<polygon fill="#890dfc" stroke="#890dfc" points="858,-582.175 862.5,-572.175 858,-577.175 858,-572.175 858,-572.175 858,-572.175 858,-577.175 853.5,-572.175 858,-582.175 858,-582.175"/>
</g>
<!-- User&#45;&gt;Project -->
<g id="edge48" class="edge"><title>User&#45;&gt;Project</title>
<path fill="none" stroke="#19777c" d="M1201.68,-637.466C1153.3,-633.439 1064,-624.008 990,-605 971.555,-600.262 926.853,-582.848 894.574,-569.895"/>
<ellipse fill="none" stroke="#19777c" cx="1205.95" cy="-637.812" rx="4" ry="4"/>
<polygon fill="#19777c" stroke="#19777c" points="894.274,-569.774 886.68,-561.864 889.636,-567.906 884.998,-566.038 884.998,-566.038 884.998,-566.038 889.636,-567.906 883.317,-570.212 894.274,-569.774 894.274,-569.774"/>
<g id="edge49" class="edge"><title>User&#45;&gt;Project</title>
<path fill="none" stroke="#7a03b6" d="M1201.68,-637.466C1153.3,-633.439 1064,-624.008 990,-605 971.555,-600.262 926.853,-582.848 894.574,-569.895"/>
<ellipse fill="none" stroke="#7a03b6" cx="1205.95" cy="-637.812" rx="4" ry="4"/>
<polygon fill="#7a03b6" stroke="#7a03b6" points="894.274,-569.774 886.68,-561.864 889.636,-567.906 884.998,-566.038 884.998,-566.038 884.998,-566.038 889.636,-567.906 883.317,-570.212 894.274,-569.774 894.274,-569.774"/>
<text text-anchor="middle" x="1024" y="-593.8" font-family="Times,serif" font-size="14.00">my_projects</text>
</g>
<!-- User&#45;&gt;Wallet -->
<g id="edge60" class="edge"><title>User&#45;&gt;Wallet</title>
<path fill="none" stroke="#de48d4" d="M1201.85,-637.158C1141.97,-632.109 1016.41,-620.616 911,-605 718.609,-576.496 490.837,-528.85 401.105,-509.528"/>
<ellipse fill="none" stroke="#de48d4" cx="1205.87" cy="-637.494" rx="4" ry="4"/>
<ellipse fill="#de48d4" stroke="#de48d4" cx="397.02" cy="-508.647" rx="4.00001" ry="4.00001"/>
<g id="edge61" class="edge"><title>User&#45;&gt;Wallet</title>
<path fill="none" stroke="#317495" d="M1201.87,-637.078C1142,-631.909 1016.46,-620.244 911,-605 710.13,-575.964 471.869,-528.237 379.405,-509.207"/>
<ellipse fill="none" stroke="#317495" cx="1205.88" cy="-637.422" rx="4" ry="4"/>
<ellipse fill="#317495" stroke="#317495" cx="375.354" cy="-508.371" rx="4.00001" ry="4.00001"/>
</g>
<!-- User&#45;&gt;Invoice -->
<g id="edge58" class="edge"><title>User&#45;&gt;Invoice</title>
<path fill="none" stroke="#67b219" d="M1201.8,-637.974C1141.2,-634.535 1013.22,-627.494 905,-623 653.978,-612.576 590.246,-627.313 340,-605 263.934,-598.218 0,-631.368 0,-555 0,-555 0,-555 0,-177 0,-100.723 1226.69,-92.8947 1484.72,-92.0917"/>
<ellipse fill="none" stroke="#67b219" cx="1205.9" cy="-638.207" rx="4" ry="4"/>
<polygon fill="#67b219" stroke="#67b219" points="1484.89,-92.0913 1494.9,-96.5622 1489.89,-92.0768 1494.89,-92.0622 1494.89,-92.0622 1494.89,-92.0622 1489.89,-92.0768 1494.88,-87.5622 1484.89,-92.0913 1484.89,-92.0913"/>
</g>
<!-- User&#45;&gt;Credit -->
<g id="edge55" class="edge"><title>User&#45;&gt;Credit</title>
<path fill="none" stroke="#34b250" d="M1246.42,-613.615C1258.18,-579.532 1277.96,-518.143 1288,-464 1302.39,-386.374 1254.08,-348.969 1303,-287 1318.2,-267.74 1344.3,-258.97 1366.79,-255.025"/>
<polygon fill="#34b250" stroke="#34b250" points="1246.35,-613.836 1238.8,-621.795 1244.7,-618.557 1243.05,-623.277 1243.05,-623.277 1243.05,-623.277 1244.7,-618.557 1247.3,-624.76 1246.35,-613.836 1246.35,-613.836"/>
<polygon fill="#34b250" stroke="#34b250" points="1366.93,-255.004 1377.48,-257.982 1371.87,-254.268 1376.82,-253.531 1376.82,-253.531 1376.82,-253.531 1371.87,-254.268 1376.15,-249.08 1366.93,-255.004 1366.93,-255.004"/>
<g id="edge59" class="edge"><title>User&#45;&gt;Invoice</title>
<path fill="none" stroke="#3cec05" d="M1201.8,-637.989C1141.19,-634.573 1013.22,-627.564 905,-623 663.749,-612.826 602.59,-625.547 362,-605 281.086,-598.09 0,-636.208 0,-555 0,-555 0,-555 0,-177 0,-107.484 1111.13,-94.3827 1356.45,-92.3374"/>
<ellipse fill="none" stroke="#3cec05" cx="1205.9" cy="-638.221" rx="4" ry="4"/>
<polygon fill="#3cec05" stroke="#3cec05" points="1356.81,-92.3345 1366.84,-96.7532 1361.81,-92.2939 1366.81,-92.2533 1366.81,-92.2533 1366.81,-92.2533 1361.81,-92.2939 1366.77,-87.7535 1356.81,-92.3345 1356.81,-92.3345"/>
</g>
<!-- User&#45;&gt;Credit -->
<g id="edge56" class="edge"><title>User&#45;&gt;Credit</title>
<path fill="none" stroke="#38b7a3" d="M1257.2,-617.546C1260.35,-613.515 1263.42,-609.243 1266,-605 1274.28,-591.389 1273.97,-586.749 1280,-572 1331.47,-446.011 1337.34,-411.637 1392,-287 1393.33,-283.969 1394.77,-280.815 1396.24,-277.698"/>
<polygon fill="#38b7a3" stroke="#38b7a3" points="1257.09,-617.68 1247.25,-622.529 1253.91,-621.536 1250.72,-625.393 1250.72,-625.393 1250.72,-625.393 1253.91,-621.536 1254.19,-628.257 1257.09,-617.68 1257.09,-617.68"/>
<polygon fill="#38b7a3" stroke="#38b7a3" points="1396.27,-277.625 1404.66,-270.561 1398.44,-273.118 1400.6,-268.611 1400.6,-268.611 1400.6,-268.611 1398.44,-273.118 1396.55,-266.662 1396.27,-277.625 1396.27,-277.625"/>
<text text-anchor="middle" x="1377.5" y="-442.3" font-family="Times,serif" font-size="14.00">training_credits</text>
<path fill="none" stroke="#f5a7a0" d="M1246.42,-613.615C1258.18,-579.532 1277.96,-518.143 1288,-464 1302.39,-386.374 1253,-348.101 1303,-287 1321.5,-264.389 1353.73,-255.88 1380.13,-252.894"/>
<polygon fill="#f5a7a0" stroke="#f5a7a0" points="1246.35,-613.836 1238.8,-621.795 1244.7,-618.557 1243.05,-623.277 1243.05,-623.277 1243.05,-623.277 1244.7,-618.557 1247.3,-624.76 1246.35,-613.836 1246.35,-613.836"/>
<polygon fill="#f5a7a0" stroke="#f5a7a0" points="1380.33,-252.876 1390.7,-256.459 1385.31,-252.427 1390.29,-251.977 1390.29,-251.977 1390.29,-251.977 1385.31,-252.427 1389.89,-247.495 1380.33,-252.876 1380.33,-252.876"/>
</g>
<!-- User&#45;&gt;Credit -->
<g id="edge57" class="edge"><title>User&#45;&gt;Credit</title>
<path fill="none" stroke="#523f8e" d="M1217.69,-616.551C1206.26,-600.303 1194,-577.605 1194,-555 1194,-555 1194,-555 1194,-337 1194,-299.93 1305.94,-272.102 1368.27,-259.478"/>
<polygon fill="#523f8e" stroke="#523f8e" points="1217.9,-616.843 1220.25,-627.555 1220.88,-620.858 1223.86,-624.872 1223.86,-624.872 1223.86,-624.872 1220.88,-620.858 1227.48,-622.189 1217.9,-616.843 1217.9,-616.843"/>
<polygon fill="#523f8e" stroke="#523f8e" points="1368.39,-259.456 1379.07,-261.927 1373.29,-258.484 1378.2,-257.513 1378.2,-257.513 1378.2,-257.513 1373.29,-258.484 1377.32,-253.098 1368.39,-259.456 1368.39,-259.456"/>
<path fill="none" stroke="#890254" d="M1257.2,-617.546C1260.35,-613.515 1263.42,-609.243 1266,-605 1274.28,-591.389 1273.93,-586.73 1280,-572 1331.98,-445.865 1324.3,-404.277 1394,-287 1396.38,-283 1399.2,-278.985 1402.13,-275.175"/>
<polygon fill="#890254" stroke="#890254" points="1257.09,-617.68 1247.25,-622.529 1253.91,-621.536 1250.72,-625.393 1250.72,-625.393 1250.72,-625.393 1253.91,-621.536 1254.19,-628.257 1257.09,-617.68 1257.09,-617.68"/>
<polygon fill="#890254" stroke="#890254" points="1402.28,-274.992 1412.09,-270.093 1405.44,-271.12 1408.61,-267.247 1408.61,-267.247 1408.61,-267.247 1405.44,-271.12 1405.12,-264.4 1402.28,-274.992 1402.28,-274.992"/>
<text text-anchor="middle" x="1372.5" y="-442.3" font-family="Times,serif" font-size="14.00">training_credits</text>
</g>
<!-- User&#45;&gt;Credit -->
<g id="edge58" class="edge"><title>User&#45;&gt;Credit</title>
<path fill="none" stroke="#c01104" d="M1217.69,-616.551C1206.26,-600.303 1194,-577.605 1194,-555 1194,-555 1194,-555 1194,-337 1194,-297.35 1316.19,-270.272 1382.06,-258.555"/>
<polygon fill="#c01104" stroke="#c01104" points="1217.9,-616.843 1220.25,-627.555 1220.88,-620.858 1223.86,-624.872 1223.86,-624.872 1223.86,-624.872 1220.88,-620.858 1227.48,-622.189 1217.9,-616.843 1217.9,-616.843"/>
<polygon fill="#c01104" stroke="#c01104" points="1382.26,-258.519 1392.89,-261.241 1387.19,-257.663 1392.12,-256.807 1392.12,-256.807 1392.12,-256.807 1387.19,-257.663 1391.35,-252.374 1382.26,-258.519 1382.26,-258.519"/>
<text text-anchor="middle" x="1239" y="-442.3" font-family="Times,serif" font-size="14.00">machine_credits</text>
</g>
<!-- Role -->
<g id="node49" class="node"><title>Role</title>
<ellipse fill="none" stroke="black" cx="1084" cy="-251" rx="27.0966" ry="18"/>
<text text-anchor="middle" x="1084" y="-247.3" font-family="Times,serif" font-size="14.00">Role</text>
<ellipse fill="none" stroke="black" cx="1076" cy="-251" rx="27.0966" ry="18"/>
<text text-anchor="middle" x="1076" y="-247.3" font-family="Times,serif" font-size="14.00">Role</text>
</g>
<!-- User&#45;&gt;Role -->
<g id="edge46" class="edge"><title>User&#45;&gt;Role</title>
<path fill="none" stroke="#20ee13" d="M1199.57,-637.008C1150.89,-630.838 1072,-612.039 1072,-555 1072,-555 1072,-555 1072,-337 1072,-317.439 1075.15,-295.593 1078.23,-278.947"/>
<polygon fill="#20ee13" stroke="#20ee13" points="1199.82,-637.036 1209.24,-642.643 1204.79,-637.604 1209.75,-638.172 1209.75,-638.172 1209.75,-638.172 1204.79,-637.604 1210.26,-633.701 1199.82,-637.036 1199.82,-637.036"/>
<polygon fill="#20ee13" stroke="#20ee13" points="1078.29,-278.649 1084.62,-269.697 1079.24,-273.742 1080.2,-268.835 1080.2,-268.835 1080.2,-268.835 1079.24,-273.742 1075.79,-267.972 1078.29,-278.649 1078.29,-278.649"/>
<g id="edge47" class="edge"><title>User&#45;&gt;Role</title>
<path fill="none" stroke="#787c74" d="M1199.57,-637.008C1150.89,-630.838 1072,-612.039 1072,-555 1072,-555 1072,-555 1072,-337 1072,-317.731 1073.04,-296.033 1074.06,-279.382"/>
<polygon fill="#787c74" stroke="#787c74" points="1199.82,-637.036 1209.24,-642.643 1204.79,-637.604 1209.75,-638.172 1209.75,-638.172 1209.75,-638.172 1204.79,-637.604 1210.26,-633.701 1199.82,-637.036 1199.82,-637.036"/>
<polygon fill="#787c74" stroke="#787c74" points="1074.07,-279.224 1079.2,-269.536 1074.39,-274.235 1074.71,-269.245 1074.71,-269.245 1074.71,-269.245 1074.39,-274.235 1070.22,-268.955 1074.07,-279.224 1074.07,-279.224"/>
</g>
<!-- Notification -->
<g id="node54" class="node"><title>Notification</title>
@ -636,16 +647,16 @@
<text text-anchor="middle" x="1399" y="-550.3" font-family="Times,serif" font-size="14.00">Notification</text>
</g>
<!-- User&#45;&gt;Notification -->
<g id="edge45" class="edge"><title>User&#45;&gt;Notification</title>
<path fill="none" stroke="#00ddba" d="M1269.39,-630.635C1288.24,-624.563 1312.13,-615.78 1332,-605 1346.3,-597.24 1360.93,-586.686 1372.85,-577.274"/>
<ellipse fill="none" stroke="#00ddba" cx="1265.47" cy="-631.869" rx="4.00001" ry="4.00001"/>
<polygon fill="#00ddba" stroke="#00ddba" points="1372.86,-577.271 1383.47,-574.49 1376.75,-574.13 1380.64,-570.989 1380.64,-570.989 1380.64,-570.989 1376.75,-574.13 1377.81,-567.487 1372.86,-577.271 1372.86,-577.271"/>
<g id="edge46" class="edge"><title>User&#45;&gt;Notification</title>
<path fill="none" stroke="#b3b3c1" d="M1269.39,-630.635C1288.24,-624.563 1312.13,-615.78 1332,-605 1346.3,-597.24 1360.93,-586.686 1372.85,-577.274"/>
<ellipse fill="none" stroke="#b3b3c1" cx="1265.47" cy="-631.869" rx="4.00001" ry="4.00001"/>
<polygon fill="#b3b3c1" stroke="#b3b3c1" points="1372.86,-577.271 1383.47,-574.49 1376.75,-574.13 1380.64,-570.989 1380.64,-570.989 1380.64,-570.989 1376.75,-574.13 1377.81,-567.487 1372.86,-577.271 1372.86,-577.271"/>
</g>
<!-- User&#45;&gt;Subscription -->
<g id="edge53" class="edge"><title>User&#45;&gt;Subscription</title>
<path fill="none" stroke="#a62697" d="M1202.4,-635.249C1180.59,-630.695 1153.05,-621.888 1134,-605 1115.56,-588.646 1110,-579.65 1110,-555 1110,-555 1110,-555 1110,-337 1110,-305.793 1138.67,-283.559 1165.15,-269.677"/>
<ellipse fill="none" stroke="#a62697" cx="1206.52" cy="-636.04" rx="4.00001" ry="4.00001"/>
<polygon fill="#a62697" stroke="#a62697" points="1165.41,-269.547 1176.37,-269.148 1169.89,-267.331 1174.37,-265.114 1174.37,-265.114 1174.37,-265.114 1169.89,-267.331 1172.38,-261.08 1165.41,-269.547 1165.41,-269.547"/>
<g id="edge54" class="edge"><title>User&#45;&gt;Subscription</title>
<path fill="none" stroke="#6e04f8" d="M1202.4,-635.249C1180.59,-630.695 1153.05,-621.888 1134,-605 1115.56,-588.646 1110,-579.65 1110,-555 1110,-555 1110,-555 1110,-337 1110,-311.598 1128.75,-289.438 1146.55,-274.118"/>
<ellipse fill="none" stroke="#6e04f8" cx="1206.52" cy="-636.04" rx="4.00001" ry="4.00001"/>
<polygon fill="#6e04f8" stroke="#6e04f8" points="1146.84,-273.885 1157.44,-271.065 1150.72,-270.729 1154.6,-267.574 1154.6,-267.574 1154.6,-267.574 1150.72,-270.729 1151.76,-264.083 1146.84,-273.885 1146.84,-273.885"/>
</g>
<!-- Training -->
<g id="node56" class="node"><title>Training</title>
@ -653,33 +664,33 @@
<text text-anchor="middle" x="1863" y="-550.3" font-family="Times,serif" font-size="14.00">Training</text>
</g>
<!-- User&#45;&gt;Training -->
<g id="edge52" class="edge"><title>User&#45;&gt;Training</title>
<path fill="none" stroke="#08f9ef" d="M1274.68,-637.802C1342.57,-633.549 1489.85,-622.997 1613,-605 1685.11,-594.462 1767.89,-576.795 1817.77,-565.529"/>
<polygon fill="#08f9ef" stroke="#08f9ef" points="1274.46,-637.815 1264.2,-633.939 1269.47,-638.122 1264.48,-638.43 1264.48,-638.43 1264.48,-638.43 1269.47,-638.122 1264.76,-642.922 1274.46,-637.815 1274.46,-637.815"/>
<polygon fill="#08f9ef" stroke="#08f9ef" points="1817.85,-565.512 1828.6,-567.685 1822.72,-564.404 1827.6,-563.297 1827.6,-563.297 1827.6,-563.297 1822.72,-564.404 1826.6,-558.908 1817.85,-565.512 1817.85,-565.512"/>
<g id="edge53" class="edge"><title>User&#45;&gt;Training</title>
<path fill="none" stroke="#d48b71" d="M1274.68,-637.802C1342.57,-633.549 1489.85,-622.997 1613,-605 1685.11,-594.462 1767.89,-576.795 1817.77,-565.529"/>
<polygon fill="#d48b71" stroke="#d48b71" points="1274.46,-637.815 1264.2,-633.939 1269.47,-638.122 1264.48,-638.43 1264.48,-638.43 1264.48,-638.43 1269.47,-638.122 1264.76,-642.922 1274.46,-637.815 1274.46,-637.815"/>
<polygon fill="#d48b71" stroke="#d48b71" points="1817.85,-565.512 1828.6,-567.685 1822.72,-564.404 1827.6,-563.297 1827.6,-563.297 1827.6,-563.297 1822.72,-564.404 1826.6,-558.908 1817.85,-565.512 1817.85,-565.512"/>
</g>
<!-- User&#45;&gt;Reservation -->
<g id="edge50" class="edge"><title>User&#45;&gt;Reservation</title>
<path fill="none" stroke="#1c27f9" d="M1272.42,-637.776C1346.27,-632.996 1522.05,-620.878 1669,-605 1890.21,-581.098 1946.78,-574.432 2162,-518 2201.37,-507.678 2300.48,-481.962 2337,-464 2394.88,-435.531 2454.63,-389.12 2487.78,-361.574"/>
<ellipse fill="none" stroke="#1c27f9" cx="1268.33" cy="-638.039" rx="4" ry="4"/>
<polygon fill="#1c27f9" stroke="#1c27f9" points="2487.96,-361.427 2498.51,-358.448 2491.79,-358.213 2495.62,-355 2495.62,-355 2495.62,-355 2491.79,-358.213 2492.73,-351.552 2487.96,-361.427 2487.96,-361.427"/>
<g id="edge51" class="edge"><title>User&#45;&gt;Reservation</title>
<path fill="none" stroke="#637876" d="M1272.42,-637.776C1346.27,-632.996 1522.05,-620.878 1669,-605 1890.21,-581.098 1946.78,-574.432 2162,-518 2201.37,-507.678 2300.48,-481.962 2337,-464 2394.88,-435.531 2454.63,-389.12 2487.78,-361.574"/>
<ellipse fill="none" stroke="#637876" cx="1268.33" cy="-638.039" rx="4" ry="4"/>
<polygon fill="#637876" stroke="#637876" points="2487.96,-361.427 2498.51,-358.448 2491.79,-358.213 2495.62,-355 2495.62,-355 2495.62,-355 2491.79,-358.213 2492.73,-351.552 2487.96,-361.427 2487.96,-361.427"/>
</g>
<!-- UsersCredit -->
<g id="node61" class="node"><title>UsersCredit</title>
<ellipse fill="none" stroke="black" cx="1402" cy="-178" rx="52.7911" ry="18"/>
<text text-anchor="middle" x="1402" y="-174.3" font-family="Times,serif" font-size="14.00">UsersCredit</text>
<ellipse fill="none" stroke="black" cx="1378" cy="-178" rx="52.7911" ry="18"/>
<text text-anchor="middle" x="1378" y="-174.3" font-family="Times,serif" font-size="14.00">UsersCredit</text>
</g>
<!-- User&#45;&gt;UsersCredit -->
<g id="edge54" class="edge"><title>User&#45;&gt;UsersCredit</title>
<path fill="none" stroke="#b4e9d2" d="M1213.68,-621.475C1208.61,-616.558 1203.68,-610.946 1200,-605 1191.94,-591.965 1193.62,-586.891 1190,-572 1163.5,-463.089 1124.67,-417.478 1180,-320 1192.6,-297.803 1204.51,-299.07 1227,-287 1246.34,-276.618 1253.64,-279.353 1273,-269 1310,-249.216 1349.05,-220.764 1374.36,-201.173"/>
<ellipse fill="none" stroke="#b4e9d2" cx="1216.66" cy="-624.206" rx="4.00002" ry="4.00002"/>
<polygon fill="#b4e9d2" stroke="#b4e9d2" points="1374.52,-201.051 1385.17,-198.44 1378.46,-197.973 1382.4,-194.894 1382.4,-194.894 1382.4,-194.894 1378.46,-197.973 1379.63,-191.348 1374.52,-201.051 1374.52,-201.051"/>
<g id="edge55" class="edge"><title>User&#45;&gt;UsersCredit</title>
<path fill="none" stroke="#f8d697" d="M1213.68,-621.475C1208.61,-616.558 1203.68,-610.946 1200,-605 1191.94,-591.965 1193.62,-586.891 1190,-572 1163.5,-463.089 1124.99,-417.662 1180,-320 1189.76,-302.672 1292.5,-234.411 1346,-199.622"/>
<ellipse fill="none" stroke="#f8d697" cx="1216.66" cy="-624.206" rx="4.00002" ry="4.00002"/>
<polygon fill="#f8d697" stroke="#f8d697" points="1346.07,-199.58 1356.9,-197.912 1350.26,-196.859 1354.46,-194.137 1354.46,-194.137 1354.46,-194.137 1350.26,-196.859 1352.01,-190.362 1346.07,-199.58 1346.07,-199.58"/>
</g>
<!-- User&#45;&gt;UserTag -->
<g id="edge59" class="edge"><title>User&#45;&gt;UserTag</title>
<path fill="none" stroke="#118d90" d="M1272.57,-640.889C1336.01,-641.494 1472.24,-638.328 1581,-605 1603.39,-598.14 1626.59,-585.677 1644.22,-574.911"/>
<ellipse fill="none" stroke="#118d90" cx="1268.47" cy="-640.837" rx="4" ry="4"/>
<polygon fill="#118d90" stroke="#118d90" points="1644.42,-574.784 1655.28,-573.288 1648.66,-572.129 1652.89,-569.474 1652.89,-569.474 1652.89,-569.474 1648.66,-572.129 1650.5,-565.661 1644.42,-574.784 1644.42,-574.784"/>
<g id="edge60" class="edge"><title>User&#45;&gt;UserTag</title>
<path fill="none" stroke="#911e7e" d="M1272.57,-640.889C1336.01,-641.494 1472.24,-638.328 1581,-605 1603.39,-598.14 1626.59,-585.677 1644.22,-574.911"/>
<ellipse fill="none" stroke="#911e7e" cx="1268.47" cy="-640.837" rx="4" ry="4"/>
<polygon fill="#911e7e" stroke="#911e7e" points="1644.42,-574.784 1655.28,-573.288 1648.66,-572.129 1652.89,-569.474 1652.89,-569.474 1652.89,-569.474 1648.66,-572.129 1650.5,-565.661 1644.42,-574.784 1644.42,-574.784"/>
</g>
<!-- Export -->
<g id="node67" class="node"><title>Export</title>
@ -687,10 +698,10 @@
<text text-anchor="middle" x="1505" y="-550.3" font-family="Times,serif" font-size="14.00">Export</text>
</g>
<!-- User&#45;&gt;Export -->
<g id="edge61" class="edge"><title>User&#45;&gt;Export</title>
<path fill="none" stroke="#812a98" d="M1269.51,-631.116C1313.36,-618.91 1393.72,-595.754 1461,-572 1463.52,-571.111 1466.11,-570.172 1468.72,-569.211"/>
<ellipse fill="none" stroke="#812a98" cx="1265.62" cy="-632.196" rx="4.00001" ry="4.00001"/>
<polygon fill="#812a98" stroke="#812a98" points="1468.74,-569.201 1479.68,-569.892 1473.42,-567.441 1478.1,-565.68 1478.1,-565.68 1478.1,-565.68 1473.42,-567.441 1476.52,-561.468 1468.74,-569.201 1468.74,-569.201"/>
<g id="edge62" class="edge"><title>User&#45;&gt;Export</title>
<path fill="none" stroke="#b307dc" d="M1269.51,-631.116C1313.36,-618.91 1393.72,-595.754 1461,-572 1463.52,-571.111 1466.11,-570.172 1468.72,-569.211"/>
<ellipse fill="none" stroke="#b307dc" cx="1265.62" cy="-632.196" rx="4.00001" ry="4.00001"/>
<polygon fill="#b307dc" stroke="#b307dc" points="1468.74,-569.201 1479.68,-569.892 1473.42,-567.441 1478.1,-565.68 1478.1,-565.68 1478.1,-565.68 1473.42,-567.441 1476.52,-561.468 1468.74,-569.201 1468.74,-569.201"/>
</g>
<!-- UserTraining -->
<g id="node73" class="node"><title>UserTraining</title>
@ -698,27 +709,27 @@
<text text-anchor="middle" x="1519" y="-442.3" font-family="Times,serif" font-size="14.00">UserTraining</text>
</g>
<!-- User&#45;&gt;UserTraining -->
<g id="edge51" class="edge"><title>User&#45;&gt;UserTraining</title>
<path fill="none" stroke="#0f88a6" d="M1272.25,-637.691C1346.24,-632.032 1513.73,-614.693 1548,-572 1570.93,-543.437 1552.44,-500.003 1536.28,-472.582"/>
<ellipse fill="none" stroke="#0f88a6" cx="1268.12" cy="-637.998" rx="4" ry="4"/>
<polygon fill="#0f88a6" stroke="#0f88a6" points="1536.2,-472.452 1534.79,-461.579 1533.58,-468.197 1530.96,-463.941 1530.96,-463.941 1530.96,-463.941 1533.58,-468.197 1527.12,-466.303 1536.2,-472.452 1536.2,-472.452"/>
<g id="edge52" class="edge"><title>User&#45;&gt;UserTraining</title>
<path fill="none" stroke="#d3106a" d="M1272.25,-637.691C1346.24,-632.032 1513.73,-614.693 1548,-572 1570.93,-543.437 1552.44,-500.003 1536.28,-472.582"/>
<ellipse fill="none" stroke="#d3106a" cx="1268.12" cy="-637.998" rx="4" ry="4"/>
<polygon fill="#d3106a" stroke="#d3106a" points="1536.2,-472.452 1534.79,-461.579 1533.58,-468.197 1530.96,-463.941 1530.96,-463.941 1530.96,-463.941 1533.58,-468.197 1527.12,-466.303 1536.2,-472.452 1536.2,-472.452"/>
</g>
<!-- User&#45;&gt;ProjectUser -->
<g id="edge49" class="edge"><title>User&#45;&gt;ProjectUser</title>
<path fill="none" stroke="#7a2965" d="M1201.99,-636.914C1072.52,-625.1 621.702,-580.257 493,-518 469.051,-506.415 446.161,-486.613 430.18,-470.861"/>
<ellipse fill="none" stroke="#7a2965" cx="1206.06" cy="-637.284" rx="4" ry="4"/>
<polygon fill="#7a2965" stroke="#7a2965" points="429.943,-470.621 426.117,-460.344 426.429,-467.064 422.916,-463.506 422.916,-463.506 422.916,-463.506 426.429,-467.064 419.714,-466.669 429.943,-470.621 429.943,-470.621"/>
<g id="edge50" class="edge"><title>User&#45;&gt;ProjectUser</title>
<path fill="none" stroke="#09601f" d="M1201.82,-637.38C1141.89,-632.659 1016.25,-621.64 911,-605 724.858,-575.572 666.281,-598.741 496,-518 471.459,-506.363 447.74,-486.566 431.123,-470.828"/>
<ellipse fill="none" stroke="#09601f" cx="1205.84" cy="-637.694" rx="4" ry="4"/>
<polygon fill="#09601f" stroke="#09601f" points="430.735,-470.451 426.7,-460.254 427.149,-466.966 423.563,-463.482 423.563,-463.482 423.563,-463.482 427.149,-466.966 420.427,-466.709 430.735,-470.451 430.735,-470.451"/>
</g>
<!-- Profile -->
<g id="node86" class="node"><title>Profile</title>
<g id="node87" class="node"><title>Profile</title>
<ellipse fill="none" stroke="black" cx="186" cy="-554" rx="34.394" ry="18"/>
<text text-anchor="middle" x="186" y="-550.3" font-family="Times,serif" font-size="14.00">Profile</text>
</g>
<!-- User&#45;&gt;Profile -->
<g id="edge47" class="edge"><title>User&#45;&gt;Profile</title>
<path fill="none" stroke="#ca2671" d="M1201.8,-638.045C1141.19,-634.714 1013.21,-627.829 905,-623 694.835,-613.621 640.88,-630.034 432,-605 357.757,-596.102 272.532,-576.672 224.394,-564.824"/>
<ellipse fill="none" stroke="#ca2671" cx="1205.9" cy="-638.271" rx="4" ry="4"/>
<ellipse fill="#ca2671" stroke="#ca2671" cx="220.304" cy="-563.81" rx="4.00001" ry="4.00001"/>
<g id="edge48" class="edge"><title>User&#45;&gt;Profile</title>
<path fill="none" stroke="#ce2222" d="M1201.8,-638.079C1141.18,-634.799 1013.2,-627.988 905,-623 709.932,-614.007 660.119,-626.213 466,-605 379.388,-595.535 279.157,-575.366 225.224,-563.743"/>
<ellipse fill="none" stroke="#ce2222" cx="1205.9" cy="-638.302" rx="4" ry="4"/>
<ellipse fill="#ce2222" stroke="#ce2222" cx="221.201" cy="-562.871" rx="4.00001" ry="4.00001"/>
</g>
<!-- ProjectStepImage -->
<g id="node42" class="node"><title>ProjectStepImage</title>
@ -726,132 +737,132 @@
<text text-anchor="middle" x="529" y="-334.3" font-family="Times,serif" font-size="14.00">ProjectStepImage</text>
</g>
<!-- Credit&#45;&gt;UsersCredit -->
<g id="edge62" class="edge"><title>Credit&#45;&gt;UsersCredit</title>
<path fill="none" stroke="#ac965c" d="M1406.51,-224.791C1405.93,-218.832 1405.3,-212.45 1404.7,-206.399"/>
<ellipse fill="none" stroke="#ac965c" cx="1406.91" cy="-228.832" rx="4" ry="4"/>
<polygon fill="#ac965c" stroke="#ac965c" points="1404.66,-205.981 1408.16,-195.587 1404.17,-201.005 1403.68,-196.029 1403.68,-196.029 1403.68,-196.029 1404.17,-201.005 1399.2,-196.47 1404.66,-205.981 1404.66,-205.981"/>
<g id="edge63" class="edge"><title>Credit&#45;&gt;UsersCredit</title>
<path fill="none" stroke="#80da29" d="M1408.36,-226.895C1403.88,-219.83 1398.93,-212.016 1394.34,-204.785"/>
<ellipse fill="none" stroke="#80da29" cx="1410.65" cy="-230.51" rx="4.00002" ry="4.00002"/>
<polygon fill="#80da29" stroke="#80da29" points="1394.15,-204.484 1392.6,-193.628 1391.47,-200.261 1388.8,-196.037 1388.8,-196.037 1388.8,-196.037 1391.47,-200.261 1385,-198.446 1394.15,-204.484 1394.15,-204.484"/>
</g>
<!-- PartnerPlan -->
<g id="node45" class="node"><title>PartnerPlan</title>
<ellipse fill="none" stroke="black" cx="1511" cy="-338" rx="51.9908" ry="18"/>
<text text-anchor="middle" x="1511" y="-334.3" font-family="Times,serif" font-size="14.00">PartnerPlan</text>
<ellipse fill="none" stroke="black" cx="1512" cy="-338" rx="51.9908" ry="18"/>
<text text-anchor="middle" x="1512" y="-334.3" font-family="Times,serif" font-size="14.00">PartnerPlan</text>
</g>
<!-- PartnerPlan&#45;&gt;Price -->
<g id="edge69" class="edge"><title>PartnerPlan&#45;&gt;Price</title>
<path fill="none" stroke="#da0c66" d="M1571.11,-335.268C1645.65,-332.235 1776.27,-324.011 1886,-302 1930.67,-293.039 1980.54,-276.338 2012.55,-264.716"/>
<ellipse fill="none" stroke="#da0c66" cx="1566.75" cy="-335.439" rx="4" ry="4"/>
<polygon fill="#da0c66" stroke="#da0c66" points="2012.9,-264.588 2023.84,-265.361 2017.59,-262.863 2022.28,-261.137 2022.28,-261.137 2022.28,-261.137 2017.59,-262.863 2020.73,-256.914 2012.9,-264.588 2012.9,-264.588"/>
<g id="edge70" class="edge"><title>PartnerPlan&#45;&gt;Price</title>
<path fill="none" stroke="#df8326" d="M1571.95,-335.253C1646.29,-332.205 1776.57,-323.967 1886,-302 1930.67,-293.033 1980.54,-276.334 2012.55,-264.713"/>
<ellipse fill="none" stroke="#df8326" cx="1567.61" cy="-335.425" rx="4" ry="4"/>
<polygon fill="#df8326" stroke="#df8326" points="2012.9,-264.585 2023.84,-265.359 2017.59,-262.86 2022.28,-261.135 2022.28,-261.135 2022.28,-261.135 2017.59,-262.86 2020.73,-256.912 2012.9,-264.585 2012.9,-264.585"/>
</g>
<!-- PartnerPlan&#45;&gt;PlanFile -->
<g id="edge68" class="edge"><title>PartnerPlan&#45;&gt;PlanFile</title>
<path fill="none" stroke="#c8b360" d="M1569.76,-332.741C1627,-327.739 1709.33,-318.023 1737,-302 1747.84,-295.725 1756.88,-285.29 1763.61,-275.571"/>
<ellipse fill="none" stroke="#c8b360" cx="1565.49" cy="-333.105" rx="4" ry="4"/>
<ellipse fill="#c8b360" stroke="#c8b360" cx="1765.92" cy="-272.042" rx="4.00002" ry="4.00002"/>
</g>
<!-- PartnerPlan&#45;&gt;Credit -->
<g id="edge63" class="edge"><title>PartnerPlan&#45;&gt;Credit</title>
<path fill="none" stroke="#11364d" d="M1452.72,-330.851C1434.82,-325.907 1416.96,-317.208 1406,-302 1401.21,-295.353 1400.35,-286.826 1401.18,-278.703"/>
<ellipse fill="none" stroke="#11364d" cx="1457.04" cy="-331.913" rx="4.00001" ry="4.00001"/>
<polygon fill="#11364d" stroke="#11364d" points="1401.19,-278.644 1407.39,-269.6 1402.08,-273.723 1402.96,-268.803 1402.96,-268.803 1402.96,-268.803 1402.08,-273.723 1398.53,-268.005 1401.19,-278.644 1401.19,-278.644"/>
<g id="edge69" class="edge"><title>PartnerPlan&#45;&gt;PlanFile</title>
<path fill="none" stroke="#270aba" d="M1570.75,-332.694C1627.73,-327.666 1709.49,-317.94 1737,-302 1747.84,-295.721 1756.88,-285.286 1763.61,-275.568"/>
<ellipse fill="none" stroke="#270aba" cx="1566.52" cy="-333.059" rx="4" ry="4"/>
<ellipse fill="#270aba" stroke="#270aba" cx="1765.91" cy="-272.039" rx="4.00002" ry="4.00002"/>
</g>
<!-- PartnerPlan&#45;&gt;Credit -->
<g id="edge64" class="edge"><title>PartnerPlan&#45;&gt;Credit</title>
<path fill="none" stroke="#41dd0a" d="M1461.18,-324.601C1448.35,-319.395 1435.5,-312.114 1426,-302 1420.02,-295.633 1416.14,-287.08 1413.62,-278.851"/>
<ellipse fill="none" stroke="#41dd0a" cx="1464.96" cy="-326.024" rx="4.00001" ry="4.00001"/>
<polygon fill="#41dd0a" stroke="#41dd0a" points="1413.62,-278.838 1415.54,-268.042 1412.39,-273.99 1411.17,-269.141 1411.17,-269.141 1411.17,-269.141 1412.39,-273.99 1406.81,-270.241 1413.62,-278.838 1413.62,-278.838"/>
<text text-anchor="middle" x="1468.5" y="-290.8" font-family="Times,serif" font-size="14.00">training_credits</text>
<path fill="none" stroke="#47abbb" d="M1453.91,-331.18C1435.59,-326.284 1417.23,-317.529 1406,-302 1400.64,-294.579 1402.04,-285.338 1405.76,-276.827"/>
<ellipse fill="none" stroke="#47abbb" cx="1457.85" cy="-332.121" rx="4.00001" ry="4.00001"/>
<polygon fill="#47abbb" stroke="#47abbb" points="1405.76,-276.816 1414.45,-270.121 1408.12,-272.407 1410.48,-267.998 1410.48,-267.998 1410.48,-267.998 1408.12,-272.407 1406.51,-265.875 1405.76,-276.816 1405.76,-276.816"/>
</g>
<!-- PartnerPlan&#45;&gt;Credit -->
<g id="edge65" class="edge"><title>PartnerPlan&#45;&gt;Credit</title>
<path fill="none" stroke="#17a9f9" d="M1516.64,-311.541C1517.13,-303.056 1515.99,-293.994 1511,-287 1497.47,-268.06 1473.03,-259.261 1451.47,-255.221"/>
<ellipse fill="none" stroke="#17a9f9" cx="1516.15" cy="-315.761" rx="4.00001" ry="4.00001"/>
<polygon fill="#17a9f9" stroke="#17a9f9" points="1451.37,-255.205 1442.2,-249.193 1446.43,-254.421 1441.49,-253.638 1441.49,-253.638 1441.49,-253.638 1446.43,-254.421 1440.79,-258.082 1451.37,-255.205 1451.37,-255.205"/>
<path fill="none" stroke="#0a76d4" d="M1459.33,-326.118C1446.46,-320.93 1434.09,-313.279 1426,-302 1421.35,-295.514 1419.65,-287.252 1419.38,-279.321"/>
<ellipse fill="none" stroke="#0a76d4" cx="1463.17" cy="-327.523" rx="4.00001" ry="4.00001"/>
<polygon fill="#0a76d4" stroke="#0a76d4" points="1419.38,-279.257 1424.22,-269.416 1419.55,-274.26 1419.72,-269.263 1419.72,-269.263 1419.72,-269.263 1419.55,-274.26 1415.22,-269.109 1419.38,-279.257 1419.38,-279.257"/>
<text text-anchor="middle" x="1468.5" y="-290.8" font-family="Times,serif" font-size="14.00">training_credits</text>
</g>
<!-- PartnerPlan&#45;&gt;Credit -->
<g id="edge66" class="edge"><title>PartnerPlan&#45;&gt;Credit</title>
<path fill="none" stroke="#8138d2" d="M1516.86,-311.62C1517.16,-303.142 1515.9,-294.064 1511,-287 1500.35,-271.638 1481.81,-263.017 1464.48,-258.18"/>
<ellipse fill="none" stroke="#8138d2" cx="1516.48" cy="-315.817" rx="4" ry="4"/>
<polygon fill="#8138d2" stroke="#8138d2" points="1464.2,-258.113 1455.55,-251.375 1459.34,-256.93 1454.48,-255.747 1454.48,-255.747 1454.48,-255.747 1459.34,-256.93 1453.42,-260.12 1464.2,-258.113 1464.2,-258.113"/>
<text text-anchor="middle" x="1562" y="-290.8" font-family="Times,serif" font-size="14.00">machine_credits</text>
</g>
<!-- PartnerPlan&#45;&gt;Role -->
<g id="edge70" class="edge"><title>PartnerPlan&#45;&gt;Role</title>
<path fill="none" stroke="#349cba" d="M1454.91,-329.627C1408.84,-323.265 1341.96,-313.33 1284,-302 1221.68,-289.819 1206.48,-284.859 1145,-269 1136.35,-266.77 1127.05,-264.244 1118.39,-261.834"/>
<ellipse fill="none" stroke="#349cba" cx="1459.02" cy="-330.19" rx="4.00001" ry="4.00001"/>
<polygon fill="#349cba" stroke="#349cba" points="1118.2,-261.783 1109.79,-254.75 1113.39,-260.433 1108.58,-259.083 1108.58,-259.083 1108.58,-259.083 1113.39,-260.433 1107.36,-263.416 1118.2,-261.783 1118.2,-261.783"/>
<g id="edge71" class="edge"><title>PartnerPlan&#45;&gt;Role</title>
<path fill="none" stroke="#02cf44" d="M1453.6,-332.129C1374.95,-324.425 1231.31,-306.302 1114,-269 1111.59,-268.233 1109.13,-267.359 1106.67,-266.42"/>
<ellipse fill="none" stroke="#02cf44" cx="1457.95" cy="-332.548" rx="4" ry="4"/>
<polygon fill="#02cf44" stroke="#02cf44" points="1106.61,-266.395 1099.09,-258.414 1101.99,-264.484 1097.37,-262.573 1097.37,-262.573 1097.37,-262.573 1101.99,-264.484 1095.65,-266.731 1106.61,-266.395 1106.61,-266.395"/>
</g>
<!-- PartnerPlan&#45;&gt;Subscription -->
<g id="edge66" class="edge"><title>PartnerPlan&#45;&gt;Subscription</title>
<path fill="none" stroke="#5b37a3" d="M1455.23,-329.432C1418.6,-323.707 1369.89,-314.653 1328,-302 1300.41,-293.665 1270.5,-281.083 1247.57,-270.626"/>
<ellipse fill="none" stroke="#5b37a3" cx="1459.38" cy="-330.067" rx="4.00001" ry="4.00001"/>
<polygon fill="#5b37a3" stroke="#5b37a3" points="1247.28,-270.49 1240.09,-262.209 1242.74,-268.392 1238.2,-266.293 1238.2,-266.293 1238.2,-266.293 1242.74,-268.392 1236.31,-270.378 1247.28,-270.49 1247.28,-270.49"/>
<g id="edge67" class="edge"><title>PartnerPlan&#45;&gt;Subscription</title>
<path fill="none" stroke="#9f5a82" d="M1457.36,-328.578C1420.53,-322.42 1371,-313.204 1328,-302 1308.07,-296.807 1259.95,-280.516 1223.54,-267.926"/>
<ellipse fill="none" stroke="#9f5a82" cx="1461.54" cy="-329.269" rx="4.00001" ry="4.00001"/>
<polygon fill="#9f5a82" stroke="#9f5a82" points="1223.54,-267.926 1215.57,-260.399 1218.82,-266.288 1214.09,-264.65 1214.09,-264.65 1214.09,-264.65 1218.82,-266.288 1212.62,-268.902 1223.54,-267.926 1223.54,-267.926"/>
</g>
<!-- PartnerPlan&#45;&gt;PlanImage -->
<g id="edge67" class="edge"><title>PartnerPlan&#45;&gt;PlanImage</title>
<path fill="none" stroke="#e5b6a6" d="M1569.34,-331.799C1620.16,-326.56 1695.57,-317.065 1760,-302 1798.38,-293.025 1840.91,-278.513 1871.03,-267.43"/>
<ellipse fill="none" stroke="#e5b6a6" cx="1565.07" cy="-332.232" rx="4" ry="4"/>
<ellipse fill="#e5b6a6" stroke="#e5b6a6" cx="1875.04" cy="-265.939" rx="4.00001" ry="4.00001"/>
<g id="edge68" class="edge"><title>PartnerPlan&#45;&gt;PlanImage</title>
<path fill="none" stroke="#d175e4" d="M1570.11,-331.779C1620.72,-326.526 1695.83,-317.023 1760,-302 1798.38,-293.014 1840.91,-278.504 1871.02,-267.423"/>
<ellipse fill="none" stroke="#d175e4" cx="1565.87" cy="-332.211" rx="4" ry="4"/>
<ellipse fill="#d175e4" stroke="#d175e4" cx="1875.04" cy="-265.933" rx="4.00001" ry="4.00001"/>
</g>
<!-- OAuth2Provider -->
<g id="node46" class="node"><title>OAuth2Provider</title>
<ellipse fill="none" stroke="black" cx="4508" cy="-735" rx="69.5877" ry="18"/>
<text text-anchor="middle" x="4508" y="-731.3" font-family="Times,serif" font-size="14.00">OAuth2Provider</text>
<ellipse fill="none" stroke="black" cx="4405" cy="-735" rx="69.5877" ry="18"/>
<text text-anchor="middle" x="4405" y="-731.3" font-family="Times,serif" font-size="14.00">OAuth2Provider</text>
</g>
<!-- OAuth2Provider&#45;&gt;OAuth2Mapping -->
<g id="edge72" class="edge"><title>OAuth2Provider&#45;&gt;OAuth2Mapping</title>
<path fill="none" stroke="#bc5f63" d="M4508,-708.451C4508,-696.315 4508,-681.795 4508,-669.427"/>
<ellipse fill="none" stroke="#bc5f63" cx="4508" cy="-712.696" rx="4" ry="4"/>
<polygon fill="#bc5f63" stroke="#bc5f63" points="4508,-669.227 4512.5,-659.227 4508,-664.227 4508,-659.227 4508,-659.227 4508,-659.227 4508,-664.227 4503.5,-659.227 4508,-669.227 4508,-669.227"/>
<g id="edge73" class="edge"><title>OAuth2Provider&#45;&gt;OAuth2Mapping</title>
<path fill="none" stroke="#0de20c" d="M4405,-708.451C4405,-696.315 4405,-681.795 4405,-669.427"/>
<ellipse fill="none" stroke="#0de20c" cx="4405" cy="-712.696" rx="4" ry="4"/>
<polygon fill="#0de20c" stroke="#0de20c" points="4405,-669.227 4409.5,-659.227 4405,-664.227 4405,-659.227 4405,-659.227 4405,-659.227 4405,-664.227 4400.5,-659.227 4405,-669.227 4405,-669.227"/>
</g>
<!-- AuthProvider -->
<g id="node71" class="node"><title>AuthProvider</title>
<ellipse fill="none" stroke="black" cx="4662" cy="-641" rx="58.4896" ry="18"/>
<text text-anchor="middle" x="4662" y="-637.3" font-family="Times,serif" font-size="14.00">AuthProvider</text>
<ellipse fill="none" stroke="black" cx="4559" cy="-641" rx="58.4896" ry="18"/>
<text text-anchor="middle" x="4559" y="-637.3" font-family="Times,serif" font-size="14.00">AuthProvider</text>
</g>
<!-- OAuth2Provider&#45;&gt;AuthProvider -->
<g id="edge71" class="edge"><title>OAuth2Provider&#45;&gt;AuthProvider</title>
<path fill="none" stroke="#f175dd" d="M4541.45,-714.015C4567.52,-698.44 4603.52,-676.937 4629.38,-661.49"/>
<ellipse fill="none" stroke="#f175dd" cx="4537.91" cy="-716.133" rx="4.00002" ry="4.00002"/>
<ellipse fill="#f175dd" stroke="#f175dd" cx="4632.95" cy="-659.355" rx="4.00002" ry="4.00002"/>
<g id="edge72" class="edge"><title>OAuth2Provider&#45;&gt;AuthProvider</title>
<path fill="none" stroke="#3cf1a6" d="M4438.45,-714.015C4464.52,-698.44 4500.52,-676.937 4526.38,-661.49"/>
<ellipse fill="none" stroke="#3cf1a6" cx="4434.91" cy="-716.133" rx="4.00002" ry="4.00002"/>
<ellipse fill="#3cf1a6" stroke="#3cf1a6" cx="4529.95" cy="-659.355" rx="4.00002" ry="4.00002"/>
</g>
<!-- Asset -->
<g id="node50" class="node"><title>Asset</title>
<ellipse fill="none" stroke="black" cx="4791" cy="-735" rx="30.5947" ry="18"/>
<text text-anchor="middle" x="4791" y="-731.3" font-family="Times,serif" font-size="14.00">Asset</text>
<ellipse fill="none" stroke="black" cx="4688" cy="-735" rx="30.5947" ry="18"/>
<text text-anchor="middle" x="4688" y="-731.3" font-family="Times,serif" font-size="14.00">Asset</text>
</g>
<!-- Project::OpenlabSync -->
<g id="node51" class="node"><title>Project::OpenlabSync</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="4974.5,-753 4839.5,-753 4839.5,-717 4974.5,-717 4974.5,-753"/>
<text text-anchor="middle" x="4907" y="-731.3" font-family="Times,serif" font-size="14.00">Project::OpenlabSync</text>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="4871.5,-753 4736.5,-753 4736.5,-717 4871.5,-717 4871.5,-753"/>
<text text-anchor="middle" x="4804" y="-731.3" font-family="Times,serif" font-size="14.00">Project::OpenlabSync</text>
</g>
<!-- DatabaseProvider -->
<g id="node52" class="node"><title>DatabaseProvider</title>
<ellipse fill="none" stroke="black" cx="4669" cy="-735" rx="73.387" ry="18"/>
<text text-anchor="middle" x="4669" y="-731.3" font-family="Times,serif" font-size="14.00">DatabaseProvider</text>
<ellipse fill="none" stroke="black" cx="4566" cy="-735" rx="73.387" ry="18"/>
<text text-anchor="middle" x="4566" y="-731.3" font-family="Times,serif" font-size="14.00">DatabaseProvider</text>
</g>
<!-- DatabaseProvider&#45;&gt;AuthProvider -->
<g id="edge73" class="edge"><title>DatabaseProvider&#45;&gt;AuthProvider</title>
<path fill="none" stroke="#c6bc71" d="M4667.06,-708.451C4666.09,-695.702 4664.92,-680.322 4663.95,-667.57"/>
<ellipse fill="none" stroke="#c6bc71" cx="4667.38" cy="-712.707" rx="4" ry="4"/>
<ellipse fill="#c6bc71" stroke="#c6bc71" cx="4663.61" cy="-663.215" rx="4" ry="4"/>
<g id="edge74" class="edge"><title>DatabaseProvider&#45;&gt;AuthProvider</title>
<path fill="none" stroke="#6c0c3f" d="M4564.06,-708.451C4563.09,-695.702 4561.92,-680.322 4560.95,-667.57"/>
<ellipse fill="none" stroke="#6c0c3f" cx="4564.38" cy="-712.707" rx="4" ry="4"/>
<ellipse fill="#6c0c3f" stroke="#6c0c3f" cx="4560.61" cy="-663.215" rx="4" ry="4"/>
</g>
<!-- Availability&#45;&gt;AvailabilityTag -->
<g id="edge81" class="edge"><title>Availability&#45;&gt;AvailabilityTag</title>
<path fill="none" stroke="#439dc7" d="M2467.44,-625.711C2484.03,-620.011 2502.65,-612.915 2519,-605 2535.73,-596.904 2553.34,-586.164 2567.77,-576.713"/>
<ellipse fill="none" stroke="#439dc7" cx="2463.26" cy="-627.117" rx="4.00001" ry="4.00001"/>
<polygon fill="#439dc7" stroke="#439dc7" points="2567.98,-576.572 2578.8,-574.776 2572.14,-573.801 2576.3,-571.03 2576.3,-571.03 2576.3,-571.03 2572.14,-573.801 2573.81,-567.284 2567.98,-576.572 2567.98,-576.572"/>
<g id="edge82" class="edge"><title>Availability&#45;&gt;AvailabilityTag</title>
<path fill="none" stroke="#e4b481" d="M2467.44,-625.711C2484.03,-620.011 2502.65,-612.915 2519,-605 2535.73,-596.904 2553.34,-586.164 2567.77,-576.713"/>
<ellipse fill="none" stroke="#e4b481" cx="2463.26" cy="-627.117" rx="4.00001" ry="4.00001"/>
<polygon fill="#e4b481" stroke="#e4b481" points="2567.98,-576.572 2578.8,-574.776 2572.14,-573.801 2576.3,-571.03 2576.3,-571.03 2576.3,-571.03 2572.14,-573.801 2573.81,-567.284 2567.98,-576.572 2567.98,-576.572"/>
</g>
<!-- Availability&#45;&gt;Event -->
<g id="edge80" class="edge"><title>Availability&#45;&gt;Event</title>
<path fill="none" stroke="#f5334f" d="M2470.53,-628.004C2541.93,-610.715 2672.12,-579.186 2735.45,-563.85"/>
<ellipse fill="none" stroke="#f5334f" cx="2466.53" cy="-628.974" rx="4.00001" ry="4.00001"/>
<ellipse fill="#f5334f" stroke="#f5334f" cx="2739.68" cy="-562.827" rx="4.00001" ry="4.00001"/>
<g id="edge81" class="edge"><title>Availability&#45;&gt;Event</title>
<path fill="none" stroke="#4b95ef" d="M2470.53,-628.004C2541.93,-610.715 2672.12,-579.186 2735.45,-563.85"/>
<ellipse fill="none" stroke="#4b95ef" cx="2466.53" cy="-628.974" rx="4.00001" ry="4.00001"/>
<ellipse fill="#4b95ef" stroke="#4b95ef" cx="2739.68" cy="-562.827" rx="4.00001" ry="4.00001"/>
</g>
<!-- Availability&#45;&gt;Training -->
<g id="edge77" class="edge"><title>Availability&#45;&gt;Training</title>
<path fill="none" stroke="#d85d7d" d="M2364.42,-630.723C2323.87,-623.946 2267.99,-614.345 2219,-605 2186.89,-598.876 2179.25,-595.337 2147,-590 2065.33,-576.484 1969.66,-565.735 1912.81,-559.877"/>
<polygon fill="#d85d7d" stroke="#d85d7d" points="2364.52,-630.739 2373.65,-636.822 2369.45,-631.561 2374.38,-632.383 2374.38,-632.383 2374.38,-632.383 2369.45,-631.561 2375.12,-627.944 2364.52,-630.739 2364.52,-630.739"/>
<polygon fill="#d85d7d" stroke="#d85d7d" points="1912.61,-559.856 1903.12,-554.364 1907.63,-559.348 1902.66,-558.84 1902.66,-558.84 1902.66,-558.84 1907.63,-559.348 1902.2,-563.317 1912.61,-559.856 1912.61,-559.856"/>
<g id="edge78" class="edge"><title>Availability&#45;&gt;Training</title>
<path fill="none" stroke="#4ecbfa" d="M2365.92,-629.711C2329.57,-622.859 2280.91,-613.573 2238,-605 2205.95,-598.596 2198.27,-595.214 2166,-590 2077.3,-575.667 1973.06,-564.958 1912.86,-559.365"/>
<polygon fill="#4ecbfa" stroke="#4ecbfa" points="2366.01,-629.726 2375,-635.998 2370.92,-630.651 2375.84,-631.576 2375.84,-631.576 2375.84,-631.576 2370.92,-630.651 2376.67,-627.153 2366.01,-629.726 2366.01,-629.726"/>
<polygon fill="#4ecbfa" stroke="#4ecbfa" points="1912.82,-559.362 1903.28,-553.965 1907.84,-558.904 1902.86,-558.447 1902.86,-558.447 1902.86,-558.447 1907.84,-558.904 1902.45,-562.928 1912.82,-559.362 1912.82,-559.362"/>
</g>
<!-- Availability&#45;&gt;Reservation -->
<g id="edge79" class="edge"><title>Availability&#45;&gt;Reservation</title>
<path fill="none" stroke="#ce33b9" d="M2431.88,-613.533C2432.97,-610.667 2434.03,-607.782 2435,-605 2465.07,-518.52 2494.03,-413.837 2506.96,-365.644"/>
<polygon fill="#ce33b9" stroke="#ce33b9" points="2431.81,-613.721 2423.96,-621.383 2429.98,-618.375 2428.15,-623.028 2428.15,-623.028 2428.15,-623.028 2429.98,-618.375 2432.34,-624.674 2431.81,-613.721 2431.81,-613.721"/>
<polygon fill="#ce33b9" stroke="#ce33b9" points="2506.96,-365.638 2513.89,-357.138 2508.25,-360.808 2509.54,-355.977 2509.54,-355.977 2509.54,-355.977 2508.25,-360.808 2505.19,-354.816 2506.96,-365.638 2506.96,-365.638"/>
<g id="edge80" class="edge"><title>Availability&#45;&gt;Reservation</title>
<path fill="none" stroke="#87cd86" d="M2431.88,-613.533C2432.97,-610.667 2434.03,-607.782 2435,-605 2465.07,-518.52 2494.03,-413.837 2506.96,-365.644"/>
<polygon fill="#87cd86" stroke="#87cd86" points="2431.81,-613.721 2423.96,-621.383 2429.98,-618.375 2428.15,-623.028 2428.15,-623.028 2428.15,-623.028 2429.98,-618.375 2432.34,-624.674 2431.81,-613.721 2431.81,-613.721"/>
<polygon fill="#87cd86" stroke="#87cd86" points="2506.96,-365.638 2513.89,-357.138 2508.25,-360.808 2509.54,-355.977 2509.54,-355.977 2509.54,-355.977 2508.25,-360.808 2505.19,-354.816 2506.96,-365.638 2506.96,-365.638"/>
</g>
<!-- Slot -->
<g id="node63" class="node"><title>Slot</title>
@ -859,10 +870,10 @@
<text text-anchor="middle" x="2556" y="-247.3" font-family="Times,serif" font-size="14.00">Slot</text>
</g>
<!-- Availability&#45;&gt;Slot -->
<g id="edge78" class="edge"><title>Availability&#45;&gt;Slot</title>
<path fill="none" stroke="#0bc0ea" d="M2442.42,-617.544C2445.81,-613.512 2449.14,-609.239 2452,-605 2521.14,-502.509 2547.69,-476.345 2576,-356 2582.19,-329.698 2574.68,-299.323 2567.16,-278.218"/>
<ellipse fill="none" stroke="#0bc0ea" cx="2439.72" cy="-620.633" rx="4.00002" ry="4.00002"/>
<polygon fill="#0bc0ea" stroke="#0bc0ea" points="2567.08,-278.008 2567.74,-267.062 2565.31,-273.334 2563.53,-268.66 2563.53,-268.66 2563.53,-268.66 2565.31,-273.334 2559.32,-270.259 2567.08,-278.008 2567.08,-278.008"/>
<g id="edge79" class="edge"><title>Availability&#45;&gt;Slot</title>
<path fill="none" stroke="#017a97" d="M2442.42,-617.544C2445.81,-613.512 2449.14,-609.239 2452,-605 2521.14,-502.509 2547.69,-476.345 2576,-356 2582.19,-329.698 2574.68,-299.323 2567.16,-278.218"/>
<ellipse fill="none" stroke="#017a97" cx="2439.72" cy="-620.633" rx="4.00002" ry="4.00002"/>
<polygon fill="#017a97" stroke="#017a97" points="2567.08,-278.008 2567.74,-267.062 2565.31,-273.334 2563.53,-268.66 2563.53,-268.66 2563.53,-268.66 2565.31,-273.334 2559.32,-270.259 2567.08,-278.008 2567.08,-278.008"/>
</g>
<!-- MachinesAvailability -->
<g id="node68" class="node"><title>MachinesAvailability</title>
@ -870,287 +881,287 @@
<text text-anchor="middle" x="2356" y="-334.3" font-family="Times,serif" font-size="14.00">MachinesAvailability</text>
</g>
<!-- Availability&#45;&gt;MachinesAvailability -->
<g id="edge74" class="edge"><title>Availability&#45;&gt;MachinesAvailability</title>
<path fill="none" stroke="#781e49" d="M2420.72,-614.486C2419.93,-582.999 2417.06,-527.982 2407,-482 2397.82,-440.08 2379.69,-393.644 2367.71,-365.39"/>
<ellipse fill="none" stroke="#781e49" cx="2420.81" cy="-618.717" rx="4" ry="4"/>
<polygon fill="#781e49" stroke="#781e49" points="2367.7,-365.377 2367.88,-354.412 2365.73,-360.784 2363.75,-356.191 2363.75,-356.191 2363.75,-356.191 2365.73,-360.784 2359.62,-357.97 2367.7,-365.377 2367.7,-365.377"/>
<g id="edge75" class="edge"><title>Availability&#45;&gt;MachinesAvailability</title>
<path fill="none" stroke="#29ed19" d="M2420.72,-614.486C2419.93,-582.999 2417.06,-527.982 2407,-482 2397.82,-440.08 2379.69,-393.644 2367.71,-365.39"/>
<ellipse fill="none" stroke="#29ed19" cx="2420.81" cy="-618.717" rx="4" ry="4"/>
<polygon fill="#29ed19" stroke="#29ed19" points="2367.7,-365.377 2367.88,-354.412 2365.73,-360.784 2363.75,-356.191 2363.75,-356.191 2363.75,-356.191 2365.73,-360.784 2359.62,-357.97 2367.7,-365.377 2367.7,-365.377"/>
</g>
<!-- TrainingsAvailability -->
<g id="node79" class="node"><title>TrainingsAvailability</title>
<g id="node80" class="node"><title>TrainingsAvailability</title>
<ellipse fill="none" stroke="black" cx="2201" cy="-446" rx="86.3847" ry="18"/>
<text text-anchor="middle" x="2201" y="-442.3" font-family="Times,serif" font-size="14.00">TrainingsAvailability</text>
</g>
<!-- Availability&#45;&gt;TrainingsAvailability -->
<g id="edge76" class="edge"><title>Availability&#45;&gt;TrainingsAvailability</title>
<path fill="none" stroke="#0e6bb8" d="M2396.45,-618.467C2354.81,-581.936 2270.66,-508.115 2227.64,-470.372"/>
<ellipse fill="none" stroke="#0e6bb8" cx="2399.61" cy="-621.239" rx="4.00002" ry="4.00002"/>
<polygon fill="#0e6bb8" stroke="#0e6bb8" points="2227.62,-470.356 2223.07,-460.379 2223.87,-467.059 2220.11,-463.762 2220.11,-463.762 2220.11,-463.762 2223.87,-467.059 2217.14,-467.144 2227.62,-470.356 2227.62,-470.356"/>
<g id="edge77" class="edge"><title>Availability&#45;&gt;TrainingsAvailability</title>
<path fill="none" stroke="#d8d953" d="M2396.45,-618.467C2354.81,-581.936 2270.66,-508.115 2227.64,-470.372"/>
<ellipse fill="none" stroke="#d8d953" cx="2399.61" cy="-621.239" rx="4.00002" ry="4.00002"/>
<polygon fill="#d8d953" stroke="#d8d953" points="2227.62,-470.356 2223.07,-460.379 2223.87,-467.059 2220.11,-463.762 2220.11,-463.762 2220.11,-463.762 2223.87,-467.059 2217.14,-467.144 2227.62,-470.356 2227.62,-470.356"/>
</g>
<!-- Availability&#45;&gt;Machine -->
<g id="edge75" class="edge"><title>Availability&#45;&gt;Machine</title>
<path fill="none" stroke="#c0fada" d="M2377.39,-623.562C2279.55,-586.682 2043.73,-497.787 1949.19,-462.151"/>
<polygon fill="#c0fada" stroke="#c0fada" points="2377.65,-623.66 2385.42,-631.398 2382.33,-625.424 2387.01,-627.187 2387.01,-627.187 2387.01,-627.187 2382.33,-625.424 2388.6,-622.976 2377.65,-623.66 2377.65,-623.66"/>
<polygon fill="#c0fada" stroke="#c0fada" points="1949.06,-462.1 1941.29,-454.362 1944.38,-460.336 1939.7,-458.573 1939.7,-458.573 1939.7,-458.573 1944.38,-460.336 1938.11,-462.783 1949.06,-462.1 1949.06,-462.1"/>
<g id="edge76" class="edge"><title>Availability&#45;&gt;Machine</title>
<path fill="none" stroke="#7ba192" d="M2377.39,-623.562C2279.55,-586.682 2043.73,-497.787 1949.19,-462.151"/>
<polygon fill="#7ba192" stroke="#7ba192" points="2377.65,-623.66 2385.42,-631.398 2382.33,-625.424 2387.01,-627.187 2387.01,-627.187 2387.01,-627.187 2382.33,-625.424 2388.6,-622.976 2377.65,-623.66 2377.65,-623.66"/>
<polygon fill="#7ba192" stroke="#7ba192" points="1949.06,-462.1 1941.29,-454.362 1944.38,-460.336 1939.7,-458.573 1939.7,-458.573 1939.7,-458.573 1944.38,-460.336 1938.11,-462.783 1949.06,-462.1 1949.06,-462.1"/>
</g>
<!-- Subscription&#45;&gt;Invoice -->
<g id="edge82" class="edge"><title>Subscription&#45;&gt;Invoice</title>
<path fill="none" stroke="#fe51f2" d="M1208.99,-224.635C1210.38,-204.372 1215.68,-176.692 1233,-160 1268.79,-125.513 1411.43,-105.159 1486.02,-96.6679"/>
<ellipse fill="none" stroke="#fe51f2" cx="1208.79" cy="-228.816" rx="4" ry="4"/>
<polygon fill="#fe51f2" stroke="#fe51f2" points="1486.13,-96.655 1496.57,-100.021 1491.1,-96.1017 1496.07,-95.5483 1496.07,-95.5483 1496.07,-95.5483 1491.1,-96.1017 1495.57,-91.0759 1486.13,-96.655 1486.13,-96.655"/>
<g id="edge83" class="edge"><title>Subscription&#45;&gt;Invoice</title>
<path fill="none" stroke="#548f57" d="M1180.37,-224.669C1183.53,-204.666 1190.88,-177.326 1208,-160 1248.07,-119.437 1313.54,-103.038 1357.66,-96.4286"/>
<ellipse fill="none" stroke="#548f57" cx="1179.81" cy="-228.78" rx="4.00001" ry="4.00001"/>
<polygon fill="#548f57" stroke="#548f57" points="1357.94,-96.391 1368.46,-99.478 1362.89,-95.7057 1367.84,-95.0204 1367.84,-95.0204 1367.84,-95.0204 1362.89,-95.7057 1367.22,-90.5629 1357.94,-96.391 1357.94,-96.391"/>
</g>
<!-- Subscription&#45;&gt;OfferDay -->
<g id="edge83" class="edge"><title>Subscription&#45;&gt;OfferDay</title>
<path fill="none" stroke="#f891fa" d="M1232.39,-228.437C1241.57,-219.971 1252.11,-210.249 1261.41,-201.678"/>
<ellipse fill="none" stroke="#f891fa" cx="1229.41" cy="-231.177" rx="4.00002" ry="4.00002"/>
<polygon fill="#f891fa" stroke="#f891fa" points="1261.51,-201.582 1271.91,-198.111 1265.19,-198.192 1268.86,-194.803 1268.86,-194.803 1268.86,-194.803 1265.19,-198.192 1265.81,-191.494 1261.51,-201.582 1261.51,-201.582"/>
<g id="edge84" class="edge"><title>Subscription&#45;&gt;OfferDay</title>
<path fill="none" stroke="#885f8a" d="M1203.25,-228.397C1213.32,-219.783 1224.91,-209.873 1235.05,-201.201"/>
<ellipse fill="none" stroke="#885f8a" cx="1199.87" cy="-231.289" rx="4.00002" ry="4.00002"/>
<polygon fill="#885f8a" stroke="#885f8a" points="1235.21,-201.06 1245.74,-197.979 1239.01,-197.81 1242.81,-194.559 1242.81,-194.559 1242.81,-194.559 1239.01,-197.81 1239.89,-191.14 1235.21,-201.06 1235.21,-201.06"/>
</g>
<!-- Training&#45;&gt;TrainingImage -->
<g id="edge84" class="edge"><title>Training&#45;&gt;TrainingImage</title>
<path fill="none" stroke="#8d45e3" d="M1892.63,-534.527C1922.82,-515.698 1969.53,-486.577 2000.67,-467.161"/>
<ellipse fill="none" stroke="#8d45e3" cx="1888.97" cy="-536.808" rx="4.00002" ry="4.00002"/>
<ellipse fill="#8d45e3" stroke="#8d45e3" cx="2004.45" cy="-464.805" rx="4.00002" ry="4.00002"/>
<g id="edge85" class="edge"><title>Training&#45;&gt;TrainingImage</title>
<path fill="none" stroke="#906a44" d="M1892.63,-534.527C1922.82,-515.698 1969.53,-486.577 2000.67,-467.161"/>
<ellipse fill="none" stroke="#906a44" cx="1888.97" cy="-536.808" rx="4.00002" ry="4.00002"/>
<ellipse fill="#906a44" stroke="#906a44" cx="2004.45" cy="-464.805" rx="4.00002" ry="4.00002"/>
</g>
<!-- Training&#45;&gt;TrainingsPricing -->
<g id="edge89" class="edge"><title>Training&#45;&gt;TrainingsPricing</title>
<path fill="none" stroke="#c75c61" d="M1824.04,-539.025C1811.54,-533.533 1798.08,-526.487 1787,-518 1770.47,-505.332 1772.58,-495.82 1757,-482 1751.48,-477.107 1745.22,-472.411 1738.97,-468.135"/>
<ellipse fill="none" stroke="#c75c61" cx="1827.99" cy="-540.688" rx="4.00001" ry="4.00001"/>
<polygon fill="#c75c61" stroke="#c75c61" points="1738.87,-468.072 1732.98,-458.824 1734.69,-465.329 1730.51,-462.586 1730.51,-462.586 1730.51,-462.586 1734.69,-465.329 1728.04,-466.348 1738.87,-468.072 1738.87,-468.072"/>
<g id="edge90" class="edge"><title>Training&#45;&gt;TrainingsPricing</title>
<path fill="none" stroke="#658e60" d="M1824.04,-539.025C1811.54,-533.533 1798.08,-526.487 1787,-518 1770.47,-505.332 1772.58,-495.82 1757,-482 1751.48,-477.107 1745.22,-472.411 1738.97,-468.135"/>
<ellipse fill="none" stroke="#658e60" cx="1827.99" cy="-540.688" rx="4.00001" ry="4.00001"/>
<polygon fill="#658e60" stroke="#658e60" points="1738.87,-468.072 1732.98,-458.824 1734.69,-465.329 1730.51,-462.586 1730.51,-462.586 1730.51,-462.586 1734.69,-465.329 1728.04,-466.348 1738.87,-468.072 1738.87,-468.072"/>
</g>
<!-- Training&#45;&gt;Plan -->
<g id="edge91" class="edge"><title>Training&#45;&gt;Plan</title>
<path fill="none" stroke="#7cdde0" d="M1859.3,-525.685C1853.72,-484.505 1843.21,-406.991 1837.66,-365.998"/>
<polygon fill="#7cdde0" stroke="#7cdde0" points="1859.33,-525.94 1856.22,-536.454 1860,-530.895 1860.68,-535.849 1860.68,-535.849 1860.68,-535.849 1860,-530.895 1865.14,-535.245 1859.33,-525.94 1859.33,-525.94"/>
<polygon fill="#7cdde0" stroke="#7cdde0" points="1837.64,-365.845 1840.75,-355.331 1836.97,-360.89 1836.29,-355.935 1836.29,-355.935 1836.29,-355.935 1836.97,-360.89 1831.84,-356.54 1837.64,-365.845 1837.64,-365.845"/>
<g id="edge92" class="edge"><title>Training&#45;&gt;Plan</title>
<path fill="none" stroke="#8fe863" d="M1859.3,-525.685C1853.72,-484.505 1843.21,-406.991 1837.66,-365.998"/>
<polygon fill="#8fe863" stroke="#8fe863" points="1859.33,-525.94 1856.22,-536.454 1860,-530.895 1860.68,-535.849 1860.68,-535.849 1860.68,-535.849 1860,-530.895 1865.14,-535.245 1859.33,-525.94 1859.33,-525.94"/>
<polygon fill="#8fe863" stroke="#8fe863" points="1837.64,-365.845 1840.75,-355.331 1836.97,-360.89 1836.29,-355.935 1836.29,-355.935 1836.29,-355.935 1836.97,-360.89 1831.84,-356.54 1837.64,-365.845 1837.64,-365.845"/>
</g>
<!-- Training&#45;&gt;Credit -->
<g id="edge90" class="edge"><title>Training&#45;&gt;Credit</title>
<path fill="none" stroke="#7b61fa" d="M1853.77,-528.162C1841.77,-499.419 1817.97,-452.86 1782,-428 1657.79,-342.163 1581.85,-429.564 1450,-356 1420.9,-339.766 1410.46,-332.901 1398,-302 1395,-294.549 1395.48,-286.126 1397.37,-278.346"/>
<ellipse fill="none" stroke="#7b61fa" cx="1855.35" cy="-532.056" rx="4.00001" ry="4.00001"/>
<polygon fill="#7b61fa" stroke="#7b61fa" points="1397.44,-278.149 1404.77,-269.999 1398.96,-273.388 1400.49,-268.626 1400.49,-268.626 1400.49,-268.626 1398.96,-273.388 1396.2,-267.253 1397.44,-278.149 1397.44,-278.149"/>
<g id="edge91" class="edge"><title>Training&#45;&gt;Credit</title>
<path fill="none" stroke="#7008ed" d="M1853.77,-528.166C1841.76,-499.426 1817.97,-452.871 1782,-428 1658.17,-342.371 1582.45,-429.394 1451,-356 1421.91,-339.757 1411.46,-332.901 1399,-302 1395.51,-293.343 1398.1,-284.073 1402.68,-275.896"/>
<ellipse fill="none" stroke="#7008ed" cx="1855.34" cy="-532.059" rx="4.00001" ry="4.00001"/>
<polygon fill="#7008ed" stroke="#7008ed" points="1402.69,-275.868 1411.97,-270.017 1405.46,-271.7 1408.22,-267.532 1408.22,-267.532 1408.22,-267.532 1405.46,-271.7 1404.47,-265.046 1402.69,-275.868 1402.69,-275.868"/>
</g>
<!-- Training&#45;&gt;Reservation -->
<g id="edge87" class="edge"><title>Training&#45;&gt;Reservation</title>
<path fill="none" stroke="#d1f3d0" d="M1908.32,-544.643C1945.39,-537.732 1999.15,-527.539 2046,-518 2157.39,-495.321 2192.49,-510.987 2296,-464 2357.03,-436.296 2357.96,-405.714 2417,-374 2432.15,-365.862 2449.59,-358.903 2465.47,-353.385"/>
<ellipse fill="none" stroke="#d1f3d0" cx="1904.14" cy="-545.421" rx="4.00001" ry="4.00001"/>
<polygon fill="#d1f3d0" stroke="#d1f3d0" points="2465.64,-353.327 2476.55,-354.402 2470.38,-351.732 2475.11,-350.137 2475.11,-350.137 2475.11,-350.137 2470.38,-351.732 2473.68,-345.872 2465.64,-353.327 2465.64,-353.327"/>
<g id="edge88" class="edge"><title>Training&#45;&gt;Reservation</title>
<path fill="none" stroke="#3bf1eb" d="M1908.32,-544.643C1945.39,-537.732 1999.15,-527.539 2046,-518 2157.39,-495.321 2192.49,-510.987 2296,-464 2357.03,-436.296 2357.96,-405.714 2417,-374 2432.15,-365.862 2449.59,-358.903 2465.47,-353.385"/>
<ellipse fill="none" stroke="#3bf1eb" cx="1904.14" cy="-545.421" rx="4.00001" ry="4.00001"/>
<polygon fill="#3bf1eb" stroke="#3bf1eb" points="2465.64,-353.327 2476.55,-354.402 2470.38,-351.732 2475.11,-350.137 2475.11,-350.137 2475.11,-350.137 2470.38,-351.732 2473.68,-345.872 2465.64,-353.327 2465.64,-353.327"/>
</g>
<!-- Training&#45;&gt;UserTraining -->
<g id="edge88" class="edge"><title>Training&#45;&gt;UserTraining</title>
<path fill="none" stroke="#4357a7" d="M1822.55,-540.535C1759.16,-521.001 1636.6,-483.238 1568.2,-462.16"/>
<ellipse fill="none" stroke="#4357a7" cx="1826.5" cy="-541.754" rx="4.00001" ry="4.00001"/>
<polygon fill="#4357a7" stroke="#4357a7" points="1568.07,-462.12 1559.84,-454.875 1563.29,-460.648 1558.51,-459.176 1558.51,-459.176 1558.51,-459.176 1563.29,-460.648 1557.19,-463.476 1568.07,-462.12 1568.07,-462.12"/>
<g id="edge89" class="edge"><title>Training&#45;&gt;UserTraining</title>
<path fill="none" stroke="#3b526f" d="M1822.55,-540.535C1759.16,-521.001 1636.6,-483.238 1568.2,-462.16"/>
<ellipse fill="none" stroke="#3b526f" cx="1826.5" cy="-541.754" rx="4.00001" ry="4.00001"/>
<polygon fill="#3b526f" stroke="#3b526f" points="1568.07,-462.12 1559.84,-454.875 1563.29,-460.648 1558.51,-459.176 1558.51,-459.176 1558.51,-459.176 1563.29,-460.648 1557.19,-463.476 1568.07,-462.12 1568.07,-462.12"/>
</g>
<!-- Training&#45;&gt;TrainingsAvailability -->
<g id="edge86" class="edge"><title>Training&#45;&gt;TrainingsAvailability</title>
<path fill="none" stroke="#74484d" d="M1903.19,-540.395C1963.49,-521.484 2077.55,-485.715 2145.67,-464.351"/>
<ellipse fill="none" stroke="#74484d" cx="1899.23" cy="-541.639" rx="4.00001" ry="4.00001"/>
<polygon fill="#74484d" stroke="#74484d" points="2145.84,-464.3 2156.72,-465.601 2150.61,-462.804 2155.38,-461.308 2155.38,-461.308 2155.38,-461.308 2150.61,-462.804 2154.03,-457.014 2145.84,-464.3 2145.84,-464.3"/>
<g id="edge87" class="edge"><title>Training&#45;&gt;TrainingsAvailability</title>
<path fill="none" stroke="#c1eafa" d="M1903.19,-540.395C1963.49,-521.484 2077.55,-485.715 2145.67,-464.351"/>
<ellipse fill="none" stroke="#c1eafa" cx="1899.23" cy="-541.639" rx="4.00001" ry="4.00001"/>
<polygon fill="#c1eafa" stroke="#c1eafa" points="2145.84,-464.3 2156.72,-465.601 2150.61,-462.804 2155.38,-461.308 2155.38,-461.308 2155.38,-461.308 2150.61,-462.804 2154.03,-457.014 2145.84,-464.3 2145.84,-464.3"/>
</g>
<!-- Training&#45;&gt;Machine -->
<g id="edge85" class="edge"><title>Training&#45;&gt;Machine</title>
<path fill="none" stroke="#c9666f" d="M1874.42,-526.676C1881.47,-510.445 1890.47,-489.7 1897.52,-473.447"/>
<polygon fill="#c9666f" stroke="#c9666f" points="1874.37,-526.796 1866.26,-534.178 1872.38,-531.383 1870.39,-535.969 1870.39,-535.969 1870.39,-535.969 1872.38,-531.383 1874.52,-537.761 1874.37,-526.796 1874.37,-526.796"/>
<polygon fill="#c9666f" stroke="#c9666f" points="1897.65,-473.162 1905.76,-465.78 1899.64,-468.575 1901.63,-463.988 1901.63,-463.988 1901.63,-463.988 1899.64,-468.575 1897.5,-462.197 1897.65,-473.162 1897.65,-473.162"/>
<g id="edge86" class="edge"><title>Training&#45;&gt;Machine</title>
<path fill="none" stroke="#49d7f2" d="M1874.42,-526.676C1881.47,-510.445 1890.47,-489.7 1897.52,-473.447"/>
<polygon fill="#49d7f2" stroke="#49d7f2" points="1874.37,-526.796 1866.26,-534.178 1872.38,-531.383 1870.39,-535.969 1870.39,-535.969 1870.39,-535.969 1872.38,-531.383 1874.52,-537.761 1874.37,-526.796 1874.37,-526.796"/>
<polygon fill="#49d7f2" stroke="#49d7f2" points="1897.65,-473.162 1905.76,-465.78 1899.64,-468.575 1901.63,-463.988 1901.63,-463.988 1901.63,-463.988 1899.64,-468.575 1897.5,-462.197 1897.65,-473.162 1897.65,-473.162"/>
</g>
<!-- ProjectStep&#45;&gt;ProjectStepImage -->
<g id="edge92" class="edge"><title>ProjectStep&#45;&gt;ProjectStepImage</title>
<path fill="none" stroke="#2be6fd" d="M529,-419.795C529,-403.123 529,-381.335 529,-364.586"/>
<ellipse fill="none" stroke="#2be6fd" cx="529" cy="-423.969" rx="4" ry="4"/>
<ellipse fill="#2be6fd" stroke="#2be6fd" cx="529" cy="-360.341" rx="4" ry="4"/>
<g id="edge93" class="edge"><title>ProjectStep&#45;&gt;ProjectStepImage</title>
<path fill="none" stroke="#d7b035" d="M529,-419.795C529,-403.123 529,-381.335 529,-364.586"/>
<ellipse fill="none" stroke="#d7b035" cx="529" cy="-423.969" rx="4" ry="4"/>
<ellipse fill="#d7b035" stroke="#d7b035" cx="529" cy="-360.341" rx="4" ry="4"/>
</g>
<!-- Reservation&#45;&gt;Invoice -->
<g id="edge95" class="edge"><title>Reservation&#45;&gt;Invoice</title>
<path fill="none" stroke="#880fca" d="M2466.87,-323.889C2461.85,-322.551 2456.83,-321.232 2452,-320 2289.16,-278.439 2249.92,-259.76 2084,-233 1898.56,-203.092 1837.48,-265.555 1663,-196 1617.49,-177.859 1575.07,-138.463 1551.44,-113.704"/>
<ellipse fill="none" stroke="#880fca" cx="2470.84" cy="-324.958" rx="4.00001" ry="4.00001"/>
<ellipse fill="#880fca" stroke="#880fca" cx="1548.58" cy="-110.662" rx="4.00002" ry="4.00002"/>
<g id="edge96" class="edge"><title>Reservation&#45;&gt;Invoice</title>
<path fill="none" stroke="#ce1d45" d="M2468.49,-323.097C2390.59,-299.959 2226.33,-254.018 2084,-233 1950.75,-213.322 1596.98,-260.995 1479,-196 1462.35,-186.83 1434.55,-143.629 1417.88,-115.871"/>
<ellipse fill="none" stroke="#ce1d45" cx="2472.37" cy="-324.255" rx="4.00001" ry="4.00001"/>
<ellipse fill="#ce1d45" stroke="#ce1d45" cx="1415.73" cy="-112.272" rx="4.00002" ry="4.00002"/>
</g>
<!-- Reservation&#45;&gt;Slot -->
<g id="edge93" class="edge"><title>Reservation&#45;&gt;Slot</title>
<path fill="none" stroke="#164c5f" d="M2525.99,-312.728C2531.41,-301.764 2537.81,-288.804 2543.31,-277.678"/>
<ellipse fill="none" stroke="#164c5f" cx="2524.07" cy="-316.621" rx="4.00002" ry="4.00002"/>
<polygon fill="#164c5f" stroke="#164c5f" points="2543.43,-277.434 2551.9,-270.463 2545.65,-272.952 2547.86,-268.469 2547.86,-268.469 2547.86,-268.469 2545.65,-272.952 2543.83,-266.476 2543.43,-277.434 2543.43,-277.434"/>
<g id="edge94" class="edge"><title>Reservation&#45;&gt;Slot</title>
<path fill="none" stroke="#4264e8" d="M2525.99,-312.728C2531.41,-301.764 2537.81,-288.804 2543.31,-277.678"/>
<ellipse fill="none" stroke="#4264e8" cx="2524.07" cy="-316.621" rx="4.00002" ry="4.00002"/>
<polygon fill="#4264e8" stroke="#4264e8" points="2543.43,-277.434 2551.9,-270.463 2545.65,-272.952 2547.86,-268.469 2547.86,-268.469 2547.86,-268.469 2545.65,-272.952 2543.83,-266.476 2543.43,-277.434 2543.43,-277.434"/>
</g>
<!-- Ticket -->
<g id="node88" class="node"><title>Ticket</title>
<g id="node89" class="node"><title>Ticket</title>
<ellipse fill="none" stroke="black" cx="2702" cy="-251" rx="33.2948" ry="18"/>
<text text-anchor="middle" x="2702" y="-247.3" font-family="Times,serif" font-size="14.00">Ticket</text>
</g>
<!-- Reservation&#45;&gt;Ticket -->
<g id="edge94" class="edge"><title>Reservation&#45;&gt;Ticket</title>
<path fill="none" stroke="#f3421c" d="M2552.31,-319.678C2586.37,-304.282 2635.66,-281.992 2668.26,-267.256"/>
<ellipse fill="none" stroke="#f3421c" cx="2548.27" cy="-321.506" rx="4.00002" ry="4.00002"/>
<polygon fill="#f3421c" stroke="#f3421c" points="2668.28,-267.247 2679.24,-267.228 2672.83,-265.187 2677.39,-263.127 2677.39,-263.127 2677.39,-263.127 2672.83,-265.187 2675.54,-259.027 2668.28,-267.247 2668.28,-267.247"/>
<g id="edge95" class="edge"><title>Reservation&#45;&gt;Ticket</title>
<path fill="none" stroke="#111459" d="M2552.31,-319.678C2586.37,-304.282 2635.66,-281.992 2668.26,-267.256"/>
<ellipse fill="none" stroke="#111459" cx="2548.27" cy="-321.506" rx="4.00002" ry="4.00002"/>
<polygon fill="#111459" stroke="#111459" points="2668.28,-267.247 2679.24,-267.228 2672.83,-265.187 2677.39,-263.127 2677.39,-263.127 2677.39,-263.127 2672.83,-265.187 2675.54,-259.027 2668.28,-267.247 2668.28,-267.247"/>
</g>
<!-- StatisticIndex&#45;&gt;StatisticType -->
<g id="edge96" class="edge"><title>StatisticIndex&#45;&gt;StatisticType</title>
<path fill="none" stroke="#e3b22e" d="M3342.65,-579.431C3346.53,-589.819 3350.31,-601.977 3352.99,-612.664"/>
<ellipse fill="none" stroke="#e3b22e" cx="3341.14" cy="-575.607" rx="4.00001" ry="4.00001"/>
<polygon fill="#e3b22e" stroke="#e3b22e" points="3353.08,-613.046 3350.9,-623.793 3354.18,-617.923 3355.29,-622.799 3355.29,-622.799 3355.29,-622.799 3354.18,-617.923 3359.68,-621.805 3353.08,-613.046 3353.08,-613.046"/>
<g id="edge97" class="edge"><title>StatisticIndex&#45;&gt;StatisticType</title>
<path fill="none" stroke="#fa5527" d="M3333.23,-580.314C3333.88,-590.527 3333.92,-602.332 3333.35,-612.734"/>
<ellipse fill="none" stroke="#fa5527" cx="3332.88" cy="-576.161" rx="4" ry="4"/>
<polygon fill="#fa5527" stroke="#fa5527" points="3333.34,-612.83 3328.06,-622.442 3332.94,-617.815 3332.55,-622.799 3332.55,-622.799 3332.55,-622.799 3332.94,-617.815 3337.03,-623.156 3333.34,-612.83 3333.34,-612.83"/>
</g>
<!-- StatisticIndex&#45;&gt;StatisticGraph -->
<g id="edge98" class="edge"><title>StatisticIndex&#45;&gt;StatisticGraph</title>
<path fill="none" stroke="#7aed94" d="M3301.72,-531.734C3278.03,-513.271 3243.91,-486.676 3220.23,-468.225"/>
<ellipse fill="none" stroke="#7aed94" cx="3305.19" cy="-534.442" rx="4.00002" ry="4.00002"/>
<ellipse fill="#7aed94" stroke="#7aed94" cx="3217" cy="-465.71" rx="4.00002" ry="4.00002"/>
<g id="edge99" class="edge"><title>StatisticIndex&#45;&gt;StatisticGraph</title>
<path fill="none" stroke="#091444" d="M3299.72,-531.734C3276.03,-513.271 3241.91,-486.676 3218.23,-468.225"/>
<ellipse fill="none" stroke="#091444" cx="3303.19" cy="-534.442" rx="4.00002" ry="4.00002"/>
<ellipse fill="#091444" stroke="#091444" cx="3215" cy="-465.71" rx="4.00002" ry="4.00002"/>
</g>
<!-- StatisticField -->
<g id="node60" class="node"><title>StatisticField</title>
<ellipse fill="none" stroke="black" cx="3329" cy="-446" rx="57.3905" ry="18"/>
<text text-anchor="middle" x="3329" y="-442.3" font-family="Times,serif" font-size="14.00">StatisticField</text>
<ellipse fill="none" stroke="black" cx="3327" cy="-446" rx="57.3905" ry="18"/>
<text text-anchor="middle" x="3327" y="-442.3" font-family="Times,serif" font-size="14.00">StatisticField</text>
</g>
<!-- StatisticIndex&#45;&gt;StatisticField -->
<g id="edge97" class="edge"><title>StatisticIndex&#45;&gt;StatisticField</title>
<path fill="none" stroke="#d2b8e9" d="M3323.15,-527.743C3321.99,-511.577 3321.95,-490.617 3323.02,-474.103"/>
<ellipse fill="none" stroke="#d2b8e9" cx="3323.53" cy="-531.985" rx="4" ry="4"/>
<polygon fill="#d2b8e9" stroke="#d2b8e9" points="3323.04,-473.952 3328.37,-464.372 3323.46,-468.97 3323.89,-463.988 3323.89,-463.988 3323.89,-463.988 3323.46,-468.97 3319.41,-463.605 3323.04,-473.952 3323.04,-473.952"/>
<g id="edge98" class="edge"><title>StatisticIndex&#45;&gt;StatisticField</title>
<path fill="none" stroke="#febc7d" d="M3321.15,-527.743C3319.99,-511.577 3319.95,-490.617 3321.02,-474.103"/>
<ellipse fill="none" stroke="#febc7d" cx="3321.53" cy="-531.985" rx="4" ry="4"/>
<polygon fill="#febc7d" stroke="#febc7d" points="3321.04,-473.952 3326.37,-464.372 3321.46,-468.97 3321.89,-463.988 3321.89,-463.988 3321.89,-463.988 3321.46,-468.97 3317.41,-463.605 3321.04,-473.952 3321.04,-473.952"/>
</g>
<!-- StatisticField&#45;&gt;StatisticIndex -->
<g id="edge99" class="edge"><title>StatisticField&#45;&gt;StatisticIndex</title>
<path fill="none" stroke="#47e75e" d="M3334.85,-472.236C3336.05,-489.013 3336.05,-510.962 3334.85,-527.743"/>
<ellipse fill="none" stroke="#47e75e" cx="3334.47" cy="-467.973" rx="4" ry="4"/>
<ellipse fill="#47e75e" stroke="#47e75e" cx="3334.47" cy="-531.985" rx="4" ry="4"/>
<g id="edge100" class="edge"><title>StatisticField&#45;&gt;StatisticIndex</title>
<path fill="none" stroke="#695094" d="M3332.85,-472.236C3334.05,-489.013 3334.05,-510.962 3332.85,-527.743"/>
<ellipse fill="none" stroke="#695094" cx="3332.47" cy="-467.973" rx="4" ry="4"/>
<ellipse fill="#695094" stroke="#695094" cx="3332.47" cy="-531.985" rx="4" ry="4"/>
</g>
<!-- WalletTransaction&#45;&gt;Invoice -->
<g id="edge100" class="edge"><title>WalletTransaction&#45;&gt;Invoice</title>
<path fill="none" stroke="#e5bbf4" d="M388.241,-366.13C395.145,-347.123 403,-320.094 403,-295.5 403,-295.5 403,-295.5 403,-177 403,-121.658 1276.99,-97.8998 1487.02,-92.9896"/>
<ellipse fill="none" stroke="#e5bbf4" cx="386.777" cy="-370.011" rx="4.00001" ry="4.00001"/>
<ellipse fill="#e5bbf4" stroke="#e5bbf4" cx="1491.08" cy="-92.8956" rx="4" ry="4"/>
<g id="edge101" class="edge"><title>WalletTransaction&#45;&gt;Invoice</title>
<path fill="none" stroke="#d7e38a" d="M363.241,-366.13C370.145,-347.123 378,-320.094 378,-295.5 378,-295.5 378,-295.5 378,-177 378,-127.03 1161.17,-99.4935 1359.02,-93.3342"/>
<ellipse fill="none" stroke="#d7e38a" cx="361.777" cy="-370.011" rx="4.00001" ry="4.00001"/>
<ellipse fill="#d7e38a" stroke="#d7e38a" cx="1363.18" cy="-93.2056" rx="4" ry="4"/>
</g>
<!-- EventPriceCategory&#45;&gt;Ticket -->
<g id="edge101" class="edge"><title>EventPriceCategory&#45;&gt;Ticket</title>
<path fill="none" stroke="#24ba77" d="M2818.29,-317.029C2792.56,-302.644 2758.18,-283.414 2733.48,-269.603"/>
<ellipse fill="none" stroke="#24ba77" cx="2821.92" cy="-319.06" rx="4.00002" ry="4.00002"/>
<polygon fill="#24ba77" stroke="#24ba77" points="2733.25,-269.477 2726.72,-260.669 2728.89,-267.037 2724.53,-264.596 2724.53,-264.596 2724.53,-264.596 2728.89,-267.037 2722.33,-268.524 2733.25,-269.477 2733.25,-269.477"/>
<g id="edge102" class="edge"><title>EventPriceCategory&#45;&gt;Ticket</title>
<path fill="none" stroke="#76d860" d="M2818.29,-317.029C2792.56,-302.644 2758.18,-283.414 2733.48,-269.603"/>
<ellipse fill="none" stroke="#76d860" cx="2821.92" cy="-319.06" rx="4.00002" ry="4.00002"/>
<polygon fill="#76d860" stroke="#76d860" points="2733.25,-269.477 2726.72,-260.669 2728.89,-267.037 2724.53,-264.596 2724.53,-264.596 2724.53,-264.596 2728.89,-267.037 2722.33,-268.524 2733.25,-269.477 2733.25,-269.477"/>
</g>
<!-- Avoir -->
<g id="node69" class="node"><title>Avoir</title>
<ellipse fill="none" stroke="black" cx="1798" cy="-178" rx="31.3957" ry="18"/>
<text text-anchor="middle" x="1798" y="-174.3" font-family="Times,serif" font-size="14.00">Avoir</text>
<ellipse fill="none" stroke="black" cx="1614" cy="-178" rx="31.3957" ry="18"/>
<text text-anchor="middle" x="1614" y="-174.3" font-family="Times,serif" font-size="14.00">Avoir</text>
</g>
<!-- Avoir&#45;&gt;InvoiceItem -->
<g id="edge102" class="edge"><title>Avoir&#45;&gt;InvoiceItem</title>
<path fill="none" stroke="#18a3fc" d="M1783.84,-153.447C1766.29,-124.264 1736.5,-74.7197 1718.4,-44.6142"/>
<ellipse fill="none" stroke="#18a3fc" cx="1786.13" cy="-157.258" rx="4.00002" ry="4.00002"/>
<polygon fill="#18a3fc" stroke="#18a3fc" points="1718.34,-44.5094 1717.04,-33.6204 1715.76,-40.2243 1713.18,-35.9392 1713.18,-35.9392 1713.18,-35.9392 1715.76,-40.2243 1709.33,-38.2581 1718.34,-44.5094 1718.34,-44.5094"/>
<g id="edge103" class="edge"><title>Avoir&#45;&gt;InvoiceItem</title>
<path fill="none" stroke="#8fa511" d="M1604.51,-152.431C1593.33,-123.46 1574.81,-75.4807 1563.28,-45.6379"/>
<ellipse fill="none" stroke="#8fa511" cx="1606.03" cy="-156.36" rx="4.00001" ry="4.00001"/>
<polygon fill="#8fa511" stroke="#8fa511" points="1563.27,-45.5951 1563.86,-34.6454 1561.47,-40.9306 1559.67,-36.2662 1559.67,-36.2662 1559.67,-36.2662 1561.47,-40.9306 1555.47,-37.887 1563.27,-45.5951 1563.27,-45.5951"/>
</g>
<!-- Avoir&#45;&gt;Invoice -->
<g id="edge103" class="edge"><title>Avoir&#45;&gt;Invoice</title>
<path fill="none" stroke="#cd332c" d="M1767.49,-162.074C1744.42,-151.23 1711.76,-136.798 1682,-127 1646.21,-115.215 1604.37,-105.8 1573.99,-99.7158"/>
<ellipse fill="none" stroke="#cd332c" cx="1771.31" cy="-163.887" rx="4.00002" ry="4.00002"/>
<ellipse fill="#cd332c" stroke="#cd332c" cx="1570.06" cy="-98.9396" rx="4.00001" ry="4.00001"/>
<text text-anchor="middle" x="1736" y="-130.8" font-family="Times,serif" font-size="14.00">avoir</text>
<g id="edge104" class="edge"><title>Avoir&#45;&gt;Invoice</title>
<path fill="none" stroke="#b6e2a0" d="M1582.65,-162.976C1559.41,-152.706 1526.89,-138.596 1498,-127 1479.22,-119.462 1458.12,-111.556 1440.68,-105.169"/>
<ellipse fill="none" stroke="#b6e2a0" cx="1586.5" cy="-164.682" rx="4.00002" ry="4.00002"/>
<ellipse fill="#b6e2a0" stroke="#b6e2a0" cx="1436.7" cy="-103.718" rx="4.00001" ry="4.00001"/>
<text text-anchor="middle" x="1548" y="-130.8" font-family="Times,serif" font-size="14.00">avoir</text>
</g>
<!-- NotificationType -->
<g id="node70" class="node"><title>NotificationType</title>
<polygon fill="none" stroke="black" points="5103,-753 4993,-753 4993,-717 5103,-717 5103,-753"/>
<text text-anchor="middle" x="5048" y="-731.3" font-family="Times,serif" font-size="14.00">NotificationType</text>
<polygon fill="none" stroke="black" points="5000,-753 4890,-753 4890,-717 5000,-717 5000,-753"/>
<text text-anchor="middle" x="4945" y="-731.3" font-family="Times,serif" font-size="14.00">NotificationType</text>
</g>
<!-- Stylesheet -->
<g id="node72" class="node"><title>Stylesheet</title>
<ellipse fill="none" stroke="black" cx="5168" cy="-735" rx="46.5926" ry="18"/>
<text text-anchor="middle" x="5168" y="-731.3" font-family="Times,serif" font-size="14.00">Stylesheet</text>
<ellipse fill="none" stroke="black" cx="5065" cy="-735" rx="46.5926" ry="18"/>
<text text-anchor="middle" x="5065" y="-731.3" font-family="Times,serif" font-size="14.00">Stylesheet</text>
</g>
<!-- Coupon -->
<g id="node77" class="node"><title>Coupon</title>
<ellipse fill="none" stroke="black" cx="1710" cy="-178" rx="38.1938" ry="18"/>
<text text-anchor="middle" x="1710" y="-174.3" font-family="Times,serif" font-size="14.00">Coupon</text>
<g id="node78" class="node"><title>Coupon</title>
<ellipse fill="none" stroke="black" cx="1526" cy="-178" rx="38.1938" ry="18"/>
<text text-anchor="middle" x="1526" y="-174.3" font-family="Times,serif" font-size="14.00">Coupon</text>
</g>
<!-- Coupon&#45;&gt;Invoice -->
<g id="edge104" class="edge"><title>Coupon&#45;&gt;Invoice</title>
<path fill="none" stroke="#b2497b" d="M1691.4,-154.659C1682.24,-144.921 1670.49,-134.126 1658,-127 1633.13,-112.813 1602.18,-104.11 1577.18,-98.9302"/>
<ellipse fill="none" stroke="#b2497b" cx="1694.34" cy="-157.895" rx="4.00002" ry="4.00002"/>
<polygon fill="#b2497b" stroke="#b2497b" points="1577.03,-98.9013 1568.08,-92.5683 1572.12,-97.9431 1567.22,-96.9849 1567.22,-96.9849 1567.22,-96.9849 1572.12,-97.9431 1566.35,-101.402 1577.03,-98.9013 1577.03,-98.9013"/>
<g id="edge105" class="edge"><title>Coupon&#45;&gt;Invoice</title>
<path fill="none" stroke="#3887e2" d="M1505.92,-154.906C1496.76,-145.589 1485.41,-135.058 1474,-127 1463.68,-119.715 1451.62,-113.105 1440.45,-107.641"/>
<ellipse fill="none" stroke="#3887e2" cx="1508.83" cy="-157.934" rx="4.00002" ry="4.00002"/>
<polygon fill="#3887e2" stroke="#3887e2" points="1440.38,-107.605 1433.26,-99.2625 1435.86,-105.468 1431.34,-103.331 1431.34,-103.331 1431.34,-103.331 1435.86,-105.468 1429.41,-107.399 1440.38,-107.605 1440.38,-107.605"/>
</g>
<!-- Category -->
<g id="node78" class="node"><title>Category</title>
<ellipse fill="none" stroke="black" cx="2794" cy="-641" rx="42.7926" ry="18"/>
<text text-anchor="middle" x="2794" y="-637.3" font-family="Times,serif" font-size="14.00">Category</text>
<g id="node79" class="node"><title>Category</title>
<ellipse fill="none" stroke="black" cx="2780" cy="-641" rx="42.7926" ry="18"/>
<text text-anchor="middle" x="2780" y="-637.3" font-family="Times,serif" font-size="14.00">Category</text>
</g>
<!-- Category&#45;&gt;Event -->
<g id="edge105" class="edge"><title>Category&#45;&gt;Event</title>
<path fill="none" stroke="#772456" d="M2787.54,-615.028C2784.84,-604.609 2781.7,-592.487 2778.96,-581.875"/>
<ellipse fill="none" stroke="#772456" cx="2788.55" cy="-618.927" rx="4.00001" ry="4.00001"/>
<polygon fill="#772456" stroke="#772456" points="2778.88,-581.566 2780.73,-570.758 2777.62,-576.726 2776.37,-571.885 2776.37,-571.885 2776.37,-571.885 2777.62,-576.726 2772.01,-573.013 2778.88,-581.566 2778.88,-581.566"/>
<g id="edge106" class="edge"><title>Category&#45;&gt;Event</title>
<path fill="none" stroke="#488a4c" d="M2777.62,-614.694C2776.66,-604.512 2775.55,-592.747 2774.58,-582.367"/>
<ellipse fill="none" stroke="#488a4c" cx="2778.01" cy="-618.817" rx="4" ry="4"/>
<polygon fill="#488a4c" stroke="#488a4c" points="2774.55,-582.131 2778.1,-571.754 2774.09,-577.153 2773.62,-572.175 2773.62,-572.175 2773.62,-572.175 2774.09,-577.153 2769.14,-572.597 2774.55,-582.131 2774.55,-582.131"/>
</g>
<!-- MachineImage -->
<g id="node80" class="node"><title>MachineImage</title>
<g id="node81" class="node"><title>MachineImage</title>
<ellipse fill="none" stroke="black" cx="2149" cy="-338" rx="64.189" ry="18"/>
<text text-anchor="middle" x="2149" y="-334.3" font-family="Times,serif" font-size="14.00">MachineImage</text>
</g>
<!-- Feed -->
<g id="node81" class="node"><title>Feed</title>
<polygon fill="none" stroke="black" points="5287,-753 5233,-753 5233,-717 5287,-717 5287,-753"/>
<text text-anchor="middle" x="5260" y="-731.3" font-family="Times,serif" font-size="14.00">Feed</text>
<g id="node82" class="node"><title>Feed</title>
<polygon fill="none" stroke="black" points="5184,-753 5130,-753 5130,-717 5184,-717 5184,-753"/>
<text text-anchor="middle" x="5157" y="-731.3" font-family="Times,serif" font-size="14.00">Feed</text>
</g>
<!-- Machine&#45;&gt;Price -->
<g id="edge109" class="edge"><title>Machine&#45;&gt;Price</title>
<path fill="none" stroke="#a082bd" d="M1946.69,-430.002C1976.97,-415.792 2017.68,-391.335 2038,-356 2051.42,-332.66 2051.95,-301.353 2050.04,-279.205"/>
<ellipse fill="none" stroke="#a082bd" cx="1942.88" cy="-431.738" rx="4.00002" ry="4.00002"/>
<polygon fill="#a082bd" stroke="#a082bd" points="2050.02,-279.085 2053.42,-268.658 2049.49,-274.114 2048.95,-269.143 2048.95,-269.143 2048.95,-269.143 2049.49,-274.114 2044.47,-269.628 2050.02,-279.085 2050.02,-279.085"/>
<g id="edge110" class="edge"><title>Machine&#45;&gt;Price</title>
<path fill="none" stroke="#fe3d0f" d="M1946.69,-430.002C1976.97,-415.792 2017.68,-391.335 2038,-356 2051.42,-332.66 2051.95,-301.353 2050.04,-279.205"/>
<ellipse fill="none" stroke="#fe3d0f" cx="1942.88" cy="-431.738" rx="4.00002" ry="4.00002"/>
<polygon fill="#fe3d0f" stroke="#fe3d0f" points="2050.02,-279.085 2053.42,-268.658 2049.49,-274.114 2048.95,-269.143 2048.95,-269.143 2048.95,-269.143 2049.49,-274.114 2044.47,-269.628 2050.02,-279.085 2050.02,-279.085"/>
</g>
<!-- Machine&#45;&gt;Plan -->
<g id="edge112" class="edge"><title>Machine&#45;&gt;Plan</title>
<path fill="none" stroke="#b0e074" d="M1887.07,-421.317C1883.92,-417.614 1880.8,-413.764 1878,-410 1867.1,-395.35 1856.27,-377.931 1848.09,-364.013"/>
<polygon fill="#b0e074" stroke="#b0e074" points="1887.3,-421.585 1890.51,-432.07 1890.6,-425.344 1893.89,-429.103 1893.89,-429.103 1893.89,-429.103 1890.6,-425.344 1897.28,-426.136 1887.3,-421.585 1887.3,-421.585"/>
<polygon fill="#b0e074" stroke="#b0e074" points="1847.89,-363.667 1846.77,-352.759 1845.38,-359.341 1842.88,-355.014 1842.88,-355.014 1842.88,-355.014 1845.38,-359.341 1838.98,-357.27 1847.89,-363.667 1847.89,-363.667"/>
<g id="edge113" class="edge"><title>Machine&#45;&gt;Plan</title>
<path fill="none" stroke="#b0edb2" d="M1887.07,-421.317C1883.92,-417.614 1880.8,-413.764 1878,-410 1867.1,-395.35 1856.27,-377.931 1848.09,-364.013"/>
<polygon fill="#b0edb2" stroke="#b0edb2" points="1887.3,-421.585 1890.51,-432.07 1890.6,-425.344 1893.89,-429.103 1893.89,-429.103 1893.89,-429.103 1890.6,-425.344 1897.28,-426.136 1887.3,-421.585 1887.3,-421.585"/>
<polygon fill="#b0edb2" stroke="#b0edb2" points="1847.89,-363.667 1846.77,-352.759 1845.38,-359.341 1842.88,-355.014 1842.88,-355.014 1842.88,-355.014 1845.38,-359.341 1838.98,-357.27 1847.89,-363.667 1847.89,-363.667"/>
</g>
<!-- Machine&#45;&gt;MachineFile -->
<g id="edge107" class="edge"><title>Machine&#45;&gt;MachineFile</title>
<path fill="none" stroke="#6da86e" d="M1923.19,-421.504C1933.33,-404.701 1946.98,-382.092 1957.43,-364.791"/>
<ellipse fill="none" stroke="#6da86e" cx="1921.07" cy="-425.013" rx="4.00002" ry="4.00002"/>
<polygon fill="#6da86e" stroke="#6da86e" points="1957.69,-364.357 1966.71,-358.122 1960.27,-360.076 1962.86,-355.796 1962.86,-355.796 1962.86,-355.796 1960.27,-360.076 1959.01,-353.47 1957.69,-364.357 1957.69,-364.357"/>
<g id="edge108" class="edge"><title>Machine&#45;&gt;MachineFile</title>
<path fill="none" stroke="#541673" d="M1923.19,-421.504C1933.33,-404.701 1946.98,-382.092 1957.43,-364.791"/>
<ellipse fill="none" stroke="#541673" cx="1921.07" cy="-425.013" rx="4.00002" ry="4.00002"/>
<polygon fill="#541673" stroke="#541673" points="1957.69,-364.357 1966.71,-358.122 1960.27,-360.076 1962.86,-355.796 1962.86,-355.796 1962.86,-355.796 1960.27,-360.076 1959.01,-353.47 1957.69,-364.357 1957.69,-364.357"/>
</g>
<!-- Machine&#45;&gt;Credit -->
<g id="edge111" class="edge"><title>Machine&#45;&gt;Credit</title>
<path fill="none" stroke="#b0def2" d="M1909.01,-419.571C1908.44,-379.525 1904.81,-304.51 1886,-287 1878.08,-279.627 1566.68,-261.049 1451.37,-254.407"/>
<ellipse fill="none" stroke="#b0def2" cx="1909.05" cy="-423.785" rx="4" ry="4"/>
<polygon fill="#b0def2" stroke="#b0def2" points="1451.14,-254.394 1441.42,-249.328 1446.15,-254.107 1441.16,-253.821 1441.16,-253.821 1441.16,-253.821 1446.15,-254.107 1440.9,-258.313 1451.14,-254.394 1451.14,-254.394"/>
<g id="edge112" class="edge"><title>Machine&#45;&gt;Credit</title>
<path fill="none" stroke="#b195b7" d="M1909,-419.576C1908.43,-379.537 1904.79,-304.531 1886,-287 1878.35,-279.858 1578.16,-261.256 1465.3,-254.499"/>
<ellipse fill="none" stroke="#b195b7" cx="1909.05" cy="-423.788" rx="4" ry="4"/>
<polygon fill="#b195b7" stroke="#b195b7" points="1465.28,-254.498 1455.57,-249.409 1460.29,-254.199 1455.3,-253.901 1455.3,-253.901 1455.3,-253.901 1460.29,-254.199 1455.03,-258.393 1465.28,-254.498 1465.28,-254.498"/>
</g>
<!-- Machine&#45;&gt;Reservation -->
<g id="edge110" class="edge"><title>Machine&#45;&gt;Reservation</title>
<path fill="none" stroke="#bd3038" d="M1947.58,-431.049C1951.74,-429.875 1955.93,-428.824 1960,-428 2060.93,-407.566 2089.04,-424.461 2191,-410 2308.28,-393.366 2336.82,-383.676 2452,-356 2456.15,-355.003 2460.45,-353.924 2464.75,-352.81"/>
<ellipse fill="none" stroke="#bd3038" cx="1943.52" cy="-432.276" rx="4.00001" ry="4.00001"/>
<polygon fill="#bd3038" stroke="#bd3038" points="2465.07,-352.725 2475.89,-354.521 2469.91,-351.447 2474.74,-350.17 2474.74,-350.17 2474.74,-350.17 2469.91,-351.447 2473.59,-345.819 2465.07,-352.725 2465.07,-352.725"/>
<g id="edge111" class="edge"><title>Machine&#45;&gt;Reservation</title>
<path fill="none" stroke="#7cb185" d="M1947.58,-431.049C1951.74,-429.875 1955.93,-428.824 1960,-428 2060.93,-407.566 2089.04,-424.461 2191,-410 2308.28,-393.366 2336.82,-383.676 2452,-356 2456.15,-355.003 2460.45,-353.924 2464.75,-352.81"/>
<ellipse fill="none" stroke="#7cb185" cx="1943.52" cy="-432.276" rx="4.00001" ry="4.00001"/>
<polygon fill="#7cb185" stroke="#7cb185" points="2465.07,-352.725 2475.89,-354.521 2469.91,-351.447 2474.74,-350.17 2474.74,-350.17 2474.74,-350.17 2469.91,-351.447 2473.59,-345.819 2465.07,-352.725 2465.07,-352.725"/>
</g>
<!-- Machine&#45;&gt;MachinesAvailability -->
<g id="edge108" class="edge"><title>Machine&#45;&gt;MachinesAvailability</title>
<path fill="none" stroke="#55ba42" d="M1947.62,-431.225C1951.77,-430.017 1955.95,-428.91 1960,-428 2025.08,-413.379 2043.63,-423.256 2109,-410 2177.05,-396.201 2253.65,-372.94 2303.25,-356.822"/>
<ellipse fill="none" stroke="#55ba42" cx="1943.56" cy="-432.473" rx="4.00001" ry="4.00001"/>
<polygon fill="#55ba42" stroke="#55ba42" points="2303.29,-356.807 2314.19,-357.975 2308.04,-355.253 2312.8,-353.698 2312.8,-353.698 2312.8,-353.698 2308.04,-355.253 2311.4,-349.421 2303.29,-356.807 2303.29,-356.807"/>
<g id="edge109" class="edge"><title>Machine&#45;&gt;MachinesAvailability</title>
<path fill="none" stroke="#efd384" d="M1947.62,-431.225C1951.77,-430.017 1955.95,-428.91 1960,-428 2025.08,-413.379 2043.63,-423.256 2109,-410 2177.05,-396.201 2253.65,-372.94 2303.25,-356.822"/>
<ellipse fill="none" stroke="#efd384" cx="1943.56" cy="-432.473" rx="4.00001" ry="4.00001"/>
<polygon fill="#efd384" stroke="#efd384" points="2303.29,-356.807 2314.19,-357.975 2308.04,-355.253 2312.8,-353.698 2312.8,-353.698 2312.8,-353.698 2308.04,-355.253 2311.4,-349.421 2303.29,-356.807 2303.29,-356.807"/>
</g>
<!-- Machine&#45;&gt;MachineImage -->
<g id="edge106" class="edge"><title>Machine&#45;&gt;MachineImage</title>
<path fill="none" stroke="#2db89d" d="M1947.83,-431.342C1951.91,-430.121 1956.02,-428.978 1960,-428 2008.53,-416.059 2025.99,-431.721 2071,-410 2094.44,-398.688 2115.9,-378.051 2130.35,-361.931"/>
<ellipse fill="none" stroke="#2db89d" cx="1943.87" cy="-432.575" rx="4.00001" ry="4.00001"/>
<ellipse fill="#2db89d" stroke="#2db89d" cx="2133.09" cy="-358.794" rx="4.00002" ry="4.00002"/>
<g id="edge107" class="edge"><title>Machine&#45;&gt;MachineImage</title>
<path fill="none" stroke="#88cbfa" d="M1947.83,-431.342C1951.91,-430.121 1956.02,-428.978 1960,-428 2008.53,-416.059 2025.99,-431.721 2071,-410 2094.44,-398.688 2115.9,-378.051 2130.35,-361.931"/>
<ellipse fill="none" stroke="#88cbfa" cx="1943.87" cy="-432.575" rx="4.00001" ry="4.00001"/>
<ellipse fill="#88cbfa" stroke="#88cbfa" cx="2133.09" cy="-358.794" rx="4.00002" ry="4.00002"/>
</g>
<!-- Abuse -->
<g id="node83" class="node"><title>Abuse</title>
<ellipse fill="none" stroke="black" cx="5338" cy="-735" rx="33.2948" ry="18"/>
<text text-anchor="middle" x="5338" y="-731.3" font-family="Times,serif" font-size="14.00">Abuse</text>
<g id="node84" class="node"><title>Abuse</title>
<ellipse fill="none" stroke="black" cx="5235" cy="-735" rx="33.2948" ry="18"/>
<text text-anchor="middle" x="5235" y="-731.3" font-family="Times,serif" font-size="14.00">Abuse</text>
</g>
<!-- Profile&#45;&gt;UserAvatar -->
<g id="edge113" class="edge"><title>Profile&#45;&gt;UserAvatar</title>
<path fill="none" stroke="#a3aa07" d="M199.965,-529.504C210.321,-512.079 224.389,-488.41 234.801,-470.891"/>
<ellipse fill="none" stroke="#a3aa07" cx="197.887" cy="-532.999" rx="4.00002" ry="4.00002"/>
<ellipse fill="#a3aa07" stroke="#a3aa07" cx="236.974" cy="-467.235" rx="4.00002" ry="4.00002"/>
<g id="edge114" class="edge"><title>Profile&#45;&gt;UserAvatar</title>
<path fill="none" stroke="#d0c381" d="M199.965,-529.504C210.321,-512.079 224.389,-488.41 234.801,-470.891"/>
<ellipse fill="none" stroke="#d0c381" cx="197.887" cy="-532.999" rx="4.00002" ry="4.00002"/>
<ellipse fill="#d0c381" stroke="#d0c381" cx="236.974" cy="-467.235" rx="4.00002" ry="4.00002"/>
</g>
<!-- Profile&#45;&gt;Address -->
<g id="edge114" class="edge"><title>Profile&#45;&gt;Address</title>
<path fill="none" stroke="#33e13f" d="M150.685,-539.775C119.689,-526.051 76.5874,-501.311 57,-464 40.0533,-431.719 55.2699,-389.222 68.2728,-363.024"/>
<ellipse fill="none" stroke="#33e13f" cx="154.605" cy="-541.453" rx="4.00002" ry="4.00002"/>
<ellipse fill="#33e13f" stroke="#33e13f" cx="70.188" cy="-359.321" rx="4.00002" ry="4.00002"/>
<g id="edge115" class="edge"><title>Profile&#45;&gt;Address</title>
<path fill="none" stroke="#ca746e" d="M150.685,-539.775C119.689,-526.051 76.5874,-501.311 57,-464 40.0533,-431.719 55.2699,-389.222 68.2728,-363.024"/>
<ellipse fill="none" stroke="#ca746e" cx="154.605" cy="-541.453" rx="4.00002" ry="4.00002"/>
<ellipse fill="#ca746e" stroke="#ca746e" cx="70.188" cy="-359.321" rx="4.00002" ry="4.00002"/>
</g>
<!-- Profile&#45;&gt;Organization -->
<g id="edge115" class="edge"><title>Profile&#45;&gt;Organization</title>
<path fill="none" stroke="#88f282" d="M172.035,-529.504C161.679,-512.079 147.611,-488.41 137.199,-470.891"/>
<ellipse fill="none" stroke="#88f282" cx="174.113" cy="-532.999" rx="4.00002" ry="4.00002"/>
<ellipse fill="#88f282" stroke="#88f282" cx="135.026" cy="-467.235" rx="4.00002" ry="4.00002"/>
<g id="edge116" class="edge"><title>Profile&#45;&gt;Organization</title>
<path fill="none" stroke="#123fa9" d="M172.035,-529.504C161.679,-512.079 147.611,-488.41 137.199,-470.891"/>
<ellipse fill="none" stroke="#123fa9" cx="174.113" cy="-532.999" rx="4.00002" ry="4.00002"/>
<ellipse fill="#123fa9" stroke="#123fa9" cx="135.026" cy="-467.235" rx="4.00002" ry="4.00002"/>
</g>
<!-- Setting -->
<g id="node87" class="node"><title>Setting</title>
<ellipse fill="none" stroke="black" cx="5425" cy="-735" rx="35.9954" ry="18"/>
<text text-anchor="middle" x="5425" y="-731.3" font-family="Times,serif" font-size="14.00">Setting</text>
<g id="node88" class="node"><title>Setting</title>
<ellipse fill="none" stroke="black" cx="5322" cy="-735" rx="35.9954" ry="18"/>
<text text-anchor="middle" x="5322" y="-731.3" font-family="Times,serif" font-size="14.00">Setting</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 89 KiB

View File

@ -4,16 +4,16 @@
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: models_diagram Pages: 1 -->
<svg width="8869pt" height="3096pt"
viewBox="0.00 0.00 8869.00 3096.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="8820pt" height="3096pt"
viewBox="0.00 0.00 8820.00 3096.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 3092)">
<title>models_diagram</title>
<polygon fill="none" stroke="none" points="-4,4 -4,-3092 8865,-3092 8865,4 -4,4"/>
<polygon fill="none" stroke="none" points="-4,4 -4,-3092 8816,-3092 8816,4 -4,4"/>
<!-- _diagram_info -->
<g id="node1" class="node"><title>_diagram_info</title>
<text text-anchor="start" x="2692" y="-3029.1" font-family="Times,serif" font-size="13.00">Models diagram</text>
<text text-anchor="start" x="2692" y="-3015.1" font-family="Times,serif" font-size="13.00">Date: Aug 31 2016 &#45; 12:07</text>
<text text-anchor="start" x="2692" y="-3001.1" font-family="Times,serif" font-size="13.00">Migration version: 20160831084519</text>
<text text-anchor="start" x="2692" y="-3015.1" font-family="Times,serif" font-size="13.00">Date: Sep 15 2016 &#45; 17:48</text>
<text text-anchor="start" x="2692" y="-3001.1" font-family="Times,serif" font-size="13.00">Migration version: 20160915105234</text>
<text text-anchor="start" x="2692" y="-2987.1" font-family="Times,serif" font-size="13.00">Generated by RailRoady 1.4.0</text>
<text text-anchor="start" x="2692" y="-2973.1" font-family="Times,serif" font-size="13.00">http://railroady.prestonlee.com</text>
</g>
@ -44,9 +44,9 @@
</g>
<!-- Group&#45;&gt;Price -->
<g id="edge4" class="edge"><title>Group&#45;&gt;Price</title>
<path fill="none" stroke="#f5146c" d="M3096.28,-2945.49C3260.23,-2777.61 3723.72,-2269.55 3882,-1741 3899.47,-1682.67 3909.76,-1658.19 3882,-1604 3875.76,-1591.81 3867.12,-1595.23 3857,-1586 3776.46,-1512.56 3741.58,-1500.01 3696,-1401 3647.71,-1296.12 3731.75,-1232.84 3658,-1144 3613.56,-1090.47 3571.28,-1125.95 3510,-1093 3500.34,-1087.81 3490.65,-1081.9 3481.15,-1075.62"/>
<ellipse fill="none" stroke="#f5146c" cx="3093.38" cy="-2948.46" rx="4.00002" ry="4.00002"/>
<polygon fill="#f5146c" stroke="#f5146c" points="3481.15,-1075.62 3475.39,-1066.29 3477.01,-1072.82 3472.87,-1070.02 3472.87,-1070.02 3472.87,-1070.02 3477.01,-1072.82 3470.35,-1073.75 3481.15,-1075.62 3481.15,-1075.62"/>
<path fill="none" stroke="#dc9f1a" d="M3096.28,-2945.49C3260.23,-2777.61 3723.72,-2269.55 3882,-1741 3899.47,-1682.67 3909.76,-1658.19 3882,-1604 3875.76,-1591.81 3867.12,-1595.23 3857,-1586 3776.46,-1512.56 3741.58,-1500.01 3696,-1401 3647.71,-1296.12 3731.75,-1232.84 3658,-1144 3613.56,-1090.47 3571.28,-1125.95 3510,-1093 3500.34,-1087.81 3490.65,-1081.9 3481.15,-1075.62"/>
<ellipse fill="none" stroke="#dc9f1a" cx="3093.38" cy="-2948.46" rx="4.00002" ry="4.00002"/>
<polygon fill="#dc9f1a" stroke="#dc9f1a" points="3481.15,-1075.62 3475.39,-1066.29 3477.01,-1072.82 3472.87,-1070.02 3472.87,-1070.02 3472.87,-1070.02 3477.01,-1072.82 3470.35,-1073.75 3481.15,-1075.62 3481.15,-1075.62"/>
<text text-anchor="middle" x="3922.5" y="-1808.8" font-family="Times,serif" font-size="14.00">machines_prices</text>
</g>
<!-- TrainingsPricing -->
@ -63,9 +63,9 @@
</g>
<!-- Group&#45;&gt;TrainingsPricing -->
<g id="edge3" class="edge"><title>Group&#45;&gt;TrainingsPricing</title>
<path fill="none" stroke="#7ed658" d="M3053.52,-2943.43C3083.17,-2825.24 3146.86,-2553.77 3169,-2321 3178.19,-2224.33 3233.72,-1956.4 3169,-1884 3145.16,-1857.32 3039.26,-1885.09 3009,-1866 2963.85,-1837.52 2932.87,-1785.23 2913.71,-1742.33"/>
<ellipse fill="none" stroke="#7ed658" cx="3052.51" cy="-2947.45" rx="4.00001" ry="4.00001"/>
<polygon fill="#7ed658" stroke="#7ed658" points="2913.66,-1742.22 2913.81,-1731.26 2911.67,-1737.64 2909.68,-1733.05 2909.68,-1733.05 2909.68,-1733.05 2911.67,-1737.64 2905.55,-1734.84 2913.66,-1742.22 2913.66,-1742.22"/>
<path fill="none" stroke="#39a7de" d="M3053.52,-2943.43C3083.17,-2825.24 3146.86,-2553.77 3169,-2321 3178.19,-2224.33 3233.72,-1956.4 3169,-1884 3145.16,-1857.32 3039.26,-1885.09 3009,-1866 2963.85,-1837.52 2932.87,-1785.23 2913.71,-1742.33"/>
<ellipse fill="none" stroke="#39a7de" cx="3052.51" cy="-2947.45" rx="4.00001" ry="4.00001"/>
<polygon fill="#39a7de" stroke="#39a7de" points="2913.66,-1742.22 2913.81,-1731.26 2911.67,-1737.64 2909.68,-1733.05 2909.68,-1733.05 2909.68,-1733.05 2911.67,-1737.64 2905.55,-1734.84 2913.66,-1742.22 2913.66,-1742.22"/>
</g>
<!-- Plan -->
<g id="node34" class="node"><title>Plan</title>
@ -90,9 +90,9 @@
</g>
<!-- Group&#45;&gt;Plan -->
<g id="edge1" class="edge"><title>Group&#45;&gt;Plan</title>
<path fill="none" stroke="#79673d" d="M3024.54,-2943.18C2998.49,-2824.56 2940.78,-2552.37 2907,-2321 2878.8,-2127.84 2924.48,-2069.27 2863,-1884 2842.6,-1822.51 2833.81,-1804.81 2788,-1759 2777.01,-1748.01 2765.66,-1754.53 2758,-1741 2698.3,-1635.55 2754.92,-1505.14 2818.23,-1408.87"/>
<ellipse fill="none" stroke="#79673d" cx="3025.42" cy="-2947.2" rx="4.00001" ry="4.00001"/>
<polygon fill="#79673d" stroke="#79673d" points="2818.24,-1408.86 2827.53,-1403.04 2821.01,-1404.7 2823.78,-1400.54 2823.78,-1400.54 2823.78,-1400.54 2821.01,-1404.7 2820.04,-1398.05 2818.24,-1408.86 2818.24,-1408.86"/>
<path fill="none" stroke="#aecb6f" d="M3024.54,-2943.18C2998.49,-2824.56 2940.78,-2552.37 2907,-2321 2878.8,-2127.84 2924.48,-2069.27 2863,-1884 2842.6,-1822.51 2833.81,-1804.81 2788,-1759 2777.01,-1748.01 2765.66,-1754.53 2758,-1741 2698.3,-1635.55 2754.92,-1505.14 2818.23,-1408.87"/>
<ellipse fill="none" stroke="#aecb6f" cx="3025.42" cy="-2947.2" rx="4.00001" ry="4.00001"/>
<polygon fill="#aecb6f" stroke="#aecb6f" points="2818.24,-1408.86 2827.53,-1403.04 2821.01,-1404.7 2823.78,-1400.54 2823.78,-1400.54 2823.78,-1400.54 2821.01,-1404.7 2820.04,-1398.05 2818.24,-1408.86 2818.24,-1408.86"/>
</g>
<!-- User -->
<g id="node41" class="node"><title>User</title>
@ -134,30 +134,30 @@
</g>
<!-- Group&#45;&gt;User -->
<g id="edge2" class="edge"><title>Group&#45;&gt;User</title>
<path fill="none" stroke="#e6ab02" d="M2953.04,-2947.17C2937.95,-2937.99 2922.2,-2928.91 2907,-2921 2731.43,-2829.68 2520.77,-2744.48 2377.54,-2689.96"/>
<ellipse fill="none" stroke="#e6ab02" cx="2956.51" cy="-2949.3" rx="4.00002" ry="4.00002"/>
<polygon fill="#e6ab02" stroke="#e6ab02" points="2377.12,-2689.8 2369.37,-2682.04 2372.44,-2688.03 2367.77,-2686.25 2367.77,-2686.25 2367.77,-2686.25 2372.44,-2688.03 2366.17,-2690.46 2377.12,-2689.8 2377.12,-2689.8"/>
<path fill="none" stroke="#736a3f" d="M2953.04,-2947.17C2937.95,-2937.99 2922.2,-2928.91 2907,-2921 2731.43,-2829.68 2520.77,-2744.48 2377.54,-2689.96"/>
<ellipse fill="none" stroke="#736a3f" cx="2956.51" cy="-2949.3" rx="4.00002" ry="4.00002"/>
<polygon fill="#736a3f" stroke="#736a3f" points="2377.12,-2689.8 2369.37,-2682.04 2372.44,-2688.03 2367.77,-2686.25 2367.77,-2686.25 2367.77,-2686.25 2372.44,-2688.03 2366.17,-2690.46 2377.12,-2689.8 2377.12,-2689.8"/>
</g>
<!-- InvoiceItem -->
<g id="node3" class="node"><title>InvoiceItem</title>
<path fill="none" stroke="black" d="M3136.5,-0.5C3136.5,-0.5 3371.5,-0.5 3371.5,-0.5 3377.5,-0.5 3383.5,-6.5 3383.5,-12.5 3383.5,-12.5 3383.5,-154.5 3383.5,-154.5 3383.5,-160.5 3377.5,-166.5 3371.5,-166.5 3371.5,-166.5 3136.5,-166.5 3136.5,-166.5 3130.5,-166.5 3124.5,-160.5 3124.5,-154.5 3124.5,-154.5 3124.5,-12.5 3124.5,-12.5 3124.5,-6.5 3130.5,-0.5 3136.5,-0.5"/>
<text text-anchor="middle" x="3254" y="-151.3" font-family="Times,serif" font-size="14.00">InvoiceItem</text>
<polyline fill="none" stroke="black" points="3124.5,-143.5 3383.5,-143.5 "/>
<text text-anchor="start" x="3132.5" y="-128.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="3132.5" y="-113.3" font-family="Times,serif" font-size="14.00">invoice_id :integer</text>
<text text-anchor="start" x="3132.5" y="-98.3" font-family="Times,serif" font-size="14.00">stp_invoice_item_id :character varying(255)</text>
<text text-anchor="start" x="3132.5" y="-83.3" font-family="Times,serif" font-size="14.00">amount :integer</text>
<text text-anchor="start" x="3132.5" y="-68.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="3132.5" y="-53.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="3132.5" y="-38.3" font-family="Times,serif" font-size="14.00">description :text</text>
<text text-anchor="start" x="3132.5" y="-23.3" font-family="Times,serif" font-size="14.00">subscription_id :integer</text>
<text text-anchor="start" x="3132.5" y="-8.3" font-family="Times,serif" font-size="14.00">invoice_item_id :integer</text>
<path fill="none" stroke="black" d="M3037.5,-0.5C3037.5,-0.5 3272.5,-0.5 3272.5,-0.5 3278.5,-0.5 3284.5,-6.5 3284.5,-12.5 3284.5,-12.5 3284.5,-154.5 3284.5,-154.5 3284.5,-160.5 3278.5,-166.5 3272.5,-166.5 3272.5,-166.5 3037.5,-166.5 3037.5,-166.5 3031.5,-166.5 3025.5,-160.5 3025.5,-154.5 3025.5,-154.5 3025.5,-12.5 3025.5,-12.5 3025.5,-6.5 3031.5,-0.5 3037.5,-0.5"/>
<text text-anchor="middle" x="3155" y="-151.3" font-family="Times,serif" font-size="14.00">InvoiceItem</text>
<polyline fill="none" stroke="black" points="3025.5,-143.5 3284.5,-143.5 "/>
<text text-anchor="start" x="3033.5" y="-128.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="3033.5" y="-113.3" font-family="Times,serif" font-size="14.00">invoice_id :integer</text>
<text text-anchor="start" x="3033.5" y="-98.3" font-family="Times,serif" font-size="14.00">stp_invoice_item_id :character varying(255)</text>
<text text-anchor="start" x="3033.5" y="-83.3" font-family="Times,serif" font-size="14.00">amount :integer</text>
<text text-anchor="start" x="3033.5" y="-68.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="3033.5" y="-53.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="3033.5" y="-38.3" font-family="Times,serif" font-size="14.00">description :text</text>
<text text-anchor="start" x="3033.5" y="-23.3" font-family="Times,serif" font-size="14.00">subscription_id :integer</text>
<text text-anchor="start" x="3033.5" y="-8.3" font-family="Times,serif" font-size="14.00">invoice_item_id :integer</text>
</g>
<!-- InvoiceItem&#45;&gt;InvoiceItem -->
<g id="edge5" class="edge"><title>InvoiceItem&#45;&gt;InvoiceItem</title>
<path fill="none" stroke="#123c50" d="M3391.65,-95.1444C3397.87,-92.1865 3401.5,-88.305 3401.5,-83.5 3401.5,-78.695 3397.87,-74.8135 3391.65,-71.8556"/>
<ellipse fill="none" stroke="#123c50" cx="3387.69" cy="-96.6063" rx="4.00001" ry="4.00001"/>
<ellipse fill="#123c50" stroke="#123c50" cx="3387.69" cy="-70.3937" rx="4.00001" ry="4.00001"/>
<path fill="none" stroke="#6cf958" d="M3292.65,-95.1444C3298.87,-92.1865 3302.5,-88.305 3302.5,-83.5 3302.5,-78.695 3298.87,-74.8135 3292.65,-71.8556"/>
<ellipse fill="none" stroke="#6cf958" cx="3288.69" cy="-96.6063" rx="4.00001" ry="4.00001"/>
<ellipse fill="#6cf958" stroke="#6cf958" cx="3288.69" cy="-70.3937" rx="4.00001" ry="4.00001"/>
</g>
<!-- AvailabilityTag -->
<g id="node5" class="node"><title>AvailabilityTag</title>
@ -172,8 +172,8 @@
</g>
<!-- OpenAPI -->
<g id="node6" class="node"><title>OpenAPI</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="4497,-3022.5 4429,-3022.5 4429,-2986.5 4497,-2986.5 4497,-3022.5"/>
<text text-anchor="middle" x="4463" y="-3000.8" font-family="Times,serif" font-size="14.00">OpenAPI</text>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="4422,-3022.5 4354,-3022.5 4354,-2986.5 4422,-2986.5 4422,-3022.5"/>
<text text-anchor="middle" x="4388" y="-3000.8" font-family="Times,serif" font-size="14.00">OpenAPI</text>
</g>
<!-- TrainingImage -->
<g id="node7" class="node"><title>TrainingImage</title>
@ -190,40 +190,40 @@
</g>
<!-- OpenAPI::Client -->
<g id="node8" class="node"><title>OpenAPI::Client</title>
<path fill="none" stroke="black" d="M5043,-2944C5043,-2944 5263,-2944 5263,-2944 5269,-2944 5275,-2950 5275,-2956 5275,-2956 5275,-3053 5275,-3053 5275,-3059 5269,-3065 5263,-3065 5263,-3065 5043,-3065 5043,-3065 5037,-3065 5031,-3059 5031,-3053 5031,-3053 5031,-2956 5031,-2956 5031,-2950 5037,-2944 5043,-2944"/>
<text text-anchor="middle" x="5153" y="-3049.8" font-family="Times,serif" font-size="14.00">OpenAPI::Client</text>
<polyline fill="none" stroke="black" points="5031,-3042 5275,-3042 "/>
<text text-anchor="start" x="5039" y="-3026.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5039" y="-3011.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="5039" y="-2996.8" font-family="Times,serif" font-size="14.00">calls_count :integer</text>
<text text-anchor="start" x="5039" y="-2981.8" font-family="Times,serif" font-size="14.00">token :character varying</text>
<text text-anchor="start" x="5039" y="-2966.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5039" y="-2951.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M4908,-2944C4908,-2944 5128,-2944 5128,-2944 5134,-2944 5140,-2950 5140,-2956 5140,-2956 5140,-3053 5140,-3053 5140,-3059 5134,-3065 5128,-3065 5128,-3065 4908,-3065 4908,-3065 4902,-3065 4896,-3059 4896,-3053 4896,-3053 4896,-2956 4896,-2956 4896,-2950 4902,-2944 4908,-2944"/>
<text text-anchor="middle" x="5018" y="-3049.8" font-family="Times,serif" font-size="14.00">OpenAPI::Client</text>
<polyline fill="none" stroke="black" points="4896,-3042 5140,-3042 "/>
<text text-anchor="start" x="4904" y="-3026.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4904" y="-3011.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="4904" y="-2996.8" font-family="Times,serif" font-size="14.00">calls_count :integer</text>
<text text-anchor="start" x="4904" y="-2981.8" font-family="Times,serif" font-size="14.00">token :character varying</text>
<text text-anchor="start" x="4904" y="-2966.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4904" y="-2951.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- OpenAPI::CallsCountTracing -->
<g id="node9" class="node"><title>OpenAPI::CallsCountTracing</title>
<path fill="none" stroke="black" d="M5043,-2567.5C5043,-2567.5 5263,-2567.5 5263,-2567.5 5269,-2567.5 5275,-2573.5 5275,-2579.5 5275,-2579.5 5275,-2676.5 5275,-2676.5 5275,-2682.5 5269,-2688.5 5263,-2688.5 5263,-2688.5 5043,-2688.5 5043,-2688.5 5037,-2688.5 5031,-2682.5 5031,-2676.5 5031,-2676.5 5031,-2579.5 5031,-2579.5 5031,-2573.5 5037,-2567.5 5043,-2567.5"/>
<text text-anchor="middle" x="5153" y="-2673.3" font-family="Times,serif" font-size="14.00">OpenAPI::CallsCountTracing</text>
<polyline fill="none" stroke="black" points="5031,-2665.5 5275,-2665.5 "/>
<text text-anchor="start" x="5039" y="-2650.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5039" y="-2635.3" font-family="Times,serif" font-size="14.00">open_api_client_id :integer</text>
<text text-anchor="start" x="5039" y="-2620.3" font-family="Times,serif" font-size="14.00">calls_count :integer</text>
<text text-anchor="start" x="5039" y="-2605.3" font-family="Times,serif" font-size="14.00">at :timestamp without time zone</text>
<text text-anchor="start" x="5039" y="-2590.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5039" y="-2575.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M4908,-2567.5C4908,-2567.5 5128,-2567.5 5128,-2567.5 5134,-2567.5 5140,-2573.5 5140,-2579.5 5140,-2579.5 5140,-2676.5 5140,-2676.5 5140,-2682.5 5134,-2688.5 5128,-2688.5 5128,-2688.5 4908,-2688.5 4908,-2688.5 4902,-2688.5 4896,-2682.5 4896,-2676.5 4896,-2676.5 4896,-2579.5 4896,-2579.5 4896,-2573.5 4902,-2567.5 4908,-2567.5"/>
<text text-anchor="middle" x="5018" y="-2673.3" font-family="Times,serif" font-size="14.00">OpenAPI::CallsCountTracing</text>
<polyline fill="none" stroke="black" points="4896,-2665.5 5140,-2665.5 "/>
<text text-anchor="start" x="4904" y="-2650.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4904" y="-2635.3" font-family="Times,serif" font-size="14.00">open_api_client_id :integer</text>
<text text-anchor="start" x="4904" y="-2620.3" font-family="Times,serif" font-size="14.00">calls_count :integer</text>
<text text-anchor="start" x="4904" y="-2605.3" font-family="Times,serif" font-size="14.00">at :timestamp without time zone</text>
<text text-anchor="start" x="4904" y="-2590.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4904" y="-2575.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- OpenAPI::Client&#45;&gt;OpenAPI::CallsCountTracing -->
<g id="edge6" class="edge"><title>OpenAPI::Client&#45;&gt;OpenAPI::CallsCountTracing</title>
<path fill="none" stroke="#521766" d="M5153,-2935.34C5153,-2868.25 5153,-2766.28 5153,-2698.67"/>
<ellipse fill="none" stroke="#521766" cx="5153" cy="-2939.75" rx="4" ry="4"/>
<polygon fill="#521766" stroke="#521766" points="5153,-2698.54 5157.5,-2688.54 5153,-2693.54 5153,-2688.54 5153,-2688.54 5153,-2688.54 5153,-2693.54 5148.5,-2688.54 5153,-2698.54 5153,-2698.54"/>
<path fill="none" stroke="#06abf7" d="M5018,-2935.34C5018,-2868.25 5018,-2766.28 5018,-2698.67"/>
<ellipse fill="none" stroke="#06abf7" cx="5018" cy="-2939.75" rx="4" ry="4"/>
<polygon fill="#06abf7" stroke="#06abf7" points="5018,-2698.54 5022.5,-2688.54 5018,-2693.54 5018,-2688.54 5018,-2688.54 5018,-2688.54 5018,-2693.54 5013.5,-2688.54 5018,-2698.54 5018,-2698.54"/>
</g>
<!-- OpenAPI::ParameterError -->
<g id="node10" class="node"><title>OpenAPI::ParameterError</title>
<polygon fill="none" stroke="black" points="5332.5,-2981.5 5332.5,-3027.5 5491.5,-3027.5 5491.5,-2981.5 5332.5,-2981.5"/>
<text text-anchor="middle" x="5412" y="-3012.3" font-family="Times,serif" font-size="14.00">OpenAPI::ParameterError</text>
<polyline fill="none" stroke="black" points="5332.5,-3004.5 5491.5,-3004.5 "/>
<text text-anchor="middle" x="5412" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<polygon fill="none" stroke="black" points="5203.5,-2981.5 5203.5,-3027.5 5362.5,-3027.5 5362.5,-2981.5 5203.5,-2981.5"/>
<text text-anchor="middle" x="5283" y="-3012.3" font-family="Times,serif" font-size="14.00">OpenAPI::ParameterError</text>
<polyline fill="none" stroke="black" points="5203.5,-3004.5 5362.5,-3004.5 "/>
<text text-anchor="middle" x="5283" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- UserAvatar -->
<g id="node11" class="node"><title>UserAvatar</title>
@ -253,25 +253,25 @@
</g>
<!-- Tag -->
<g id="node13" class="node"><title>Tag</title>
<path fill="none" stroke="black" d="M3662,-2959C3662,-2959 3882,-2959 3882,-2959 3888,-2959 3894,-2965 3894,-2971 3894,-2971 3894,-3038 3894,-3038 3894,-3044 3888,-3050 3882,-3050 3882,-3050 3662,-3050 3662,-3050 3656,-3050 3650,-3044 3650,-3038 3650,-3038 3650,-2971 3650,-2971 3650,-2965 3656,-2959 3662,-2959"/>
<text text-anchor="middle" x="3772" y="-3034.8" font-family="Times,serif" font-size="14.00">Tag</text>
<polyline fill="none" stroke="black" points="3650,-3027 3894,-3027 "/>
<text text-anchor="start" x="3658" y="-3011.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="3658" y="-2996.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="3658" y="-2981.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="3658" y="-2966.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M3715,-2959C3715,-2959 3935,-2959 3935,-2959 3941,-2959 3947,-2965 3947,-2971 3947,-2971 3947,-3038 3947,-3038 3947,-3044 3941,-3050 3935,-3050 3935,-3050 3715,-3050 3715,-3050 3709,-3050 3703,-3044 3703,-3038 3703,-3038 3703,-2971 3703,-2971 3703,-2965 3709,-2959 3715,-2959"/>
<text text-anchor="middle" x="3825" y="-3034.8" font-family="Times,serif" font-size="14.00">Tag</text>
<polyline fill="none" stroke="black" points="3703,-3027 3947,-3027 "/>
<text text-anchor="start" x="3711" y="-3011.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="3711" y="-2996.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="3711" y="-2981.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="3711" y="-2966.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Tag&#45;&gt;AvailabilityTag -->
<g id="edge9" class="edge"><title>Tag&#45;&gt;AvailabilityTag</title>
<path fill="none" stroke="#74bf7c" d="M3902.46,-2995C3982.61,-2982.58 4080.6,-2953.09 4138,-2884 4313.91,-2672.25 4276.78,-2310.55 4252.94,-2165.94"/>
<ellipse fill="none" stroke="#74bf7c" cx="3898.22" cy="-2995.63" rx="4.00001" ry="4.00001"/>
<polygon fill="#74bf7c" stroke="#74bf7c" points="4252.91,-2165.77 4255.69,-2155.16 4252.08,-2160.84 4251.25,-2155.91 4251.25,-2155.91 4251.25,-2155.91 4252.08,-2160.84 4246.81,-2156.65 4252.91,-2165.77 4252.91,-2165.77"/>
<path fill="none" stroke="#59c59b" d="M3955.13,-2985.62C4019.95,-2969.8 4093.73,-2940.03 4138,-2884 4225.68,-2773.02 4238.91,-2331.39 4240.76,-2166.24"/>
<ellipse fill="none" stroke="#59c59b" cx="3951.17" cy="-2986.55" rx="4.00001" ry="4.00001"/>
<polygon fill="#59c59b" stroke="#59c59b" points="4240.77,-2165.77 4245.37,-2155.82 4240.82,-2160.77 4240.87,-2155.77 4240.87,-2155.77 4240.87,-2155.77 4240.82,-2160.77 4236.37,-2155.73 4240.77,-2165.77 4240.77,-2165.77"/>
</g>
<!-- Tag&#45;&gt;User -->
<g id="edge8" class="edge"><title>Tag&#45;&gt;User</title>
<path fill="none" stroke="#88e785" d="M3639.8,-2971.78C3356.18,-2903.74 2689.75,-2743.86 2377.69,-2668.99"/>
<polygon fill="#88e785" stroke="#88e785" points="3640.11,-2971.86 3648.79,-2978.57 3644.97,-2973.03 3649.84,-2974.19 3649.84,-2974.19 3649.84,-2974.19 3644.97,-2973.03 3650.89,-2969.82 3640.11,-2971.86 3640.11,-2971.86"/>
<polygon fill="#88e785" stroke="#88e785" points="2377.37,-2668.91 2368.7,-2662.21 2372.51,-2667.75 2367.65,-2666.58 2367.65,-2666.58 2367.65,-2666.58 2372.51,-2667.75 2366.6,-2670.96 2377.37,-2668.91 2377.37,-2668.91"/>
<path fill="none" stroke="#5afd6f" d="M3692.79,-2972.82C3400.35,-2904.97 2699.14,-2742.26 2377.43,-2667.62"/>
<polygon fill="#5afd6f" stroke="#5afd6f" points="3692.95,-2972.86 3701.68,-2979.5 3697.82,-2973.99 3702.69,-2975.12 3702.69,-2975.12 3702.69,-2975.12 3697.82,-2973.99 3703.71,-2970.74 3692.95,-2972.86 3692.95,-2972.86"/>
<polygon fill="#5afd6f" stroke="#5afd6f" points="2377.3,-2667.59 2368.57,-2660.94 2372.43,-2666.46 2367.56,-2665.33 2367.56,-2665.33 2367.56,-2665.33 2372.43,-2666.46 2366.54,-2669.71 2377.3,-2667.59 2377.3,-2667.59"/>
</g>
<!-- Availability -->
<g id="node53" class="node"><title>Availability</title>
@ -289,9 +289,9 @@
</g>
<!-- Tag&#45;&gt;Availability -->
<g id="edge10" class="edge"><title>Tag&#45;&gt;Availability</title>
<path fill="none" stroke="#a0ced8" d="M3805.64,-2949.88C3844.6,-2887.8 3909.25,-2784.78 3954.76,-2712.25"/>
<polygon fill="#a0ced8" stroke="#a0ced8" points="3805.43,-2950.23 3796.3,-2956.31 3802.77,-2954.46 3800.11,-2958.7 3800.11,-2958.7 3800.11,-2958.7 3802.77,-2954.46 3803.92,-2961.09 3805.43,-2950.23 3805.43,-2950.23"/>
<polygon fill="#a0ced8" stroke="#a0ced8" points="3954.9,-2712.03 3964.02,-2705.96 3957.55,-2707.8 3960.21,-2703.56 3960.21,-2703.56 3960.21,-2703.56 3957.55,-2707.8 3956.4,-2701.17 3954.9,-2712.03 3954.9,-2712.03"/>
<path fill="none" stroke="#616c0f" d="M3851.25,-2949.49C3881.38,-2887.48 3931.17,-2785.03 3966.33,-2712.68"/>
<polygon fill="#616c0f" stroke="#616c0f" points="3851.14,-2949.7 3842.73,-2956.73 3848.96,-2954.2 3846.77,-2958.7 3846.77,-2958.7 3846.77,-2958.7 3848.96,-2954.2 3850.82,-2960.67 3851.14,-2949.7 3851.14,-2949.7"/>
<polygon fill="#616c0f" stroke="#616c0f" points="3966.39,-2712.56 3974.81,-2705.53 3968.58,-2708.06 3970.76,-2703.56 3970.76,-2703.56 3970.76,-2703.56 3968.58,-2708.06 3966.72,-2701.6 3966.39,-2712.56 3966.39,-2712.56"/>
</g>
<!-- UserTag -->
<g id="node66" class="node"><title>UserTag</title>
@ -306,80 +306,80 @@
</g>
<!-- Tag&#45;&gt;UserTag -->
<g id="edge7" class="edge"><title>Tag&#45;&gt;UserTag</title>
<path fill="none" stroke="#fcd3a4" d="M3728.91,-2952.55C3633.67,-2839.71 3398.52,-2559.77 3207,-2321 3164.75,-2268.33 3117.69,-2207.58 3083.98,-2163.7"/>
<ellipse fill="none" stroke="#fcd3a4" cx="3731.58" cy="-2955.72" rx="4.00002" ry="4.00002"/>
<polygon fill="#fcd3a4" stroke="#fcd3a4" points="3083.93,-2163.64 3081.41,-2152.97 3080.89,-2159.68 3077.85,-2155.71 3077.85,-2155.71 3077.85,-2155.71 3080.89,-2159.68 3074.28,-2158.45 3083.93,-2163.64 3083.93,-2163.64"/>
<path fill="none" stroke="#c0d245" d="M3776.66,-2952.79C3670.7,-2841.06 3411.17,-2564.29 3207,-2321 3163.45,-2269.1 3116.34,-2208.03 3082.95,-2163.83"/>
<ellipse fill="none" stroke="#c0d245" cx="3779.44" cy="-2955.72" rx="4.00002" ry="4.00002"/>
<polygon fill="#c0d245" stroke="#c0d245" points="3082.9,-2163.77 3080.47,-2153.07 3079.89,-2159.78 3076.88,-2155.78 3076.88,-2155.78 3076.88,-2155.78 3079.89,-2159.78 3073.28,-2158.49 3082.9,-2163.77 3082.9,-2163.77"/>
</g>
<!-- Event -->
<g id="node14" class="node"><title>Event</title>
<path fill="none" stroke="black" d="M4434,-1997C4434,-1997 4654,-1997 4654,-1997 4660,-1997 4666,-2003 4666,-2009 4666,-2009 4666,-2196 4666,-2196 4666,-2202 4660,-2208 4654,-2208 4654,-2208 4434,-2208 4434,-2208 4428,-2208 4422,-2202 4422,-2196 4422,-2196 4422,-2009 4422,-2009 4422,-2003 4428,-1997 4434,-1997"/>
<text text-anchor="middle" x="4544" y="-2192.8" font-family="Times,serif" font-size="14.00">Event</text>
<polyline fill="none" stroke="black" points="4422,-2185 4666,-2185 "/>
<text text-anchor="start" x="4430" y="-2169.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4430" y="-2154.8" font-family="Times,serif" font-size="14.00">title :character varying(255)</text>
<text text-anchor="start" x="4430" y="-2139.8" font-family="Times,serif" font-size="14.00">description :text</text>
<text text-anchor="start" x="4430" y="-2124.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4430" y="-2109.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="4430" y="-2094.8" font-family="Times,serif" font-size="14.00">availability_id :integer</text>
<text text-anchor="start" x="4430" y="-2079.8" font-family="Times,serif" font-size="14.00">amount :integer</text>
<text text-anchor="start" x="4430" y="-2064.8" font-family="Times,serif" font-size="14.00">nb_total_places :integer</text>
<text text-anchor="start" x="4430" y="-2049.8" font-family="Times,serif" font-size="14.00">nb_free_places :integer</text>
<text text-anchor="start" x="4430" y="-2034.8" font-family="Times,serif" font-size="14.00">recurrence_id :integer</text>
<text text-anchor="start" x="4430" y="-2019.8" font-family="Times,serif" font-size="14.00">age_range_id :integer</text>
<text text-anchor="start" x="4430" y="-2004.8" font-family="Times,serif" font-size="14.00">category_id :integer</text>
<path fill="none" stroke="black" d="M4433,-1997C4433,-1997 4653,-1997 4653,-1997 4659,-1997 4665,-2003 4665,-2009 4665,-2009 4665,-2196 4665,-2196 4665,-2202 4659,-2208 4653,-2208 4653,-2208 4433,-2208 4433,-2208 4427,-2208 4421,-2202 4421,-2196 4421,-2196 4421,-2009 4421,-2009 4421,-2003 4427,-1997 4433,-1997"/>
<text text-anchor="middle" x="4543" y="-2192.8" font-family="Times,serif" font-size="14.00">Event</text>
<polyline fill="none" stroke="black" points="4421,-2185 4665,-2185 "/>
<text text-anchor="start" x="4429" y="-2169.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4429" y="-2154.8" font-family="Times,serif" font-size="14.00">title :character varying(255)</text>
<text text-anchor="start" x="4429" y="-2139.8" font-family="Times,serif" font-size="14.00">description :text</text>
<text text-anchor="start" x="4429" y="-2124.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4429" y="-2109.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="4429" y="-2094.8" font-family="Times,serif" font-size="14.00">availability_id :integer</text>
<text text-anchor="start" x="4429" y="-2079.8" font-family="Times,serif" font-size="14.00">amount :integer</text>
<text text-anchor="start" x="4429" y="-2064.8" font-family="Times,serif" font-size="14.00">nb_total_places :integer</text>
<text text-anchor="start" x="4429" y="-2049.8" font-family="Times,serif" font-size="14.00">nb_free_places :integer</text>
<text text-anchor="start" x="4429" y="-2034.8" font-family="Times,serif" font-size="14.00">recurrence_id :integer</text>
<text text-anchor="start" x="4429" y="-2019.8" font-family="Times,serif" font-size="14.00">age_range_id :integer</text>
<text text-anchor="start" x="4429" y="-2004.8" font-family="Times,serif" font-size="14.00">category_id :integer</text>
</g>
<!-- PriceCategory -->
<g id="node27" class="node"><title>PriceCategory</title>
<path fill="none" stroke="black" d="M4996,-1619.5C4996,-1619.5 5216,-1619.5 5216,-1619.5 5222,-1619.5 5228,-1625.5 5228,-1631.5 5228,-1631.5 5228,-1713.5 5228,-1713.5 5228,-1719.5 5222,-1725.5 5216,-1725.5 5216,-1725.5 4996,-1725.5 4996,-1725.5 4990,-1725.5 4984,-1719.5 4984,-1713.5 4984,-1713.5 4984,-1631.5 4984,-1631.5 4984,-1625.5 4990,-1619.5 4996,-1619.5"/>
<text text-anchor="middle" x="5106" y="-1710.3" font-family="Times,serif" font-size="14.00">PriceCategory</text>
<polyline fill="none" stroke="black" points="4984,-1702.5 5228,-1702.5 "/>
<text text-anchor="start" x="4992" y="-1687.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4992" y="-1672.3" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="4992" y="-1657.3" font-family="Times,serif" font-size="14.00">conditions :text</text>
<text text-anchor="start" x="4992" y="-1642.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4992" y="-1627.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M4995,-1619.5C4995,-1619.5 5215,-1619.5 5215,-1619.5 5221,-1619.5 5227,-1625.5 5227,-1631.5 5227,-1631.5 5227,-1713.5 5227,-1713.5 5227,-1719.5 5221,-1725.5 5215,-1725.5 5215,-1725.5 4995,-1725.5 4995,-1725.5 4989,-1725.5 4983,-1719.5 4983,-1713.5 4983,-1713.5 4983,-1631.5 4983,-1631.5 4983,-1625.5 4989,-1619.5 4995,-1619.5"/>
<text text-anchor="middle" x="5105" y="-1710.3" font-family="Times,serif" font-size="14.00">PriceCategory</text>
<polyline fill="none" stroke="black" points="4983,-1702.5 5227,-1702.5 "/>
<text text-anchor="start" x="4991" y="-1687.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4991" y="-1672.3" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="4991" y="-1657.3" font-family="Times,serif" font-size="14.00">conditions :text</text>
<text text-anchor="start" x="4991" y="-1642.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4991" y="-1627.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Event&#45;&gt;PriceCategory -->
<g id="edge16" class="edge"><title>Event&#45;&gt;PriceCategory</title>
<path fill="none" stroke="#86a999" d="M4674.38,-2002.21C4784.51,-1918.34 4938.46,-1801.1 5029.63,-1731.66"/>
<polygon fill="#86a999" stroke="#86a999" points="4674.25,-2002.31 4663.57,-2004.79 4670.27,-2005.34 4666.29,-2008.37 4666.29,-2008.37 4666.29,-2008.37 4670.27,-2005.34 4669.02,-2011.95 4674.25,-2002.31 4674.25,-2002.31"/>
<polygon fill="#86a999" stroke="#86a999" points="5029.75,-1731.57 5040.43,-1729.09 5033.73,-1728.54 5037.71,-1725.51 5037.71,-1725.51 5037.71,-1725.51 5033.73,-1728.54 5034.98,-1721.93 5029.75,-1731.57 5029.75,-1731.57"/>
<path fill="none" stroke="#031475" d="M4673.38,-2002.21C4783.51,-1918.34 4937.46,-1801.1 5028.63,-1731.66"/>
<polygon fill="#031475" stroke="#031475" points="4673.25,-2002.31 4662.57,-2004.79 4669.27,-2005.34 4665.29,-2008.37 4665.29,-2008.37 4665.29,-2008.37 4669.27,-2005.34 4668.02,-2011.95 4673.25,-2002.31 4673.25,-2002.31"/>
<polygon fill="#031475" stroke="#031475" points="5028.75,-1731.57 5039.43,-1729.09 5032.73,-1728.54 5036.71,-1725.51 5036.71,-1725.51 5036.71,-1725.51 5032.73,-1728.54 5033.98,-1721.93 5028.75,-1731.57 5028.75,-1731.57"/>
</g>
<!-- EventTheme -->
<g id="node38" class="node"><title>EventTheme</title>
<path fill="none" stroke="black" d="M4172,-1619.5C4172,-1619.5 4392,-1619.5 4392,-1619.5 4398,-1619.5 4404,-1625.5 4404,-1631.5 4404,-1631.5 4404,-1713.5 4404,-1713.5 4404,-1719.5 4398,-1725.5 4392,-1725.5 4392,-1725.5 4172,-1725.5 4172,-1725.5 4166,-1725.5 4160,-1719.5 4160,-1713.5 4160,-1713.5 4160,-1631.5 4160,-1631.5 4160,-1625.5 4166,-1619.5 4172,-1619.5"/>
<text text-anchor="middle" x="4282" y="-1710.3" font-family="Times,serif" font-size="14.00">EventTheme</text>
<polyline fill="none" stroke="black" points="4160,-1702.5 4404,-1702.5 "/>
<text text-anchor="start" x="4168" y="-1687.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4168" y="-1672.3" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="4168" y="-1657.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4168" y="-1642.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="4168" y="-1627.3" font-family="Times,serif" font-size="14.00">slug :character varying</text>
<path fill="none" stroke="black" d="M4171,-1619.5C4171,-1619.5 4391,-1619.5 4391,-1619.5 4397,-1619.5 4403,-1625.5 4403,-1631.5 4403,-1631.5 4403,-1713.5 4403,-1713.5 4403,-1719.5 4397,-1725.5 4391,-1725.5 4391,-1725.5 4171,-1725.5 4171,-1725.5 4165,-1725.5 4159,-1719.5 4159,-1713.5 4159,-1713.5 4159,-1631.5 4159,-1631.5 4159,-1625.5 4165,-1619.5 4171,-1619.5"/>
<text text-anchor="middle" x="4281" y="-1710.3" font-family="Times,serif" font-size="14.00">EventTheme</text>
<polyline fill="none" stroke="black" points="4159,-1702.5 4403,-1702.5 "/>
<text text-anchor="start" x="4167" y="-1687.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4167" y="-1672.3" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="4167" y="-1657.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4167" y="-1642.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="4167" y="-1627.3" font-family="Times,serif" font-size="14.00">slug :character varying</text>
</g>
<!-- Event&#45;&gt;EventTheme -->
<g id="edge14" class="edge"><title>Event&#45;&gt;EventTheme</title>
<path fill="none" stroke="#29aa14" d="M4474.6,-1988.13C4424.73,-1906.67 4359.44,-1800.01 4319.13,-1734.16"/>
<polygon fill="#29aa14" stroke="#29aa14" points="4474.69,-1988.27 4476.07,-1999.15 4477.3,-1992.53 4479.91,-1996.8 4479.91,-1996.8 4479.91,-1996.8 4477.3,-1992.53 4483.75,-1994.45 4474.69,-1988.27 4474.69,-1988.27"/>
<polygon fill="#29aa14" stroke="#29aa14" points="4319.08,-1734.07 4317.7,-1723.19 4316.47,-1729.81 4313.86,-1725.54 4313.86,-1725.54 4313.86,-1725.54 4316.47,-1729.81 4310.02,-1727.89 4319.08,-1734.07 4319.08,-1734.07"/>
<path fill="none" stroke="#92fca1" d="M4473.6,-1988.13C4423.73,-1906.67 4358.44,-1800.01 4318.13,-1734.16"/>
<polygon fill="#92fca1" stroke="#92fca1" points="4473.69,-1988.27 4475.07,-1999.15 4476.3,-1992.53 4478.91,-1996.8 4478.91,-1996.8 4478.91,-1996.8 4476.3,-1992.53 4482.75,-1994.45 4473.69,-1988.27 4473.69,-1988.27"/>
<polygon fill="#92fca1" stroke="#92fca1" points="4318.08,-1734.07 4316.7,-1723.19 4315.47,-1729.81 4312.86,-1725.54 4312.86,-1725.54 4312.86,-1725.54 4315.47,-1729.81 4309.02,-1727.89 4318.08,-1734.07 4318.08,-1734.07"/>
</g>
<!-- EventImage -->
<g id="node43" class="node"><title>EventImage</title>
<path fill="none" stroke="black" d="M4434,-1604.5C4434,-1604.5 4654,-1604.5 4654,-1604.5 4660,-1604.5 4666,-1610.5 4666,-1616.5 4666,-1616.5 4666,-1728.5 4666,-1728.5 4666,-1734.5 4660,-1740.5 4654,-1740.5 4654,-1740.5 4434,-1740.5 4434,-1740.5 4428,-1740.5 4422,-1734.5 4422,-1728.5 4422,-1728.5 4422,-1616.5 4422,-1616.5 4422,-1610.5 4428,-1604.5 4434,-1604.5"/>
<text text-anchor="middle" x="4544" y="-1725.3" font-family="Times,serif" font-size="14.00">EventImage</text>
<polyline fill="none" stroke="black" points="4422,-1717.5 4666,-1717.5 "/>
<text text-anchor="start" x="4430" y="-1702.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4430" y="-1687.3" font-family="Times,serif" font-size="14.00">viewable_id :integer</text>
<text text-anchor="start" x="4430" y="-1672.3" font-family="Times,serif" font-size="14.00">viewable_type :character varying(255)</text>
<text text-anchor="start" x="4430" y="-1657.3" font-family="Times,serif" font-size="14.00">attachment :character varying(255)</text>
<text text-anchor="start" x="4430" y="-1642.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="4430" y="-1627.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4430" y="-1612.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M4433,-1604.5C4433,-1604.5 4653,-1604.5 4653,-1604.5 4659,-1604.5 4665,-1610.5 4665,-1616.5 4665,-1616.5 4665,-1728.5 4665,-1728.5 4665,-1734.5 4659,-1740.5 4653,-1740.5 4653,-1740.5 4433,-1740.5 4433,-1740.5 4427,-1740.5 4421,-1734.5 4421,-1728.5 4421,-1728.5 4421,-1616.5 4421,-1616.5 4421,-1610.5 4427,-1604.5 4433,-1604.5"/>
<text text-anchor="middle" x="4543" y="-1725.3" font-family="Times,serif" font-size="14.00">EventImage</text>
<polyline fill="none" stroke="black" points="4421,-1717.5 4665,-1717.5 "/>
<text text-anchor="start" x="4429" y="-1702.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4429" y="-1687.3" font-family="Times,serif" font-size="14.00">viewable_id :integer</text>
<text text-anchor="start" x="4429" y="-1672.3" font-family="Times,serif" font-size="14.00">viewable_type :character varying(255)</text>
<text text-anchor="start" x="4429" y="-1657.3" font-family="Times,serif" font-size="14.00">attachment :character varying(255)</text>
<text text-anchor="start" x="4429" y="-1642.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="4429" y="-1627.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4429" y="-1612.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Event&#45;&gt;EventImage -->
<g id="edge11" class="edge"><title>Event&#45;&gt;EventImage</title>
<path fill="none" stroke="#e4f36c" d="M4544,-1988.76C4544,-1913.12 4544,-1815.56 4544,-1749.13"/>
<ellipse fill="none" stroke="#e4f36c" cx="4544" cy="-1992.8" rx="4" ry="4"/>
<ellipse fill="#e4f36c" stroke="#e4f36c" cx="4544" cy="-1744.78" rx="4" ry="4"/>
<path fill="none" stroke="#869c15" d="M4543,-1988.76C4543,-1913.12 4543,-1815.56 4543,-1749.13"/>
<ellipse fill="none" stroke="#869c15" cx="4543" cy="-1992.8" rx="4" ry="4"/>
<ellipse fill="#869c15" stroke="#869c15" cx="4543" cy="-1744.78" rx="4" ry="4"/>
</g>
<!-- Reservation -->
<g id="node58" class="node"><title>Reservation</title>
@ -398,94 +398,94 @@
</g>
<!-- Event&#45;&gt;Reservation -->
<g id="edge13" class="edge"><title>Event&#45;&gt;Reservation</title>
<path fill="none" stroke="#72fbab" d="M4471.05,-1989.95C4443.17,-1953.04 4409.08,-1913.82 4372,-1884 4357.75,-1872.54 4350.83,-1875.16 4335,-1866 4249.44,-1816.47 4208.01,-1821.77 4151,-1741 4065.71,-1620.17 4122.43,-1556.12 4067,-1419 4059.69,-1400.92 4050.56,-1382.29 4041.07,-1364.65"/>
<ellipse fill="none" stroke="#72fbab" cx="4473.79" cy="-1993.61" rx="4.00002" ry="4.00002"/>
<polygon fill="#72fbab" stroke="#72fbab" points="4040.88,-1364.3 4040.03,-1353.37 4038.48,-1359.91 4036.08,-1355.53 4036.08,-1355.53 4036.08,-1355.53 4038.48,-1359.91 4032.13,-1357.69 4040.88,-1364.3 4040.88,-1364.3"/>
<path fill="none" stroke="#74f915" d="M4470.95,-1989.98C4443.22,-1952.97 4409.2,-1913.68 4372,-1884 4357.39,-1872.34 4350.22,-1875.28 4334,-1866 4248.18,-1816.92 4206.89,-1821.85 4150,-1741 4064.95,-1620.13 4122.19,-1556.1 4067,-1419 4059.72,-1400.9 4050.6,-1382.27 4041.11,-1364.63"/>
<ellipse fill="none" stroke="#74f915" cx="4473.67" cy="-1993.65" rx="4.00002" ry="4.00002"/>
<polygon fill="#74f915" stroke="#74f915" points="4040.92,-1364.28 4040.07,-1353.35 4038.52,-1359.9 4036.12,-1355.51 4036.12,-1355.51 4036.12,-1355.51 4038.52,-1359.9 4032.18,-1357.67 4040.92,-1364.28 4040.92,-1364.28"/>
</g>
<!-- EventPriceCategory -->
<g id="node64" class="node"><title>EventPriceCategory</title>
<path fill="none" stroke="black" d="M4584,-1212C4584,-1212 4804,-1212 4804,-1212 4810,-1212 4816,-1218 4816,-1224 4816,-1224 4816,-1321 4816,-1321 4816,-1327 4810,-1333 4804,-1333 4804,-1333 4584,-1333 4584,-1333 4578,-1333 4572,-1327 4572,-1321 4572,-1321 4572,-1224 4572,-1224 4572,-1218 4578,-1212 4584,-1212"/>
<text text-anchor="middle" x="4694" y="-1317.8" font-family="Times,serif" font-size="14.00">EventPriceCategory</text>
<polyline fill="none" stroke="black" points="4572,-1310 4816,-1310 "/>
<text text-anchor="start" x="4580" y="-1294.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4580" y="-1279.8" font-family="Times,serif" font-size="14.00">event_id :integer</text>
<text text-anchor="start" x="4580" y="-1264.8" font-family="Times,serif" font-size="14.00">price_category_id :integer</text>
<text text-anchor="start" x="4580" y="-1249.8" font-family="Times,serif" font-size="14.00">amount :integer</text>
<text text-anchor="start" x="4580" y="-1234.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4580" y="-1219.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M4583,-1212C4583,-1212 4803,-1212 4803,-1212 4809,-1212 4815,-1218 4815,-1224 4815,-1224 4815,-1321 4815,-1321 4815,-1327 4809,-1333 4803,-1333 4803,-1333 4583,-1333 4583,-1333 4577,-1333 4571,-1327 4571,-1321 4571,-1321 4571,-1224 4571,-1224 4571,-1218 4577,-1212 4583,-1212"/>
<text text-anchor="middle" x="4693" y="-1317.8" font-family="Times,serif" font-size="14.00">EventPriceCategory</text>
<polyline fill="none" stroke="black" points="4571,-1310 4815,-1310 "/>
<text text-anchor="start" x="4579" y="-1294.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4579" y="-1279.8" font-family="Times,serif" font-size="14.00">event_id :integer</text>
<text text-anchor="start" x="4579" y="-1264.8" font-family="Times,serif" font-size="14.00">price_category_id :integer</text>
<text text-anchor="start" x="4579" y="-1249.8" font-family="Times,serif" font-size="14.00">amount :integer</text>
<text text-anchor="start" x="4579" y="-1234.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4579" y="-1219.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Event&#45;&gt;EventPriceCategory -->
<g id="edge15" class="edge"><title>Event&#45;&gt;EventPriceCategory</title>
<path fill="none" stroke="#e63047" d="M4594.99,-1989.15C4624.11,-1919.29 4658.1,-1826.73 4675,-1741 4702.4,-1601.96 4701.28,-1435.31 4697.79,-1343.26"/>
<ellipse fill="none" stroke="#e63047" cx="4593.37" cy="-1993.01" rx="4.00002" ry="4.00002"/>
<polygon fill="#e63047" stroke="#e63047" points="4697.78,-1343.21 4701.88,-1333.04 4697.58,-1338.22 4697.38,-1333.22 4697.38,-1333.22 4697.38,-1333.22 4697.58,-1338.22 4692.89,-1333.4 4697.78,-1343.21 4697.78,-1343.21"/>
<path fill="none" stroke="#fea59e" d="M4593.99,-1989.15C4623.11,-1919.29 4657.1,-1826.73 4674,-1741 4701.4,-1601.96 4700.28,-1435.31 4696.79,-1343.26"/>
<ellipse fill="none" stroke="#fea59e" cx="4592.37" cy="-1993.01" rx="4.00002" ry="4.00002"/>
<polygon fill="#fea59e" stroke="#fea59e" points="4696.78,-1343.21 4700.88,-1333.04 4696.58,-1338.22 4696.38,-1333.22 4696.38,-1333.22 4696.38,-1333.22 4696.58,-1338.22 4691.89,-1333.4 4696.78,-1343.21 4696.78,-1343.21"/>
</g>
<!-- EventFile -->
<g id="node65" class="node"><title>EventFile</title>
<path fill="none" stroke="black" d="M4734,-1604.5C4734,-1604.5 4954,-1604.5 4954,-1604.5 4960,-1604.5 4966,-1610.5 4966,-1616.5 4966,-1616.5 4966,-1728.5 4966,-1728.5 4966,-1734.5 4960,-1740.5 4954,-1740.5 4954,-1740.5 4734,-1740.5 4734,-1740.5 4728,-1740.5 4722,-1734.5 4722,-1728.5 4722,-1728.5 4722,-1616.5 4722,-1616.5 4722,-1610.5 4728,-1604.5 4734,-1604.5"/>
<text text-anchor="middle" x="4844" y="-1725.3" font-family="Times,serif" font-size="14.00">EventFile</text>
<polyline fill="none" stroke="black" points="4722,-1717.5 4966,-1717.5 "/>
<text text-anchor="start" x="4730" y="-1702.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4730" y="-1687.3" font-family="Times,serif" font-size="14.00">viewable_id :integer</text>
<text text-anchor="start" x="4730" y="-1672.3" font-family="Times,serif" font-size="14.00">viewable_type :character varying(255)</text>
<text text-anchor="start" x="4730" y="-1657.3" font-family="Times,serif" font-size="14.00">attachment :character varying(255)</text>
<text text-anchor="start" x="4730" y="-1642.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="4730" y="-1627.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4730" y="-1612.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M4733,-1604.5C4733,-1604.5 4953,-1604.5 4953,-1604.5 4959,-1604.5 4965,-1610.5 4965,-1616.5 4965,-1616.5 4965,-1728.5 4965,-1728.5 4965,-1734.5 4959,-1740.5 4953,-1740.5 4953,-1740.5 4733,-1740.5 4733,-1740.5 4727,-1740.5 4721,-1734.5 4721,-1728.5 4721,-1728.5 4721,-1616.5 4721,-1616.5 4721,-1610.5 4727,-1604.5 4733,-1604.5"/>
<text text-anchor="middle" x="4843" y="-1725.3" font-family="Times,serif" font-size="14.00">EventFile</text>
<polyline fill="none" stroke="black" points="4721,-1717.5 4965,-1717.5 "/>
<text text-anchor="start" x="4729" y="-1702.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4729" y="-1687.3" font-family="Times,serif" font-size="14.00">viewable_id :integer</text>
<text text-anchor="start" x="4729" y="-1672.3" font-family="Times,serif" font-size="14.00">viewable_type :character varying(255)</text>
<text text-anchor="start" x="4729" y="-1657.3" font-family="Times,serif" font-size="14.00">attachment :character varying(255)</text>
<text text-anchor="start" x="4729" y="-1642.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="4729" y="-1627.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4729" y="-1612.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Event&#45;&gt;EventFile -->
<g id="edge12" class="edge"><title>Event&#45;&gt;EventFile</title>
<path fill="none" stroke="#896508" d="M4622.02,-1990.19C4675.16,-1914.38 4744.1,-1816.03 4790.95,-1749.18"/>
<ellipse fill="none" stroke="#896508" cx="4619.68" cy="-1993.52" rx="4.00002" ry="4.00002"/>
<polygon fill="#896508" stroke="#896508" points="4791.1,-1748.97 4800.53,-1743.36 4793.97,-1744.87 4796.84,-1740.78 4796.84,-1740.78 4796.84,-1740.78 4793.97,-1744.87 4793.16,-1738.2 4791.1,-1748.97 4791.1,-1748.97"/>
<path fill="none" stroke="#b83157" d="M4621.02,-1990.19C4674.16,-1914.38 4743.1,-1816.03 4789.95,-1749.18"/>
<ellipse fill="none" stroke="#b83157" cx="4618.68" cy="-1993.52" rx="4.00002" ry="4.00002"/>
<polygon fill="#b83157" stroke="#b83157" points="4790.1,-1748.97 4799.53,-1743.36 4792.97,-1744.87 4795.84,-1740.78 4795.84,-1740.78 4795.84,-1740.78 4792.97,-1744.87 4792.16,-1738.2 4790.1,-1748.97 4790.1,-1748.97"/>
</g>
<!-- StatisticSubType -->
<g id="node15" class="node"><title>StatisticSubType</title>
<path fill="none" stroke="black" d="M5632,-2951.5C5632,-2951.5 5852,-2951.5 5852,-2951.5 5858,-2951.5 5864,-2957.5 5864,-2963.5 5864,-2963.5 5864,-3045.5 5864,-3045.5 5864,-3051.5 5858,-3057.5 5852,-3057.5 5852,-3057.5 5632,-3057.5 5632,-3057.5 5626,-3057.5 5620,-3051.5 5620,-3045.5 5620,-3045.5 5620,-2963.5 5620,-2963.5 5620,-2957.5 5626,-2951.5 5632,-2951.5"/>
<text text-anchor="middle" x="5742" y="-3042.3" font-family="Times,serif" font-size="14.00">StatisticSubType</text>
<polyline fill="none" stroke="black" points="5620,-3034.5 5864,-3034.5 "/>
<text text-anchor="start" x="5628" y="-3019.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5628" y="-3004.3" font-family="Times,serif" font-size="14.00">key :character varying(255)</text>
<text text-anchor="start" x="5628" y="-2989.3" font-family="Times,serif" font-size="14.00">label :character varying(255)</text>
<text text-anchor="start" x="5628" y="-2974.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5628" y="-2959.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M5416,-2951.5C5416,-2951.5 5636,-2951.5 5636,-2951.5 5642,-2951.5 5648,-2957.5 5648,-2963.5 5648,-2963.5 5648,-3045.5 5648,-3045.5 5648,-3051.5 5642,-3057.5 5636,-3057.5 5636,-3057.5 5416,-3057.5 5416,-3057.5 5410,-3057.5 5404,-3051.5 5404,-3045.5 5404,-3045.5 5404,-2963.5 5404,-2963.5 5404,-2957.5 5410,-2951.5 5416,-2951.5"/>
<text text-anchor="middle" x="5526" y="-3042.3" font-family="Times,serif" font-size="14.00">StatisticSubType</text>
<polyline fill="none" stroke="black" points="5404,-3034.5 5648,-3034.5 "/>
<text text-anchor="start" x="5412" y="-3019.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5412" y="-3004.3" font-family="Times,serif" font-size="14.00">key :character varying(255)</text>
<text text-anchor="start" x="5412" y="-2989.3" font-family="Times,serif" font-size="14.00">label :character varying(255)</text>
<text text-anchor="start" x="5412" y="-2974.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5412" y="-2959.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- StatisticType -->
<g id="node32" class="node"><title>StatisticType</title>
<path fill="none" stroke="black" d="M5562,-2552.5C5562,-2552.5 5782,-2552.5 5782,-2552.5 5788,-2552.5 5794,-2558.5 5794,-2564.5 5794,-2564.5 5794,-2691.5 5794,-2691.5 5794,-2697.5 5788,-2703.5 5782,-2703.5 5782,-2703.5 5562,-2703.5 5562,-2703.5 5556,-2703.5 5550,-2697.5 5550,-2691.5 5550,-2691.5 5550,-2564.5 5550,-2564.5 5550,-2558.5 5556,-2552.5 5562,-2552.5"/>
<text text-anchor="middle" x="5672" y="-2688.3" font-family="Times,serif" font-size="14.00">StatisticType</text>
<polyline fill="none" stroke="black" points="5550,-2680.5 5794,-2680.5 "/>
<text text-anchor="start" x="5558" y="-2665.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5558" y="-2650.3" font-family="Times,serif" font-size="14.00">statistic_index_id :integer</text>
<text text-anchor="start" x="5558" y="-2635.3" font-family="Times,serif" font-size="14.00">key :character varying(255)</text>
<text text-anchor="start" x="5558" y="-2620.3" font-family="Times,serif" font-size="14.00">label :character varying(255)</text>
<text text-anchor="start" x="5558" y="-2605.3" font-family="Times,serif" font-size="14.00">graph :boolean</text>
<text text-anchor="start" x="5558" y="-2590.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5558" y="-2575.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="5558" y="-2560.3" font-family="Times,serif" font-size="14.00">simple :boolean</text>
<path fill="none" stroke="black" d="M5607,-2552.5C5607,-2552.5 5827,-2552.5 5827,-2552.5 5833,-2552.5 5839,-2558.5 5839,-2564.5 5839,-2564.5 5839,-2691.5 5839,-2691.5 5839,-2697.5 5833,-2703.5 5827,-2703.5 5827,-2703.5 5607,-2703.5 5607,-2703.5 5601,-2703.5 5595,-2697.5 5595,-2691.5 5595,-2691.5 5595,-2564.5 5595,-2564.5 5595,-2558.5 5601,-2552.5 5607,-2552.5"/>
<text text-anchor="middle" x="5717" y="-2688.3" font-family="Times,serif" font-size="14.00">StatisticType</text>
<polyline fill="none" stroke="black" points="5595,-2680.5 5839,-2680.5 "/>
<text text-anchor="start" x="5603" y="-2665.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5603" y="-2650.3" font-family="Times,serif" font-size="14.00">statistic_index_id :integer</text>
<text text-anchor="start" x="5603" y="-2635.3" font-family="Times,serif" font-size="14.00">key :character varying(255)</text>
<text text-anchor="start" x="5603" y="-2620.3" font-family="Times,serif" font-size="14.00">label :character varying(255)</text>
<text text-anchor="start" x="5603" y="-2605.3" font-family="Times,serif" font-size="14.00">graph :boolean</text>
<text text-anchor="start" x="5603" y="-2590.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5603" y="-2575.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="5603" y="-2560.3" font-family="Times,serif" font-size="14.00">simple :boolean</text>
</g>
<!-- StatisticSubType&#45;&gt;StatisticType -->
<g id="edge18" class="edge"><title>StatisticSubType&#45;&gt;StatisticType</title>
<path fill="none" stroke="#cb7b7a" d="M5730.37,-2941.27C5718.73,-2878.99 5700.73,-2782.73 5687.8,-2713.55"/>
<polygon fill="#cb7b7a" stroke="#cb7b7a" points="5730.43,-2941.6 5727.84,-2952.25 5731.35,-2946.51 5732.27,-2951.43 5732.27,-2951.43 5732.27,-2951.43 5731.35,-2946.51 5736.69,-2950.6 5730.43,-2941.6 5730.43,-2941.6"/>
<polygon fill="#cb7b7a" stroke="#cb7b7a" points="5687.77,-2713.37 5690.36,-2702.72 5686.85,-2708.46 5685.93,-2703.54 5685.93,-2703.54 5685.93,-2703.54 5686.85,-2708.46 5681.51,-2704.37 5687.77,-2713.37 5687.77,-2713.37"/>
<path fill="none" stroke="#7abd4b" d="M5557.12,-2942.48C5588.99,-2880 5638.75,-2782.44 5674.28,-2712.75"/>
<polygon fill="#7abd4b" stroke="#7abd4b" points="5557.1,-2942.52 5548.55,-2949.38 5554.83,-2946.97 5552.56,-2951.43 5552.56,-2951.43 5552.56,-2951.43 5554.83,-2946.97 5556.57,-2953.47 5557.1,-2942.52 5557.1,-2942.52"/>
<polygon fill="#7abd4b" stroke="#7abd4b" points="5674.44,-2712.45 5682.99,-2705.59 5676.71,-2708 5678.98,-2703.54 5678.98,-2703.54 5678.98,-2703.54 5676.71,-2708 5674.97,-2701.5 5674.44,-2712.45 5674.44,-2712.45"/>
</g>
<!-- StatisticTypeSubType -->
<g id="node76" class="node"><title>StatisticTypeSubType</title>
<path fill="none" stroke="black" d="M5782,-2049.5C5782,-2049.5 6002,-2049.5 6002,-2049.5 6008,-2049.5 6014,-2055.5 6014,-2061.5 6014,-2061.5 6014,-2143.5 6014,-2143.5 6014,-2149.5 6008,-2155.5 6002,-2155.5 6002,-2155.5 5782,-2155.5 5782,-2155.5 5776,-2155.5 5770,-2149.5 5770,-2143.5 5770,-2143.5 5770,-2061.5 5770,-2061.5 5770,-2055.5 5776,-2049.5 5782,-2049.5"/>
<text text-anchor="middle" x="5892" y="-2140.3" font-family="Times,serif" font-size="14.00">StatisticTypeSubType</text>
<polyline fill="none" stroke="black" points="5770,-2132.5 6014,-2132.5 "/>
<text text-anchor="start" x="5778" y="-2117.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5778" y="-2102.3" font-family="Times,serif" font-size="14.00">statistic_type_id :integer</text>
<text text-anchor="start" x="5778" y="-2087.3" font-family="Times,serif" font-size="14.00">statistic_sub_type_id :integer</text>
<text text-anchor="start" x="5778" y="-2072.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5778" y="-2057.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M5345,-2049.5C5345,-2049.5 5565,-2049.5 5565,-2049.5 5571,-2049.5 5577,-2055.5 5577,-2061.5 5577,-2061.5 5577,-2143.5 5577,-2143.5 5577,-2149.5 5571,-2155.5 5565,-2155.5 5565,-2155.5 5345,-2155.5 5345,-2155.5 5339,-2155.5 5333,-2149.5 5333,-2143.5 5333,-2143.5 5333,-2061.5 5333,-2061.5 5333,-2055.5 5339,-2049.5 5345,-2049.5"/>
<text text-anchor="middle" x="5455" y="-2140.3" font-family="Times,serif" font-size="14.00">StatisticTypeSubType</text>
<polyline fill="none" stroke="black" points="5333,-2132.5 5577,-2132.5 "/>
<text text-anchor="start" x="5341" y="-2117.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5341" y="-2102.3" font-family="Times,serif" font-size="14.00">statistic_type_id :integer</text>
<text text-anchor="start" x="5341" y="-2087.3" font-family="Times,serif" font-size="14.00">statistic_sub_type_id :integer</text>
<text text-anchor="start" x="5341" y="-2072.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5341" y="-2057.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- StatisticSubType&#45;&gt;StatisticTypeSubType -->
<g id="edge17" class="edge"><title>StatisticSubType&#45;&gt;StatisticTypeSubType</title>
<path fill="none" stroke="#3184b3" d="M5777.61,-2944.08C5787.33,-2925.43 5796.86,-2904.38 5803,-2884 5880.87,-2625.66 5891.54,-2300.45 5892.36,-2166.04"/>
<ellipse fill="none" stroke="#3184b3" cx="5775.62" cy="-2947.85" rx="4.00002" ry="4.00002"/>
<polygon fill="#3184b3" stroke="#3184b3" points="5892.36,-2165.92 5896.91,-2155.94 5892.39,-2160.92 5892.41,-2155.92 5892.41,-2155.92 5892.41,-2155.92 5892.39,-2160.92 5887.91,-2155.9 5892.36,-2165.92 5892.36,-2165.92"/>
<path fill="none" stroke="#b144e0" d="M5521.23,-2943.03C5508.35,-2779.72 5472.94,-2330.9 5459.9,-2165.64"/>
<ellipse fill="none" stroke="#b144e0" cx="5521.56" cy="-2947.23" rx="4" ry="4"/>
<polygon fill="#b144e0" stroke="#b144e0" points="5459.9,-2165.61 5463.6,-2155.29 5459.51,-2160.63 5459.11,-2155.64 5459.11,-2155.64 5459.11,-2155.64 5459.51,-2160.63 5454.63,-2155.99 5459.9,-2165.61 5459.9,-2165.61"/>
</g>
<!-- Project -->
<g id="node16" class="node"><title>Project</title>
@ -506,15 +506,15 @@
</g>
<!-- Project&#45;&gt;ProjectImage -->
<g id="edge19" class="edge"><title>Project&#45;&gt;ProjectImage</title>
<path fill="none" stroke="#fbf2e7" d="M1754.79,-1997.22C1796.05,-1920.11 1851.25,-1816.95 1888.13,-1748.01"/>
<ellipse fill="none" stroke="#fbf2e7" cx="1752.85" cy="-2000.85" rx="4.00002" ry="4.00002"/>
<ellipse fill="#fbf2e7" stroke="#fbf2e7" cx="1890.2" cy="-1744.14" rx="4.00002" ry="4.00002"/>
<path fill="none" stroke="#554c5d" d="M1754.79,-1997.22C1796.05,-1920.11 1851.25,-1816.95 1888.13,-1748.01"/>
<ellipse fill="none" stroke="#554c5d" cx="1752.85" cy="-2000.85" rx="4.00002" ry="4.00002"/>
<ellipse fill="#554c5d" stroke="#554c5d" cx="1890.2" cy="-1744.14" rx="4.00002" ry="4.00002"/>
</g>
<!-- Project&#45;&gt;User -->
<g id="edge25" class="edge"><title>Project&#45;&gt;User</title>
<path fill="none" stroke="#6e7a89" d="M1783.93,-2208.64C1822.15,-2254.42 1868.58,-2308.01 1913,-2354 1955.02,-2397.5 2002.53,-2442.66 2047.07,-2483.43"/>
<polygon fill="#6e7a89" stroke="#6e7a89" points="1783.78,-2208.46 1780.84,-2197.9 1780.58,-2204.62 1777.39,-2200.78 1777.39,-2200.78 1777.39,-2200.78 1780.58,-2204.62 1773.93,-2203.66 1783.78,-2208.46 1783.78,-2208.46"/>
<polygon fill="#6e7a89" stroke="#6e7a89" points="2047.09,-2483.45 2051.44,-2493.52 2050.78,-2486.82 2054.48,-2490.2 2054.48,-2490.2 2054.48,-2490.2 2050.78,-2486.82 2057.51,-2486.87 2047.09,-2483.45 2047.09,-2483.45"/>
<path fill="none" stroke="#b0c6db" d="M1753.27,-2209.74C1780.04,-2256.7 1814.97,-2310.91 1854,-2354 1910.14,-2415.97 1981.83,-2473.9 2046.23,-2520.31"/>
<polygon fill="#b0c6db" stroke="#b0c6db" points="1753.11,-2209.46 1752.11,-2198.54 1750.65,-2205.11 1748.19,-2200.75 1748.19,-2200.75 1748.19,-2200.75 1750.65,-2205.11 1744.27,-2202.96 1753.11,-2209.46 1753.11,-2209.46"/>
<polygon fill="#b0c6db" stroke="#b0c6db" points="2046.32,-2520.37 2051.83,-2529.86 2050.38,-2523.29 2054.45,-2526.2 2054.45,-2526.2 2054.45,-2526.2 2050.38,-2523.29 2057.07,-2522.54 2046.32,-2520.37 2046.32,-2520.37"/>
</g>
<!-- Theme -->
<g id="node47" class="node"><title>Theme</title>
@ -526,9 +526,9 @@
</g>
<!-- Project&#45;&gt;Theme -->
<g id="edge23" class="edge"><title>Project&#45;&gt;Theme</title>
<path fill="none" stroke="#327a10" d="M1587.7,-1997.49C1488.06,-1904.38 1347.6,-1773.12 1280.15,-1710.08"/>
<polygon fill="#327a10" stroke="#327a10" points="1587.77,-1997.55 1592,-2007.67 1591.42,-2000.97 1595.07,-2004.38 1595.07,-2004.38 1595.07,-2004.38 1591.42,-2000.97 1598.15,-2001.09 1587.77,-1997.55 1587.77,-1997.55"/>
<polygon fill="#327a10" stroke="#327a10" points="1279.99,-1709.93 1275.75,-1699.82 1276.33,-1706.52 1272.68,-1703.11 1272.68,-1703.11 1272.68,-1703.11 1276.33,-1706.52 1269.61,-1706.39 1279.99,-1709.93 1279.99,-1709.93"/>
<path fill="none" stroke="#e4e243" d="M1587.7,-1997.49C1488.06,-1904.38 1347.6,-1773.12 1280.15,-1710.08"/>
<polygon fill="#e4e243" stroke="#e4e243" points="1587.77,-1997.55 1592,-2007.67 1591.42,-2000.97 1595.07,-2004.38 1595.07,-2004.38 1595.07,-2004.38 1591.42,-2000.97 1598.15,-2001.09 1587.77,-1997.55 1587.77,-1997.55"/>
<polygon fill="#e4e243" stroke="#e4e243" points="1279.99,-1709.93 1275.75,-1699.82 1276.33,-1706.52 1272.68,-1703.11 1272.68,-1703.11 1272.68,-1703.11 1276.33,-1706.52 1269.61,-1706.39 1279.99,-1709.93 1279.99,-1709.93"/>
</g>
<!-- ProjectCao -->
<g id="node48" class="node"><title>ProjectCao</title>
@ -545,9 +545,9 @@
</g>
<!-- Project&#45;&gt;ProjectCao -->
<g id="edge20" class="edge"><title>Project&#45;&gt;ProjectCao</title>
<path fill="none" stroke="#d4136b" d="M1643.21,-1997.22C1602.28,-1920.74 1547.65,-1818.62 1510.77,-1749.69"/>
<ellipse fill="none" stroke="#d4136b" cx="1645.15" cy="-2000.85" rx="4.00002" ry="4.00002"/>
<polygon fill="#d4136b" stroke="#d4136b" points="1510.63,-1749.43 1509.88,-1738.49 1508.27,-1745.02 1505.91,-1740.62 1505.91,-1740.62 1505.91,-1740.62 1508.27,-1745.02 1501.94,-1742.74 1510.63,-1749.43 1510.63,-1749.43"/>
<path fill="none" stroke="#4b18e9" d="M1643.21,-1997.22C1602.28,-1920.74 1547.65,-1818.62 1510.77,-1749.69"/>
<ellipse fill="none" stroke="#4b18e9" cx="1645.15" cy="-2000.85" rx="4.00002" ry="4.00002"/>
<polygon fill="#4b18e9" stroke="#4b18e9" points="1510.63,-1749.43 1509.88,-1738.49 1508.27,-1745.02 1505.91,-1740.62 1505.91,-1740.62 1505.91,-1740.62 1508.27,-1745.02 1501.94,-1742.74 1510.63,-1749.43 1510.63,-1749.43"/>
</g>
<!-- ProjectStep -->
<g id="node57" class="node"><title>ProjectStep</title>
@ -564,9 +564,9 @@
</g>
<!-- Project&#45;&gt;ProjectStep -->
<g id="edge26" class="edge"><title>Project&#45;&gt;ProjectStep</title>
<path fill="none" stroke="#8d72bf" d="M1564.87,-2017.94C1437.81,-1938.78 1248.95,-1821.12 1128.16,-1745.87"/>
<ellipse fill="none" stroke="#8d72bf" cx="1568.4" cy="-2020.13" rx="4.00002" ry="4.00002"/>
<polygon fill="#8d72bf" stroke="#8d72bf" points="1128.07,-1745.81 1121.97,-1736.71 1123.83,-1743.17 1119.59,-1740.53 1119.59,-1740.53 1119.59,-1740.53 1123.83,-1743.17 1117.21,-1744.35 1128.07,-1745.81 1128.07,-1745.81"/>
<path fill="none" stroke="#482831" d="M1564.87,-2017.94C1437.81,-1938.78 1248.95,-1821.12 1128.16,-1745.87"/>
<ellipse fill="none" stroke="#482831" cx="1568.4" cy="-2020.13" rx="4.00002" ry="4.00002"/>
<polygon fill="#482831" stroke="#482831" points="1128.07,-1745.81 1121.97,-1736.71 1123.83,-1743.17 1119.59,-1740.53 1119.59,-1740.53 1119.59,-1740.53 1123.83,-1743.17 1117.21,-1744.35 1128.07,-1745.81 1128.07,-1745.81"/>
</g>
<!-- ProjectUser -->
<g id="node74" class="node"><title>ProjectUser</title>
@ -583,12 +583,12 @@
</g>
<!-- Project&#45;&gt;ProjectUser -->
<g id="edge24" class="edge"><title>Project&#45;&gt;ProjectUser</title>
<path fill="none" stroke="#96dd12" d="M1564.72,-2016.06C1485.89,-1969.81 1382.64,-1915.79 1284,-1884 1229.74,-1866.51 1211.74,-1881.92 1157,-1866 1030.85,-1829.31 1003.53,-1801.05 881.613,-1741.3"/>
<ellipse fill="none" stroke="#96dd12" cx="1568.35" cy="-2018.19" rx="4.00002" ry="4.00002"/>
<polygon fill="#96dd12" stroke="#96dd12" points="881.27,-1741.13 874.25,-1732.71 876.775,-1738.94 872.279,-1736.75 872.279,-1736.75 872.279,-1736.75 876.775,-1738.94 870.309,-1740.8 881.27,-1741.13 881.27,-1741.13"/>
<path fill="none" stroke="#d0c029" d="M1564.72,-2016.06C1485.89,-1969.81 1382.64,-1915.79 1284,-1884 1229.74,-1866.51 1211.74,-1881.92 1157,-1866 1030.85,-1829.31 1003.53,-1801.05 881.613,-1741.3"/>
<ellipse fill="none" stroke="#d0c029" cx="1568.35" cy="-2018.19" rx="4.00002" ry="4.00002"/>
<polygon fill="#d0c029" stroke="#d0c029" points="881.27,-1741.13 874.25,-1732.71 876.775,-1738.94 872.279,-1736.75 872.279,-1736.75 872.279,-1736.75 876.775,-1738.94 870.309,-1740.8 881.27,-1741.13 881.27,-1741.13"/>
</g>
<!-- Machine -->
<g id="node82" class="node"><title>Machine</title>
<g id="node83" class="node"><title>Machine</title>
<path fill="none" stroke="black" d="M3117,-1604.5C3117,-1604.5 3337,-1604.5 3337,-1604.5 3343,-1604.5 3349,-1610.5 3349,-1616.5 3349,-1616.5 3349,-1728.5 3349,-1728.5 3349,-1734.5 3343,-1740.5 3337,-1740.5 3337,-1740.5 3117,-1740.5 3117,-1740.5 3111,-1740.5 3105,-1734.5 3105,-1728.5 3105,-1728.5 3105,-1616.5 3105,-1616.5 3105,-1610.5 3111,-1604.5 3117,-1604.5"/>
<text text-anchor="middle" x="3227" y="-1725.3" font-family="Times,serif" font-size="14.00">Machine</text>
<polyline fill="none" stroke="black" points="3105,-1717.5 3349,-1717.5 "/>
@ -602,12 +602,12 @@
</g>
<!-- Project&#45;&gt;Machine -->
<g id="edge21" class="edge"><title>Project&#45;&gt;Machine</title>
<path fill="none" stroke="#0e50f8" d="M1835.52,-2043.83C1953.39,-1995.79 2129.1,-1928.29 2287,-1884 2606.58,-1794.35 2698.73,-1824.39 3020,-1741 3044.47,-1734.65 3070.28,-1727.01 3095.06,-1719.19"/>
<polygon fill="#0e50f8" stroke="#0e50f8" points="1835.33,-2043.91 1824.37,-2043.53 1830.7,-2045.8 1826.07,-2047.69 1826.07,-2047.69 1826.07,-2047.69 1830.7,-2045.8 1827.78,-2051.86 1835.33,-2043.91 1835.33,-2043.91"/>
<polygon fill="#0e50f8" stroke="#0e50f8" points="3095.34,-1719.1 3106.23,-1720.36 3100.1,-1717.59 3104.87,-1716.07 3104.87,-1716.07 3104.87,-1716.07 3100.1,-1717.59 3103.5,-1711.78 3095.34,-1719.1 3095.34,-1719.1"/>
<path fill="none" stroke="#fe0ba1" d="M1835.52,-2043.83C1953.39,-1995.79 2129.1,-1928.29 2287,-1884 2606.58,-1794.35 2698.73,-1824.39 3020,-1741 3044.47,-1734.65 3070.28,-1727.01 3095.06,-1719.19"/>
<polygon fill="#fe0ba1" stroke="#fe0ba1" points="1835.33,-2043.91 1824.37,-2043.53 1830.7,-2045.8 1826.07,-2047.69 1826.07,-2047.69 1826.07,-2047.69 1830.7,-2045.8 1827.78,-2051.86 1835.33,-2043.91 1835.33,-2043.91"/>
<polygon fill="#fe0ba1" stroke="#fe0ba1" points="3095.34,-1719.1 3106.23,-1720.36 3100.1,-1717.59 3104.87,-1716.07 3104.87,-1716.07 3104.87,-1716.07 3100.1,-1717.59 3103.5,-1711.78 3095.34,-1719.1 3095.34,-1719.1"/>
</g>
<!-- Component -->
<g id="node84" class="node"><title>Component</title>
<g id="node85" class="node"><title>Component</title>
<path fill="none" stroke="black" d="M1622,-1642C1622,-1642 1776,-1642 1776,-1642 1782,-1642 1788,-1648 1788,-1654 1788,-1654 1788,-1691 1788,-1691 1788,-1697 1782,-1703 1776,-1703 1776,-1703 1622,-1703 1622,-1703 1616,-1703 1610,-1697 1610,-1691 1610,-1691 1610,-1654 1610,-1654 1610,-1648 1616,-1642 1622,-1642"/>
<text text-anchor="middle" x="1699" y="-1687.8" font-family="Times,serif" font-size="14.00">Component</text>
<polyline fill="none" stroke="black" points="1610,-1680 1788,-1680 "/>
@ -616,55 +616,55 @@
</g>
<!-- Project&#45;&gt;Component -->
<g id="edge22" class="edge"><title>Project&#45;&gt;Component</title>
<path fill="none" stroke="#23a212" d="M1699,-1994.28C1699,-1903.05 1699,-1776.98 1699,-1713.48"/>
<polygon fill="#23a212" stroke="#23a212" points="1699,-1994.38 1694.5,-2004.38 1699,-1999.38 1699,-2004.38 1699,-2004.38 1699,-2004.38 1699,-1999.38 1703.5,-2004.38 1699,-1994.38 1699,-1994.38"/>
<polygon fill="#23a212" stroke="#23a212" points="1699,-1713.11 1703.5,-1703.11 1699,-1708.11 1699,-1703.11 1699,-1703.11 1699,-1703.11 1699,-1708.11 1694.5,-1703.11 1699,-1713.11 1699,-1713.11"/>
<path fill="none" stroke="#48ab8e" d="M1699,-1994.28C1699,-1903.05 1699,-1776.98 1699,-1713.48"/>
<polygon fill="#48ab8e" stroke="#48ab8e" points="1699,-1994.38 1694.5,-2004.38 1699,-1999.38 1699,-2004.38 1699,-2004.38 1699,-2004.38 1699,-1999.38 1703.5,-2004.38 1699,-1994.38 1699,-1994.38"/>
<polygon fill="#48ab8e" stroke="#48ab8e" points="1699,-1713.11 1703.5,-1703.11 1699,-1708.11 1699,-1703.11 1699,-1703.11 1699,-1703.11 1699,-1708.11 1694.5,-1703.11 1699,-1713.11 1699,-1713.11"/>
</g>
<!-- CustomAsset -->
<g id="node17" class="node"><title>CustomAsset</title>
<path fill="none" stroke="black" d="M5918,-2959C5918,-2959 6138,-2959 6138,-2959 6144,-2959 6150,-2965 6150,-2971 6150,-2971 6150,-3038 6150,-3038 6150,-3044 6144,-3050 6138,-3050 6138,-3050 5918,-3050 5918,-3050 5912,-3050 5906,-3044 5906,-3038 5906,-3038 5906,-2971 5906,-2971 5906,-2965 5912,-2959 5918,-2959"/>
<text text-anchor="middle" x="6028" y="-3034.8" font-family="Times,serif" font-size="14.00">CustomAsset</text>
<polyline fill="none" stroke="black" points="5906,-3027 6150,-3027 "/>
<text text-anchor="start" x="5914" y="-3011.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5914" y="-2996.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="5914" y="-2981.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5914" y="-2966.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M5869,-2959C5869,-2959 6089,-2959 6089,-2959 6095,-2959 6101,-2965 6101,-2971 6101,-2971 6101,-3038 6101,-3038 6101,-3044 6095,-3050 6089,-3050 6089,-3050 5869,-3050 5869,-3050 5863,-3050 5857,-3044 5857,-3038 5857,-3038 5857,-2971 5857,-2971 5857,-2965 5863,-2959 5869,-2959"/>
<text text-anchor="middle" x="5979" y="-3034.8" font-family="Times,serif" font-size="14.00">CustomAsset</text>
<polyline fill="none" stroke="black" points="5857,-3027 6101,-3027 "/>
<text text-anchor="start" x="5865" y="-3011.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5865" y="-2996.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="5865" y="-2981.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5865" y="-2966.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- CustomAssetFile -->
<g id="node85" class="node"><title>CustomAssetFile</title>
<path fill="none" stroke="black" d="M5918,-2560C5918,-2560 6138,-2560 6138,-2560 6144,-2560 6150,-2566 6150,-2572 6150,-2572 6150,-2684 6150,-2684 6150,-2690 6144,-2696 6138,-2696 6138,-2696 5918,-2696 5918,-2696 5912,-2696 5906,-2690 5906,-2684 5906,-2684 5906,-2572 5906,-2572 5906,-2566 5912,-2560 5918,-2560"/>
<text text-anchor="middle" x="6028" y="-2680.8" font-family="Times,serif" font-size="14.00">CustomAssetFile</text>
<polyline fill="none" stroke="black" points="5906,-2673 6150,-2673 "/>
<text text-anchor="start" x="5914" y="-2657.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5914" y="-2642.8" font-family="Times,serif" font-size="14.00">viewable_id :integer</text>
<text text-anchor="start" x="5914" y="-2627.8" font-family="Times,serif" font-size="14.00">viewable_type :character varying(255)</text>
<text text-anchor="start" x="5914" y="-2612.8" font-family="Times,serif" font-size="14.00">attachment :character varying(255)</text>
<text text-anchor="start" x="5914" y="-2597.8" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="5914" y="-2582.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5914" y="-2567.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<g id="node86" class="node"><title>CustomAssetFile</title>
<path fill="none" stroke="black" d="M5869,-2560C5869,-2560 6089,-2560 6089,-2560 6095,-2560 6101,-2566 6101,-2572 6101,-2572 6101,-2684 6101,-2684 6101,-2690 6095,-2696 6089,-2696 6089,-2696 5869,-2696 5869,-2696 5863,-2696 5857,-2690 5857,-2684 5857,-2684 5857,-2572 5857,-2572 5857,-2566 5863,-2560 5869,-2560"/>
<text text-anchor="middle" x="5979" y="-2680.8" font-family="Times,serif" font-size="14.00">CustomAssetFile</text>
<polyline fill="none" stroke="black" points="5857,-2673 6101,-2673 "/>
<text text-anchor="start" x="5865" y="-2657.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5865" y="-2642.8" font-family="Times,serif" font-size="14.00">viewable_id :integer</text>
<text text-anchor="start" x="5865" y="-2627.8" font-family="Times,serif" font-size="14.00">viewable_type :character varying(255)</text>
<text text-anchor="start" x="5865" y="-2612.8" font-family="Times,serif" font-size="14.00">attachment :character varying(255)</text>
<text text-anchor="start" x="5865" y="-2597.8" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="5865" y="-2582.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5865" y="-2567.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- CustomAsset&#45;&gt;CustomAssetFile -->
<g id="edge27" class="edge"><title>CustomAsset&#45;&gt;CustomAssetFile</title>
<path fill="none" stroke="#9550e5" d="M6028,-2950.41C6028,-2886.16 6028,-2777.55 6028,-2704.58"/>
<ellipse fill="none" stroke="#9550e5" cx="6028" cy="-2954.7" rx="4" ry="4"/>
<ellipse fill="#9550e5" stroke="#9550e5" cx="6028" cy="-2700.31" rx="4" ry="4"/>
<path fill="none" stroke="#51b285" d="M5979,-2950.41C5979,-2886.16 5979,-2777.55 5979,-2704.58"/>
<ellipse fill="none" stroke="#51b285" cx="5979" cy="-2954.7" rx="4" ry="4"/>
<ellipse fill="#51b285" stroke="#51b285" cx="5979" cy="-2700.31" rx="4" ry="4"/>
</g>
<!-- AgeRange -->
<g id="node18" class="node"><title>AgeRange</title>
<path fill="none" stroke="black" d="M4346,-2575C4346,-2575 4566,-2575 4566,-2575 4572,-2575 4578,-2581 4578,-2587 4578,-2587 4578,-2669 4578,-2669 4578,-2675 4572,-2681 4566,-2681 4566,-2681 4346,-2681 4346,-2681 4340,-2681 4334,-2675 4334,-2669 4334,-2669 4334,-2587 4334,-2587 4334,-2581 4340,-2575 4346,-2575"/>
<text text-anchor="middle" x="4456" y="-2665.8" font-family="Times,serif" font-size="14.00">AgeRange</text>
<polyline fill="none" stroke="black" points="4334,-2658 4578,-2658 "/>
<text text-anchor="start" x="4342" y="-2642.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4342" y="-2627.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="4342" y="-2612.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4342" y="-2597.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="4342" y="-2582.8" font-family="Times,serif" font-size="14.00">slug :character varying</text>
<path fill="none" stroke="black" d="M4276,-2575C4276,-2575 4496,-2575 4496,-2575 4502,-2575 4508,-2581 4508,-2587 4508,-2587 4508,-2669 4508,-2669 4508,-2675 4502,-2681 4496,-2681 4496,-2681 4276,-2681 4276,-2681 4270,-2681 4264,-2675 4264,-2669 4264,-2669 4264,-2587 4264,-2587 4264,-2581 4270,-2575 4276,-2575"/>
<text text-anchor="middle" x="4386" y="-2665.8" font-family="Times,serif" font-size="14.00">AgeRange</text>
<polyline fill="none" stroke="black" points="4264,-2658 4508,-2658 "/>
<text text-anchor="start" x="4272" y="-2642.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4272" y="-2627.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="4272" y="-2612.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4272" y="-2597.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="4272" y="-2582.8" font-family="Times,serif" font-size="14.00">slug :character varying</text>
</g>
<!-- AgeRange&#45;&gt;Event -->
<g id="edge28" class="edge"><title>AgeRange&#45;&gt;Event</title>
<path fill="none" stroke="#c5e680" d="M4466.1,-2566.93C4480.36,-2482.12 4506.66,-2325.65 4524.72,-2218.17"/>
<ellipse fill="none" stroke="#c5e680" cx="4465.42" cy="-2570.95" rx="4.00001" ry="4.00001"/>
<polygon fill="#c5e680" stroke="#c5e680" points="4524.73,-2218.11 4530.83,-2209 4525.56,-2213.18 4526.39,-2208.25 4526.39,-2208.25 4526.39,-2208.25 4525.56,-2213.18 4521.95,-2207.5 4524.73,-2218.11 4524.73,-2218.11"/>
<path fill="none" stroke="#59f930" d="M4403.94,-2567.19C4429.38,-2482.36 4476.43,-2325.46 4508.7,-2217.86"/>
<ellipse fill="none" stroke="#59f930" cx="4402.78" cy="-2571.06" rx="4.00001" ry="4.00001"/>
<polygon fill="#59f930" stroke="#59f930" points="4508.71,-2217.83 4515.9,-2209.54 4510.15,-2213.04 4511.58,-2208.25 4511.58,-2208.25 4511.58,-2208.25 4510.15,-2213.04 4507.27,-2206.96 4508.71,-2217.83 4508.71,-2217.83"/>
</g>
<!-- Wallet -->
<g id="node19" class="node"><title>Wallet</title>
@ -679,116 +679,116 @@
</g>
<!-- WalletTransaction -->
<g id="node62" class="node"><title>WalletTransaction</title>
<path fill="none" stroke="black" d="M556,-1419.5C556,-1419.5 776,-1419.5 776,-1419.5 782,-1419.5 788,-1425.5 788,-1431.5 788,-1431.5 788,-1573.5 788,-1573.5 788,-1579.5 782,-1585.5 776,-1585.5 776,-1585.5 556,-1585.5 556,-1585.5 550,-1585.5 544,-1579.5 544,-1573.5 544,-1573.5 544,-1431.5 544,-1431.5 544,-1425.5 550,-1419.5 556,-1419.5"/>
<text text-anchor="middle" x="666" y="-1570.3" font-family="Times,serif" font-size="14.00">WalletTransaction</text>
<polyline fill="none" stroke="black" points="544,-1562.5 788,-1562.5 "/>
<text text-anchor="start" x="552" y="-1547.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="552" y="-1532.3" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="552" y="-1517.3" font-family="Times,serif" font-size="14.00">wallet_id :integer</text>
<text text-anchor="start" x="552" y="-1502.3" font-family="Times,serif" font-size="14.00">transactable_id :integer</text>
<text text-anchor="start" x="552" y="-1487.3" font-family="Times,serif" font-size="14.00">transactable_type :character varying</text>
<text text-anchor="start" x="552" y="-1472.3" font-family="Times,serif" font-size="14.00">transaction_type :character varying</text>
<text text-anchor="start" x="552" y="-1457.3" font-family="Times,serif" font-size="14.00">amount :integer</text>
<text text-anchor="start" x="552" y="-1442.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="552" y="-1427.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M555,-1419.5C555,-1419.5 775,-1419.5 775,-1419.5 781,-1419.5 787,-1425.5 787,-1431.5 787,-1431.5 787,-1573.5 787,-1573.5 787,-1579.5 781,-1585.5 775,-1585.5 775,-1585.5 555,-1585.5 555,-1585.5 549,-1585.5 543,-1579.5 543,-1573.5 543,-1573.5 543,-1431.5 543,-1431.5 543,-1425.5 549,-1419.5 555,-1419.5"/>
<text text-anchor="middle" x="665" y="-1570.3" font-family="Times,serif" font-size="14.00">WalletTransaction</text>
<polyline fill="none" stroke="black" points="543,-1562.5 787,-1562.5 "/>
<text text-anchor="start" x="551" y="-1547.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="551" y="-1532.3" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="551" y="-1517.3" font-family="Times,serif" font-size="14.00">wallet_id :integer</text>
<text text-anchor="start" x="551" y="-1502.3" font-family="Times,serif" font-size="14.00">transactable_id :integer</text>
<text text-anchor="start" x="551" y="-1487.3" font-family="Times,serif" font-size="14.00">transactable_type :character varying</text>
<text text-anchor="start" x="551" y="-1472.3" font-family="Times,serif" font-size="14.00">transaction_type :character varying</text>
<text text-anchor="start" x="551" y="-1457.3" font-family="Times,serif" font-size="14.00">amount :integer</text>
<text text-anchor="start" x="551" y="-1442.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="551" y="-1427.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Wallet&#45;&gt;WalletTransaction -->
<g id="edge29" class="edge"><title>Wallet&#45;&gt;WalletTransaction</title>
<path fill="none" stroke="#ca8c47" d="M622.329,-1751.57C621.037,-1748.06 619.91,-1744.52 619,-1741 603.78,-1682.04 605.788,-1663.44 619,-1604 619.637,-1601.14 620.364,-1598.26 621.169,-1595.37"/>
<ellipse fill="none" stroke="#ca8c47" cx="623.904" cy="-1755.48" rx="4.00001" ry="4.00001"/>
<polygon fill="#ca8c47" stroke="#ca8c47" points="621.242,-1595.14 628.487,-1586.9 622.714,-1590.36 624.186,-1585.58 624.186,-1585.58 624.186,-1585.58 622.714,-1590.36 619.886,-1584.25 621.242,-1595.14 621.242,-1595.14"/>
<path fill="none" stroke="#3e0178" d="M622.329,-1751.57C621.037,-1748.06 619.91,-1744.52 619,-1741 603.78,-1682.04 606.032,-1663.49 619,-1604 619.623,-1601.14 620.334,-1598.27 621.121,-1595.4"/>
<ellipse fill="none" stroke="#3e0178" cx="623.904" cy="-1755.48" rx="4.00001" ry="4.00001"/>
<polygon fill="#3e0178" stroke="#3e0178" points="621.183,-1595.19 628.381,-1586.92 622.628,-1590.41 624.073,-1585.62 624.073,-1585.62 624.073,-1585.62 622.628,-1590.41 619.765,-1584.32 621.183,-1595.19 621.183,-1595.19"/>
</g>
<!-- Stats::Event -->
<g id="node20" class="node"><title>Stats::Event</title>
<polygon fill="none" stroke="black" points="6168,-2981.5 6168,-3027.5 6250,-3027.5 6250,-2981.5 6168,-2981.5"/>
<text text-anchor="middle" x="6209" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Event</text>
<polyline fill="none" stroke="black" points="6168,-3004.5 6250,-3004.5 "/>
<text text-anchor="middle" x="6209" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<polygon fill="none" stroke="black" points="6119,-2981.5 6119,-3027.5 6201,-3027.5 6201,-2981.5 6119,-2981.5"/>
<text text-anchor="middle" x="6160" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Event</text>
<polyline fill="none" stroke="black" points="6119,-3004.5 6201,-3004.5 "/>
<text text-anchor="middle" x="6160" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- Stats::Project -->
<g id="node21" class="node"><title>Stats::Project</title>
<polygon fill="none" stroke="black" points="6268.5,-2981.5 6268.5,-3027.5 6357.5,-3027.5 6357.5,-2981.5 6268.5,-2981.5"/>
<text text-anchor="middle" x="6313" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Project</text>
<polyline fill="none" stroke="black" points="6268.5,-3004.5 6357.5,-3004.5 "/>
<text text-anchor="middle" x="6313" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<polygon fill="none" stroke="black" points="6219.5,-2981.5 6219.5,-3027.5 6308.5,-3027.5 6308.5,-2981.5 6219.5,-2981.5"/>
<text text-anchor="middle" x="6264" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Project</text>
<polyline fill="none" stroke="black" points="6219.5,-3004.5 6308.5,-3004.5 "/>
<text text-anchor="middle" x="6264" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- Stats::User -->
<g id="node22" class="node"><title>Stats::User</title>
<polygon fill="none" stroke="black" points="6376,-2981.5 6376,-3027.5 6452,-3027.5 6452,-2981.5 6376,-2981.5"/>
<text text-anchor="middle" x="6414" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::User</text>
<polyline fill="none" stroke="black" points="6376,-3004.5 6452,-3004.5 "/>
<text text-anchor="middle" x="6414" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<polygon fill="none" stroke="black" points="6327,-2981.5 6327,-3027.5 6403,-3027.5 6403,-2981.5 6327,-2981.5"/>
<text text-anchor="middle" x="6365" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::User</text>
<polyline fill="none" stroke="black" points="6327,-3004.5 6403,-3004.5 "/>
<text text-anchor="middle" x="6365" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- Stats::Subscription -->
<g id="node23" class="node"><title>Stats::Subscription</title>
<polygon fill="none" stroke="black" points="6470.5,-2981.5 6470.5,-3027.5 6589.5,-3027.5 6589.5,-2981.5 6470.5,-2981.5"/>
<text text-anchor="middle" x="6530" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Subscription</text>
<polyline fill="none" stroke="black" points="6470.5,-3004.5 6589.5,-3004.5 "/>
<text text-anchor="middle" x="6530" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<polygon fill="none" stroke="black" points="6421.5,-2981.5 6421.5,-3027.5 6540.5,-3027.5 6540.5,-2981.5 6421.5,-2981.5"/>
<text text-anchor="middle" x="6481" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Subscription</text>
<polyline fill="none" stroke="black" points="6421.5,-3004.5 6540.5,-3004.5 "/>
<text text-anchor="middle" x="6481" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- Stats::Training -->
<g id="node24" class="node"><title>Stats::Training</title>
<polygon fill="none" stroke="black" points="6607.5,-2981.5 6607.5,-3027.5 6704.5,-3027.5 6704.5,-2981.5 6607.5,-2981.5"/>
<text text-anchor="middle" x="6656" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Training</text>
<polyline fill="none" stroke="black" points="6607.5,-3004.5 6704.5,-3004.5 "/>
<text text-anchor="middle" x="6656" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<polygon fill="none" stroke="black" points="6558.5,-2981.5 6558.5,-3027.5 6655.5,-3027.5 6655.5,-2981.5 6558.5,-2981.5"/>
<text text-anchor="middle" x="6607" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Training</text>
<polyline fill="none" stroke="black" points="6558.5,-3004.5 6655.5,-3004.5 "/>
<text text-anchor="middle" x="6607" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- Stats::Account -->
<g id="node25" class="node"><title>Stats::Account</title>
<polygon fill="none" stroke="black" points="6723,-2981.5 6723,-3027.5 6819,-3027.5 6819,-2981.5 6723,-2981.5"/>
<text text-anchor="middle" x="6771" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Account</text>
<polyline fill="none" stroke="black" points="6723,-3004.5 6819,-3004.5 "/>
<text text-anchor="middle" x="6771" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<polygon fill="none" stroke="black" points="6674,-2981.5 6674,-3027.5 6770,-3027.5 6770,-2981.5 6674,-2981.5"/>
<text text-anchor="middle" x="6722" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Account</text>
<polyline fill="none" stroke="black" points="6674,-3004.5 6770,-3004.5 "/>
<text text-anchor="middle" x="6722" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- Stats::Machine -->
<g id="node26" class="node"><title>Stats::Machine</title>
<polygon fill="none" stroke="black" points="6837,-2981.5 6837,-3027.5 6935,-3027.5 6935,-2981.5 6837,-2981.5"/>
<text text-anchor="middle" x="6886" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Machine</text>
<polyline fill="none" stroke="black" points="6837,-3004.5 6935,-3004.5 "/>
<text text-anchor="middle" x="6886" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<polygon fill="none" stroke="black" points="6788,-2981.5 6788,-3027.5 6886,-3027.5 6886,-2981.5 6788,-2981.5"/>
<text text-anchor="middle" x="6837" y="-3012.3" font-family="Times,serif" font-size="14.00">Stats::Machine</text>
<polyline fill="none" stroke="black" points="6788,-3004.5 6886,-3004.5 "/>
<text text-anchor="middle" x="6837" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- PriceCategory&#45;&gt;EventPriceCategory -->
<g id="edge30" class="edge"><title>PriceCategory&#45;&gt;EventPriceCategory</title>
<path fill="none" stroke="#5608b4" d="M5046.19,-1613.73C4971.06,-1541.14 4842.39,-1416.84 4763.11,-1340.27"/>
<ellipse fill="none" stroke="#5608b4" cx="5049.26" cy="-1616.69" rx="4.00002" ry="4.00002"/>
<polygon fill="#5608b4" stroke="#5608b4" points="4762.79,-1339.96 4758.73,-1329.77 4759.2,-1336.48 4755.6,-1333.01 4755.6,-1333.01 4755.6,-1333.01 4759.2,-1336.48 4752.47,-1336.24 4762.79,-1339.96 4762.79,-1339.96"/>
<path fill="none" stroke="#7a110c" d="M5045.19,-1613.73C4970.06,-1541.14 4841.39,-1416.84 4762.11,-1340.27"/>
<ellipse fill="none" stroke="#7a110c" cx="5048.26" cy="-1616.69" rx="4.00002" ry="4.00002"/>
<polygon fill="#7a110c" stroke="#7a110c" points="4761.79,-1339.96 4757.73,-1329.77 4758.2,-1336.48 4754.6,-1333.01 4754.6,-1333.01 4754.6,-1333.01 4758.2,-1336.48 4751.47,-1336.24 4761.79,-1339.96 4761.79,-1339.96"/>
</g>
<!-- Invoice -->
<g id="node28" class="node"><title>Invoice</title>
<path fill="none" stroke="black" d="M2641,-204.5C2641,-204.5 2861,-204.5 2861,-204.5 2867,-204.5 2873,-210.5 2873,-216.5 2873,-216.5 2873,-493.5 2873,-493.5 2873,-499.5 2867,-505.5 2861,-505.5 2861,-505.5 2641,-505.5 2641,-505.5 2635,-505.5 2629,-499.5 2629,-493.5 2629,-493.5 2629,-216.5 2629,-216.5 2629,-210.5 2635,-204.5 2641,-204.5"/>
<text text-anchor="middle" x="2751" y="-490.3" font-family="Times,serif" font-size="14.00">Invoice</text>
<polyline fill="none" stroke="black" points="2629,-482.5 2873,-482.5 "/>
<text text-anchor="start" x="2637" y="-467.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="2637" y="-452.3" font-family="Times,serif" font-size="14.00">invoiced_id :integer</text>
<text text-anchor="start" x="2637" y="-437.3" font-family="Times,serif" font-size="14.00">invoiced_type :character varying(255)</text>
<text text-anchor="start" x="2637" y="-422.3" font-family="Times,serif" font-size="14.00">stp_invoice_id :character varying(255)</text>
<text text-anchor="start" x="2637" y="-407.3" font-family="Times,serif" font-size="14.00">total :integer</text>
<text text-anchor="start" x="2637" y="-392.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="2637" y="-377.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="2637" y="-362.3" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="2637" y="-347.3" font-family="Times,serif" font-size="14.00">reference :character varying(255)</text>
<text text-anchor="start" x="2637" y="-332.3" font-family="Times,serif" font-size="14.00">avoir_mode :character varying(255)</text>
<text text-anchor="start" x="2637" y="-317.3" font-family="Times,serif" font-size="14.00">avoir_date :timestamp without time zone</text>
<text text-anchor="start" x="2637" y="-302.3" font-family="Times,serif" font-size="14.00">invoice_id :integer</text>
<text text-anchor="start" x="2637" y="-287.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="2637" y="-272.3" font-family="Times,serif" font-size="14.00">subscription_to_expire :boolean</text>
<text text-anchor="start" x="2637" y="-257.3" font-family="Times,serif" font-size="14.00">description :text</text>
<text text-anchor="start" x="2637" y="-242.3" font-family="Times,serif" font-size="14.00">wallet_amount :integer</text>
<text text-anchor="start" x="2637" y="-227.3" font-family="Times,serif" font-size="14.00">wallet_transaction_id :integer</text>
<text text-anchor="start" x="2637" y="-212.3" font-family="Times,serif" font-size="14.00">coupon_id :integer</text>
<path fill="none" stroke="black" d="M2548,-204.5C2548,-204.5 2768,-204.5 2768,-204.5 2774,-204.5 2780,-210.5 2780,-216.5 2780,-216.5 2780,-493.5 2780,-493.5 2780,-499.5 2774,-505.5 2768,-505.5 2768,-505.5 2548,-505.5 2548,-505.5 2542,-505.5 2536,-499.5 2536,-493.5 2536,-493.5 2536,-216.5 2536,-216.5 2536,-210.5 2542,-204.5 2548,-204.5"/>
<text text-anchor="middle" x="2658" y="-490.3" font-family="Times,serif" font-size="14.00">Invoice</text>
<polyline fill="none" stroke="black" points="2536,-482.5 2780,-482.5 "/>
<text text-anchor="start" x="2544" y="-467.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="2544" y="-452.3" font-family="Times,serif" font-size="14.00">invoiced_id :integer</text>
<text text-anchor="start" x="2544" y="-437.3" font-family="Times,serif" font-size="14.00">invoiced_type :character varying(255)</text>
<text text-anchor="start" x="2544" y="-422.3" font-family="Times,serif" font-size="14.00">stp_invoice_id :character varying(255)</text>
<text text-anchor="start" x="2544" y="-407.3" font-family="Times,serif" font-size="14.00">total :integer</text>
<text text-anchor="start" x="2544" y="-392.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="2544" y="-377.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="2544" y="-362.3" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="2544" y="-347.3" font-family="Times,serif" font-size="14.00">reference :character varying(255)</text>
<text text-anchor="start" x="2544" y="-332.3" font-family="Times,serif" font-size="14.00">avoir_mode :character varying(255)</text>
<text text-anchor="start" x="2544" y="-317.3" font-family="Times,serif" font-size="14.00">avoir_date :timestamp without time zone</text>
<text text-anchor="start" x="2544" y="-302.3" font-family="Times,serif" font-size="14.00">invoice_id :integer</text>
<text text-anchor="start" x="2544" y="-287.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="2544" y="-272.3" font-family="Times,serif" font-size="14.00">subscription_to_expire :boolean</text>
<text text-anchor="start" x="2544" y="-257.3" font-family="Times,serif" font-size="14.00">description :text</text>
<text text-anchor="start" x="2544" y="-242.3" font-family="Times,serif" font-size="14.00">wallet_amount :integer</text>
<text text-anchor="start" x="2544" y="-227.3" font-family="Times,serif" font-size="14.00">wallet_transaction_id :integer</text>
<text text-anchor="start" x="2544" y="-212.3" font-family="Times,serif" font-size="14.00">coupon_id :integer</text>
</g>
<!-- Invoice&#45;&gt;InvoiceItem -->
<g id="edge31" class="edge"><title>Invoice&#45;&gt;InvoiceItem</title>
<path fill="none" stroke="#bc7474" d="M2880.27,-284.737C2952.28,-246.156 3041.95,-198.112 3115.41,-158.756"/>
<ellipse fill="none" stroke="#bc7474" cx="2876.61" cy="-286.7" rx="4.00002" ry="4.00002"/>
<polygon fill="#bc7474" stroke="#bc7474" points="3115.47,-158.723 3126.41,-157.967 3119.88,-156.362 3124.28,-154.001 3124.28,-154.001 3124.28,-154.001 3119.88,-156.362 3122.16,-150.034 3115.47,-158.723 3115.47,-158.723"/>
<path fill="none" stroke="#b1dda5" d="M2787.25,-283.911C2857.57,-245.782 2944.58,-198.599 3016.31,-159.703"/>
<ellipse fill="none" stroke="#b1dda5" cx="2783.73" cy="-285.821" rx="4.00002" ry="4.00002"/>
<polygon fill="#b1dda5" stroke="#b1dda5" points="3016.64,-159.526 3027.58,-158.715 3021.04,-157.142 3025.43,-154.759 3025.43,-154.759 3025.43,-154.759 3021.04,-157.142 3023.29,-150.803 3016.64,-159.526 3016.64,-159.526"/>
</g>
<!-- Invoice&#45;&gt;Invoice -->
<g id="edge32" class="edge"><title>Invoice&#45;&gt;Invoice</title>
<path fill="none" stroke="#2ec6ca" d="M2880.31,-375.636C2887.03,-370.546 2891,-363.667 2891,-355 2891,-346.333 2887.03,-339.454 2880.31,-334.364"/>
<ellipse fill="none" stroke="#2ec6ca" cx="2876.82" cy="-377.739" rx="4.00002" ry="4.00002"/>
<ellipse fill="#2ec6ca" stroke="#2ec6ca" cx="2876.82" cy="-332.261" rx="4.00002" ry="4.00002"/>
<text text-anchor="middle" x="2905" y="-351.3" font-family="Times,serif" font-size="14.00">avoir</text>
<path fill="none" stroke="#6f21fa" d="M2787.31,-375.636C2794.03,-370.546 2798,-363.667 2798,-355 2798,-346.333 2794.03,-339.454 2787.31,-334.364"/>
<ellipse fill="none" stroke="#6f21fa" cx="2783.82" cy="-377.739" rx="4.00002" ry="4.00002"/>
<ellipse fill="#6f21fa" stroke="#6f21fa" cx="2783.82" cy="-332.261" rx="4.00002" ry="4.00002"/>
<text text-anchor="middle" x="2812" y="-351.3" font-family="Times,serif" font-size="14.00">avoir</text>
</g>
<!-- PlanFile -->
<g id="node29" class="node"><title>PlanFile</title>
@ -805,75 +805,95 @@
</g>
<!-- OfferDay -->
<g id="node30" class="node"><title>OfferDay</title>
<path fill="none" stroke="black" d="M2262,-647.5C2262,-647.5 2482,-647.5 2482,-647.5 2488,-647.5 2494,-653.5 2494,-659.5 2494,-659.5 2494,-756.5 2494,-756.5 2494,-762.5 2488,-768.5 2482,-768.5 2482,-768.5 2262,-768.5 2262,-768.5 2256,-768.5 2250,-762.5 2250,-756.5 2250,-756.5 2250,-659.5 2250,-659.5 2250,-653.5 2256,-647.5 2262,-647.5"/>
<text text-anchor="middle" x="2372" y="-753.3" font-family="Times,serif" font-size="14.00">OfferDay</text>
<polyline fill="none" stroke="black" points="2250,-745.5 2494,-745.5 "/>
<text text-anchor="start" x="2258" y="-730.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="2258" y="-715.3" font-family="Times,serif" font-size="14.00">subscription_id :integer</text>
<text text-anchor="start" x="2258" y="-700.3" font-family="Times,serif" font-size="14.00">start_at :timestamp without time zone</text>
<text text-anchor="start" x="2258" y="-685.3" font-family="Times,serif" font-size="14.00">end_at :timestamp without time zone</text>
<text text-anchor="start" x="2258" y="-670.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="2258" y="-655.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M2241,-647.5C2241,-647.5 2461,-647.5 2461,-647.5 2467,-647.5 2473,-653.5 2473,-659.5 2473,-659.5 2473,-756.5 2473,-756.5 2473,-762.5 2467,-768.5 2461,-768.5 2461,-768.5 2241,-768.5 2241,-768.5 2235,-768.5 2229,-762.5 2229,-756.5 2229,-756.5 2229,-659.5 2229,-659.5 2229,-653.5 2235,-647.5 2241,-647.5"/>
<text text-anchor="middle" x="2351" y="-753.3" font-family="Times,serif" font-size="14.00">OfferDay</text>
<polyline fill="none" stroke="black" points="2229,-745.5 2473,-745.5 "/>
<text text-anchor="start" x="2237" y="-730.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="2237" y="-715.3" font-family="Times,serif" font-size="14.00">subscription_id :integer</text>
<text text-anchor="start" x="2237" y="-700.3" font-family="Times,serif" font-size="14.00">start_at :timestamp without time zone</text>
<text text-anchor="start" x="2237" y="-685.3" font-family="Times,serif" font-size="14.00">end_at :timestamp without time zone</text>
<text text-anchor="start" x="2237" y="-670.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="2237" y="-655.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- OfferDay&#45;&gt;Invoice -->
<g id="edge33" class="edge"><title>OfferDay&#45;&gt;Invoice</title>
<path fill="none" stroke="#93614e" d="M2425.57,-640.785C2448.44,-613.84 2476.04,-582.99 2503,-557 2539.51,-521.811 2581.6,-486.101 2620.62,-454.737"/>
<ellipse fill="none" stroke="#93614e" cx="2422.74" cy="-644.129" rx="4.00002" ry="4.00002"/>
<polygon fill="#93614e" stroke="#93614e" points="2621.08,-454.361 2631.7,-451.625 2624.99,-451.237 2628.89,-448.112 2628.89,-448.112 2628.89,-448.112 2624.99,-451.237 2626.08,-444.599 2621.08,-454.361 2621.08,-454.361"/>
<path fill="none" stroke="#65d87d" d="M2408.37,-641.271C2431.27,-615.049 2457.87,-584.589 2482,-557 2497.23,-539.586 2513.2,-521.328 2529.06,-503.216"/>
<ellipse fill="none" stroke="#65d87d" cx="2405.57" cy="-644.479" rx="4.00002" ry="4.00002"/>
<polygon fill="#65d87d" stroke="#65d87d" points="2529.25,-502.99 2539.23,-498.429 2532.55,-499.228 2535.84,-495.465 2535.84,-495.465 2535.84,-495.465 2532.55,-499.228 2532.45,-492.501 2529.25,-502.99 2529.25,-502.99"/>
</g>
<!-- StatisticIndex -->
<g id="node59" class="node"><title>StatisticIndex</title>
<path fill="none" stroke="black" d="M5520,-2034.5C5520,-2034.5 5740,-2034.5 5740,-2034.5 5746,-2034.5 5752,-2040.5 5752,-2046.5 5752,-2046.5 5752,-2158.5 5752,-2158.5 5752,-2164.5 5746,-2170.5 5740,-2170.5 5740,-2170.5 5520,-2170.5 5520,-2170.5 5514,-2170.5 5508,-2164.5 5508,-2158.5 5508,-2158.5 5508,-2046.5 5508,-2046.5 5508,-2040.5 5514,-2034.5 5520,-2034.5"/>
<text text-anchor="middle" x="5630" y="-2155.3" font-family="Times,serif" font-size="14.00">StatisticIndex</text>
<polyline fill="none" stroke="black" points="5508,-2147.5 5752,-2147.5 "/>
<text text-anchor="start" x="5516" y="-2132.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5516" y="-2117.3" font-family="Times,serif" font-size="14.00">es_type_key :character varying(255)</text>
<text text-anchor="start" x="5516" y="-2102.3" font-family="Times,serif" font-size="14.00">label :character varying(255)</text>
<text text-anchor="start" x="5516" y="-2087.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5516" y="-2072.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="5516" y="-2057.3" font-family="Times,serif" font-size="14.00">table :boolean</text>
<text text-anchor="start" x="5516" y="-2042.3" font-family="Times,serif" font-size="14.00">ca :boolean</text>
<path fill="none" stroke="black" d="M5607,-2034.5C5607,-2034.5 5827,-2034.5 5827,-2034.5 5833,-2034.5 5839,-2040.5 5839,-2046.5 5839,-2046.5 5839,-2158.5 5839,-2158.5 5839,-2164.5 5833,-2170.5 5827,-2170.5 5827,-2170.5 5607,-2170.5 5607,-2170.5 5601,-2170.5 5595,-2164.5 5595,-2158.5 5595,-2158.5 5595,-2046.5 5595,-2046.5 5595,-2040.5 5601,-2034.5 5607,-2034.5"/>
<text text-anchor="middle" x="5717" y="-2155.3" font-family="Times,serif" font-size="14.00">StatisticIndex</text>
<polyline fill="none" stroke="black" points="5595,-2147.5 5839,-2147.5 "/>
<text text-anchor="start" x="5603" y="-2132.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5603" y="-2117.3" font-family="Times,serif" font-size="14.00">es_type_key :character varying(255)</text>
<text text-anchor="start" x="5603" y="-2102.3" font-family="Times,serif" font-size="14.00">label :character varying(255)</text>
<text text-anchor="start" x="5603" y="-2087.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5603" y="-2072.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="5603" y="-2057.3" font-family="Times,serif" font-size="14.00">table :boolean</text>
<text text-anchor="start" x="5603" y="-2042.3" font-family="Times,serif" font-size="14.00">ca :boolean</text>
</g>
<!-- StatisticType&#45;&gt;StatisticIndex -->
<g id="edge34" class="edge"><title>StatisticType&#45;&gt;StatisticIndex</title>
<path fill="none" stroke="#01c0f4" d="M5660.25,-2544.03C5649.91,-2443.46 5636.49,-2275.43 5631.12,-2178.56"/>
<ellipse fill="none" stroke="#01c0f4" cx="5660.7" cy="-2548.29" rx="4" ry="4"/>
<ellipse fill="#01c0f4" stroke="#01c0f4" cx="5630.9" cy="-2174.55" rx="4" ry="4"/>
<path fill="none" stroke="#b19a7c" d="M5711.91,-2544.03C5709.64,-2443.46 5709.7,-2275.43 5712.1,-2178.56"/>
<ellipse fill="none" stroke="#b19a7c" cx="5712.01" cy="-2548.27" rx="4" ry="4"/>
<ellipse fill="#b19a7c" stroke="#b19a7c" cx="5712.2" cy="-2174.56" rx="4" ry="4"/>
</g>
<!-- StatisticType&#45;&gt;StatisticTypeSubType -->
<g id="edge35" class="edge"><title>StatisticType&#45;&gt;StatisticTypeSubType</title>
<path fill="none" stroke="#f814be" d="M5706.64,-2544.57C5750.89,-2439.29 5826.46,-2259.45 5866.06,-2165.23"/>
<ellipse fill="none" stroke="#f814be" cx="5704.95" cy="-2548.59" rx="4.00001" ry="4.00001"/>
<polygon fill="#f814be" stroke="#f814be" points="5866.13,-2165.05 5874.16,-2157.57 5868.07,-2160.44 5870.01,-2155.83 5870.01,-2155.83 5870.01,-2155.83 5868.07,-2160.44 5865.86,-2154.09 5866.13,-2165.05 5866.13,-2165.05"/>
<path fill="none" stroke="#c0d68a" d="M5675.91,-2544.9C5623.19,-2439.56 5532.92,-2259.2 5485.76,-2164.95"/>
<ellipse fill="none" stroke="#c0d68a" cx="5677.81" cy="-2548.7" rx="4.00002" ry="4.00002"/>
<polygon fill="#c0d68a" stroke="#c0d68a" points="5485.67,-2164.77 5485.21,-2153.82 5483.43,-2160.3 5481.19,-2155.83 5481.19,-2155.83 5481.19,-2155.83 5483.43,-2160.3 5477.17,-2157.85 5485.67,-2164.77 5485.67,-2164.77"/>
</g>
<!-- StatisticCustomAggregation -->
<g id="node77" class="node"><title>StatisticCustomAggregation</title>
<path fill="none" stroke="black" d="M5869,-2027C5869,-2027 6089,-2027 6089,-2027 6095,-2027 6101,-2033 6101,-2039 6101,-2039 6101,-2166 6101,-2166 6101,-2172 6095,-2178 6089,-2178 6089,-2178 5869,-2178 5869,-2178 5863,-2178 5857,-2172 5857,-2166 5857,-2166 5857,-2039 5857,-2039 5857,-2033 5863,-2027 5869,-2027"/>
<text text-anchor="middle" x="5979" y="-2162.8" font-family="Times,serif" font-size="14.00">StatisticCustomAggregation</text>
<polyline fill="none" stroke="black" points="5857,-2155 6101,-2155 "/>
<text text-anchor="start" x="5865" y="-2139.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5865" y="-2124.8" font-family="Times,serif" font-size="14.00">query :text</text>
<text text-anchor="start" x="5865" y="-2109.8" font-family="Times,serif" font-size="14.00">statistic_type_id :integer</text>
<text text-anchor="start" x="5865" y="-2094.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5865" y="-2079.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="5865" y="-2064.8" font-family="Times,serif" font-size="14.00">field :character varying</text>
<text text-anchor="start" x="5865" y="-2049.8" font-family="Times,serif" font-size="14.00">es_index :character varying</text>
<text text-anchor="start" x="5865" y="-2034.8" font-family="Times,serif" font-size="14.00">es_type :character varying</text>
</g>
<!-- StatisticType&#45;&gt;StatisticCustomAggregation -->
<g id="edge36" class="edge"><title>StatisticType&#45;&gt;StatisticCustomAggregation</title>
<path fill="none" stroke="#f4efaa" d="M5758.12,-2544.85C5806.97,-2447.23 5888.03,-2285.26 5937.19,-2187.04"/>
<ellipse fill="none" stroke="#f4efaa" cx="5756.19" cy="-2548.7" rx="4.00002" ry="4.00002"/>
<polygon fill="#f4efaa" stroke="#f4efaa" points="5937.22,-2186.97 5945.72,-2180.04 5939.46,-2182.5 5941.7,-2178.03 5941.7,-2178.03 5941.7,-2178.03 5939.46,-2182.5 5937.68,-2176.01 5937.22,-2186.97 5937.22,-2186.97"/>
</g>
<!-- Address -->
<g id="node33" class="node"><title>Address</title>
<path fill="none" stroke="black" d="M50,-1174.5C50,-1174.5 270,-1174.5 270,-1174.5 276,-1174.5 282,-1180.5 282,-1186.5 282,-1186.5 282,-1358.5 282,-1358.5 282,-1364.5 276,-1370.5 270,-1370.5 270,-1370.5 50,-1370.5 50,-1370.5 44,-1370.5 38,-1364.5 38,-1358.5 38,-1358.5 38,-1186.5 38,-1186.5 38,-1180.5 44,-1174.5 50,-1174.5"/>
<text text-anchor="middle" x="160" y="-1355.3" font-family="Times,serif" font-size="14.00">Address</text>
<polyline fill="none" stroke="black" points="38,-1347.5 282,-1347.5 "/>
<text text-anchor="start" x="46" y="-1332.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="46" y="-1317.3" font-family="Times,serif" font-size="14.00">address :character varying(255)</text>
<text text-anchor="start" x="46" y="-1302.3" font-family="Times,serif" font-size="14.00">street_number :character varying(255)</text>
<text text-anchor="start" x="46" y="-1287.3" font-family="Times,serif" font-size="14.00">route :character varying(255)</text>
<text text-anchor="start" x="46" y="-1272.3" font-family="Times,serif" font-size="14.00">locality :character varying(255)</text>
<text text-anchor="start" x="46" y="-1257.3" font-family="Times,serif" font-size="14.00">country :character varying(255)</text>
<text text-anchor="start" x="46" y="-1242.3" font-family="Times,serif" font-size="14.00">postal_code :character varying(255)</text>
<text text-anchor="start" x="46" y="-1227.3" font-family="Times,serif" font-size="14.00">placeable_id :integer</text>
<text text-anchor="start" x="46" y="-1212.3" font-family="Times,serif" font-size="14.00">placeable_type :character varying(255)</text>
<text text-anchor="start" x="46" y="-1197.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="46" y="-1182.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M49,-1174.5C49,-1174.5 269,-1174.5 269,-1174.5 275,-1174.5 281,-1180.5 281,-1186.5 281,-1186.5 281,-1358.5 281,-1358.5 281,-1364.5 275,-1370.5 269,-1370.5 269,-1370.5 49,-1370.5 49,-1370.5 43,-1370.5 37,-1364.5 37,-1358.5 37,-1358.5 37,-1186.5 37,-1186.5 37,-1180.5 43,-1174.5 49,-1174.5"/>
<text text-anchor="middle" x="159" y="-1355.3" font-family="Times,serif" font-size="14.00">Address</text>
<polyline fill="none" stroke="black" points="37,-1347.5 281,-1347.5 "/>
<text text-anchor="start" x="45" y="-1332.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="45" y="-1317.3" font-family="Times,serif" font-size="14.00">address :character varying(255)</text>
<text text-anchor="start" x="45" y="-1302.3" font-family="Times,serif" font-size="14.00">street_number :character varying(255)</text>
<text text-anchor="start" x="45" y="-1287.3" font-family="Times,serif" font-size="14.00">route :character varying(255)</text>
<text text-anchor="start" x="45" y="-1272.3" font-family="Times,serif" font-size="14.00">locality :character varying(255)</text>
<text text-anchor="start" x="45" y="-1257.3" font-family="Times,serif" font-size="14.00">country :character varying(255)</text>
<text text-anchor="start" x="45" y="-1242.3" font-family="Times,serif" font-size="14.00">postal_code :character varying(255)</text>
<text text-anchor="start" x="45" y="-1227.3" font-family="Times,serif" font-size="14.00">placeable_id :integer</text>
<text text-anchor="start" x="45" y="-1212.3" font-family="Times,serif" font-size="14.00">placeable_type :character varying(255)</text>
<text text-anchor="start" x="45" y="-1197.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="45" y="-1182.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Plan&#45;&gt;Price -->
<g id="edge42" class="edge"><title>Plan&#45;&gt;Price</title>
<path fill="none" stroke="#14f111" d="M3056.51,-1163.58C3069.35,-1156.06 3082.61,-1149.35 3096,-1144 3161.22,-1117.93 3189.78,-1156.6 3253,-1126 3277.12,-1114.33 3299.38,-1096.31 3318.41,-1077.36"/>
<ellipse fill="none" stroke="#14f111" cx="3052.84" cy="-1165.78" rx="4.00002" ry="4.00002"/>
<polygon fill="#14f111" stroke="#14f111" points="3318.55,-1077.21 3328.76,-1073.21 3322.05,-1073.64 3325.54,-1070.06 3325.54,-1070.06 3325.54,-1070.06 3322.05,-1073.64 3322.33,-1066.92 3318.55,-1077.21 3318.55,-1077.21"/>
<g id="edge43" class="edge"><title>Plan&#45;&gt;Price</title>
<path fill="none" stroke="#b54a1a" d="M3056.35,-1164.43C3069.27,-1156.69 3082.58,-1149.7 3096,-1144 3143.22,-1123.96 3162.78,-1146.04 3210,-1126 3239.06,-1113.66 3267.66,-1095.39 3292.98,-1076.4"/>
<ellipse fill="none" stroke="#b54a1a" cx="3052.62" cy="-1166.72" rx="4.00002" ry="4.00002"/>
<polygon fill="#b54a1a" stroke="#b54a1a" points="3293.13,-1076.29 3303.81,-1073.8 3297.1,-1073.25 3301.08,-1070.22 3301.08,-1070.22 3301.08,-1070.22 3297.1,-1073.25 3298.35,-1066.64 3293.13,-1076.29 3293.13,-1076.29"/>
</g>
<!-- Plan&#45;&gt;PlanFile -->
<g id="edge41" class="edge"><title>Plan&#45;&gt;PlanFile</title>
<path fill="none" stroke="#639173" d="M3055.01,-1186.61C3076.29,-1162.54 3085.81,-1136.06 3066,-1111 3044.47,-1083.77 3021.46,-1107.67 2990,-1093 2974.87,-1085.95 2959.78,-1076.99 2945.5,-1067.36"/>
<ellipse fill="none" stroke="#639173" cx="3052.09" cy="-1189.75" rx="4.00002" ry="4.00002"/>
<ellipse fill="#639173" stroke="#639173" cx="2941.85" cy="-1064.86" rx="4.00002" ry="4.00002"/>
<g id="edge42" class="edge"><title>Plan&#45;&gt;PlanFile</title>
<path fill="none" stroke="#a80c34" d="M3055.01,-1186.61C3076.29,-1162.54 3085.81,-1136.06 3066,-1111 3044.47,-1083.77 3021.46,-1107.67 2990,-1093 2974.87,-1085.95 2959.78,-1076.99 2945.5,-1067.36"/>
<ellipse fill="none" stroke="#a80c34" cx="3052.09" cy="-1189.75" rx="4.00002" ry="4.00002"/>
<ellipse fill="#a80c34" stroke="#a80c34" cx="2941.85" cy="-1064.86" rx="4.00002" ry="4.00002"/>
</g>
<!-- Credit -->
<g id="node44" class="node"><title>Credit</title>
@ -889,44 +909,44 @@
<text text-anchor="start" x="2469" y="-934.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Plan&#45;&gt;Credit -->
<g id="edge36" class="edge"><title>Plan&#45;&gt;Credit</title>
<path fill="none" stroke="#811e7c" d="M2904.37,-1137.18C2898.67,-1127.36 2891.64,-1118.42 2883,-1111 2856.69,-1088.41 2760.53,-1105.01 2728,-1093 2710.83,-1086.66 2693.7,-1077.89 2677.55,-1068.2"/>
<ellipse fill="none" stroke="#811e7c" cx="2906.4" cy="-1140.95" rx="4.00002" ry="4.00002"/>
<polygon fill="#811e7c" stroke="#811e7c" points="2677.19,-1067.97 2671.04,-1058.89 2672.94,-1065.35 2668.68,-1062.72 2668.68,-1062.72 2668.68,-1062.72 2672.94,-1065.35 2666.32,-1066.55 2677.19,-1067.97 2677.19,-1067.97"/>
</g>
<!-- Plan&#45;&gt;Credit -->
<g id="edge37" class="edge"><title>Plan&#45;&gt;Credit</title>
<path fill="none" stroke="#aba004" d="M2922.24,-1136.87C2917.72,-1127.27 2911.77,-1118.46 2904,-1111 2875.64,-1083.77 2764.97,-1106.37 2728,-1093 2710.67,-1086.73 2693.4,-1077.95 2677.14,-1068.2"/>
<ellipse fill="none" stroke="#aba004" cx="2923.86" cy="-1140.67" rx="4.00002" ry="4.00002"/>
<polygon fill="#aba004" stroke="#aba004" points="2676.72,-1067.94 2670.57,-1058.86 2672.46,-1065.32 2668.21,-1062.69 2668.21,-1062.69 2668.21,-1062.69 2672.46,-1065.32 2665.85,-1066.52 2676.72,-1067.94 2676.72,-1067.94"/>
<text text-anchor="middle" x="2957.5" y="-1114.8" font-family="Times,serif" font-size="14.00">training_credits</text>
<path fill="none" stroke="#d69cbd" d="M2904.37,-1137.18C2898.67,-1127.36 2891.64,-1118.42 2883,-1111 2856.69,-1088.41 2760.53,-1105.01 2728,-1093 2710.83,-1086.66 2693.7,-1077.89 2677.55,-1068.2"/>
<ellipse fill="none" stroke="#d69cbd" cx="2906.4" cy="-1140.95" rx="4.00002" ry="4.00002"/>
<polygon fill="#d69cbd" stroke="#d69cbd" points="2677.19,-1067.97 2671.04,-1058.89 2672.94,-1065.35 2668.68,-1062.72 2668.68,-1062.72 2668.68,-1062.72 2672.94,-1065.35 2666.32,-1066.55 2677.19,-1067.97 2677.19,-1067.97"/>
</g>
<!-- Plan&#45;&gt;Credit -->
<g id="edge38" class="edge"><title>Plan&#45;&gt;Credit</title>
<path fill="none" stroke="#603aa5" d="M2798.67,-1147.18C2797.45,-1146.11 2796.22,-1145.05 2795,-1144 2776.75,-1128.27 2771.51,-1125.14 2752,-1111 2732.65,-1096.98 2711.81,-1082.36 2691.59,-1068.42"/>
<ellipse fill="none" stroke="#603aa5" cx="2801.83" cy="-1149.95" rx="4.00002" ry="4.00002"/>
<polygon fill="#603aa5" stroke="#603aa5" points="2691.51,-1068.36 2685.83,-1058.99 2687.39,-1065.53 2683.28,-1062.69 2683.28,-1062.69 2683.28,-1062.69 2687.39,-1065.53 2680.72,-1066.4 2691.51,-1068.36 2691.51,-1068.36"/>
<path fill="none" stroke="#594dfe" d="M2922.24,-1136.87C2917.72,-1127.27 2911.77,-1118.46 2904,-1111 2875.64,-1083.77 2764.97,-1106.37 2728,-1093 2710.67,-1086.73 2693.4,-1077.95 2677.14,-1068.2"/>
<ellipse fill="none" stroke="#594dfe" cx="2923.86" cy="-1140.67" rx="4.00002" ry="4.00002"/>
<polygon fill="#594dfe" stroke="#594dfe" points="2676.72,-1067.94 2670.57,-1058.86 2672.46,-1065.32 2668.21,-1062.69 2668.21,-1062.69 2668.21,-1062.69 2672.46,-1065.32 2665.85,-1066.52 2676.72,-1067.94 2676.72,-1067.94"/>
<text text-anchor="middle" x="2957.5" y="-1114.8" font-family="Times,serif" font-size="14.00">training_credits</text>
</g>
<!-- Plan&#45;&gt;Credit -->
<g id="edge39" class="edge"><title>Plan&#45;&gt;Credit</title>
<path fill="none" stroke="#0eb22d" d="M2798.67,-1147.18C2797.45,-1146.11 2796.22,-1145.05 2795,-1144 2776.75,-1128.27 2771.51,-1125.14 2752,-1111 2732.65,-1096.98 2711.81,-1082.36 2691.59,-1068.42"/>
<ellipse fill="none" stroke="#0eb22d" cx="2801.83" cy="-1149.95" rx="4.00002" ry="4.00002"/>
<polygon fill="#0eb22d" stroke="#0eb22d" points="2691.51,-1068.36 2685.83,-1058.99 2687.39,-1065.53 2683.28,-1062.69 2683.28,-1062.69 2683.28,-1062.69 2687.39,-1065.53 2680.72,-1066.4 2691.51,-1068.36 2691.51,-1068.36"/>
<text text-anchor="middle" x="2818" y="-1114.8" font-family="Times,serif" font-size="14.00">machine_credits</text>
</g>
<!-- Subscription -->
<g id="node55" class="node"><title>Subscription</title>
<path fill="none" stroke="black" d="M2143,-919C2143,-919 2373,-919 2373,-919 2379,-919 2385,-925 2385,-931 2385,-931 2385,-1058 2385,-1058 2385,-1064 2379,-1070 2373,-1070 2373,-1070 2143,-1070 2143,-1070 2137,-1070 2131,-1064 2131,-1058 2131,-1058 2131,-931 2131,-931 2131,-925 2137,-919 2143,-919"/>
<text text-anchor="middle" x="2258" y="-1054.8" font-family="Times,serif" font-size="14.00">Subscription</text>
<polyline fill="none" stroke="black" points="2131,-1047 2385,-1047 "/>
<text text-anchor="start" x="2139" y="-1031.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="2139" y="-1016.8" font-family="Times,serif" font-size="14.00">plan_id :integer</text>
<text text-anchor="start" x="2139" y="-1001.8" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="2139" y="-986.8" font-family="Times,serif" font-size="14.00">stp_subscription_id :character varying(255)</text>
<text text-anchor="start" x="2139" y="-971.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="2139" y="-956.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="2139" y="-941.8" font-family="Times,serif" font-size="14.00">expired_at :timestamp without time zone</text>
<text text-anchor="start" x="2139" y="-926.8" font-family="Times,serif" font-size="14.00">canceled_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M2122,-919C2122,-919 2352,-919 2352,-919 2358,-919 2364,-925 2364,-931 2364,-931 2364,-1058 2364,-1058 2364,-1064 2358,-1070 2352,-1070 2352,-1070 2122,-1070 2122,-1070 2116,-1070 2110,-1064 2110,-1058 2110,-1058 2110,-931 2110,-931 2110,-925 2116,-919 2122,-919"/>
<text text-anchor="middle" x="2237" y="-1054.8" font-family="Times,serif" font-size="14.00">Subscription</text>
<polyline fill="none" stroke="black" points="2110,-1047 2364,-1047 "/>
<text text-anchor="start" x="2118" y="-1031.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="2118" y="-1016.8" font-family="Times,serif" font-size="14.00">plan_id :integer</text>
<text text-anchor="start" x="2118" y="-1001.8" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="2118" y="-986.8" font-family="Times,serif" font-size="14.00">stp_subscription_id :character varying(255)</text>
<text text-anchor="start" x="2118" y="-971.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="2118" y="-956.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="2118" y="-941.8" font-family="Times,serif" font-size="14.00">expired_at :timestamp without time zone</text>
<text text-anchor="start" x="2118" y="-926.8" font-family="Times,serif" font-size="14.00">canceled_at :timestamp without time zone</text>
</g>
<!-- Plan&#45;&gt;Subscription -->
<g id="edge39" class="edge"><title>Plan&#45;&gt;Subscription</title>
<path fill="none" stroke="#945a4f" d="M2797.5,-1145.15C2796.67,-1144.76 2795.84,-1144.38 2795,-1144 2747.64,-1122.7 2613.05,-1135.52 2562,-1126 2511.82,-1116.65 2499.43,-1111.87 2452,-1093 2433.03,-1085.45 2413.4,-1076.73 2394.24,-1067.68"/>
<ellipse fill="none" stroke="#945a4f" cx="2801.34" cy="-1147.07" rx="4.00002" ry="4.00002"/>
<polygon fill="#945a4f" stroke="#945a4f" points="2394.2,-1067.66 2387.11,-1059.29 2389.69,-1065.51 2385.17,-1063.35 2385.17,-1063.35 2385.17,-1063.35 2389.69,-1065.51 2383.23,-1067.41 2394.2,-1067.66 2394.2,-1067.66"/>
<g id="edge40" class="edge"><title>Plan&#45;&gt;Subscription</title>
<path fill="none" stroke="#a1c622" d="M2797.5,-1145.15C2796.67,-1144.76 2795.84,-1144.38 2795,-1144 2747.64,-1122.7 2613.05,-1135.52 2562,-1126 2511.82,-1116.65 2499.79,-1110.91 2452,-1093 2426.28,-1083.36 2399.29,-1072.08 2373.46,-1060.69"/>
<ellipse fill="none" stroke="#a1c622" cx="2801.34" cy="-1147.07" rx="4.00002" ry="4.00002"/>
<polygon fill="#a1c622" stroke="#a1c622" points="2373.14,-1060.55 2365.83,-1052.38 2368.57,-1058.52 2364,-1056.49 2364,-1056.49 2364,-1056.49 2368.57,-1058.52 2362.17,-1060.6 2373.14,-1060.55 2373.14,-1060.55"/>
</g>
<!-- PlanImage -->
<g id="node75" class="node"><title>PlanImage</title>
@ -942,10 +962,10 @@
<text text-anchor="start" x="3007" y="-934.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Plan&#45;&gt;PlanImage -->
<g id="edge40" class="edge"><title>Plan&#45;&gt;PlanImage</title>
<path fill="none" stroke="#aa066b" d="M3054.56,-1165.58C3065.49,-1153.02 3075.57,-1139.75 3084,-1126 3094.27,-1109.24 3101.78,-1089.52 3107.24,-1070.57"/>
<ellipse fill="none" stroke="#aa066b" cx="3051.78" cy="-1168.7" rx="4.00002" ry="4.00002"/>
<ellipse fill="#aa066b" stroke="#aa066b" cx="3108.32" cy="-1066.65" rx="4.00001" ry="4.00001"/>
<g id="edge41" class="edge"><title>Plan&#45;&gt;PlanImage</title>
<path fill="none" stroke="#86401c" d="M3054.56,-1165.58C3065.49,-1153.02 3075.57,-1139.75 3084,-1126 3094.27,-1109.24 3101.78,-1089.52 3107.24,-1070.57"/>
<ellipse fill="none" stroke="#86401c" cx="3051.78" cy="-1168.7" rx="4.00002" ry="4.00002"/>
<ellipse fill="#86401c" stroke="#86401c" cx="3108.32" cy="-1066.65" rx="4.00001" ry="4.00001"/>
</g>
<!-- MachineFile -->
<g id="node35" class="node"><title>MachineFile</title>
@ -972,37 +992,38 @@
<text text-anchor="start" x="74" y="-1627.3" font-family="Times,serif" font-size="14.00">profile_id :integer</text>
</g>
<!-- Organization&#45;&gt;Address -->
<g id="edge43" class="edge"><title>Organization&#45;&gt;Address</title>
<path fill="none" stroke="#1a0728" d="M183.751,-1611.11C179.419,-1549.53 172.613,-1452.79 167.395,-1378.61"/>
<ellipse fill="none" stroke="#1a0728" cx="184.059" cy="-1615.48" rx="4" ry="4"/>
<ellipse fill="#1a0728" stroke="#1a0728" cx="167.112" cy="-1374.59" rx="4" ry="4"/>
<g id="edge44" class="edge"><title>Organization&#45;&gt;Address</title>
<path fill="none" stroke="#341e8c" d="M183.6,-1611.11C179.113,-1549.53 172.064,-1452.79 166.659,-1378.61"/>
<ellipse fill="none" stroke="#341e8c" cx="183.918" cy="-1615.48" rx="4" ry="4"/>
<ellipse fill="#341e8c" stroke="#341e8c" cx="166.366" cy="-1374.59" rx="4" ry="4"/>
</g>
<!-- StatisticGraph -->
<g id="node37" class="node"><title>StatisticGraph</title>
<path fill="none" stroke="black" d="M5258,-1612C5258,-1612 5478,-1612 5478,-1612 5484,-1612 5490,-1618 5490,-1624 5490,-1624 5490,-1721 5490,-1721 5490,-1727 5484,-1733 5478,-1733 5478,-1733 5258,-1733 5258,-1733 5252,-1733 5246,-1727 5246,-1721 5246,-1721 5246,-1624 5246,-1624 5246,-1618 5252,-1612 5258,-1612"/>
<text text-anchor="middle" x="5368" y="-1717.8" font-family="Times,serif" font-size="14.00">StatisticGraph</text>
<polyline fill="none" stroke="black" points="5246,-1710 5490,-1710 "/>
<text text-anchor="start" x="5254" y="-1694.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5254" y="-1679.8" font-family="Times,serif" font-size="14.00">statistic_index_id :integer</text>
<text text-anchor="start" x="5254" y="-1664.8" font-family="Times,serif" font-size="14.00">chart_type :character varying(255)</text>
<text text-anchor="start" x="5254" y="-1649.8" font-family="Times,serif" font-size="14.00">limit :integer</text>
<text text-anchor="start" x="5254" y="-1634.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5254" y="-1619.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M5345,-1612C5345,-1612 5565,-1612 5565,-1612 5571,-1612 5577,-1618 5577,-1624 5577,-1624 5577,-1721 5577,-1721 5577,-1727 5571,-1733 5565,-1733 5565,-1733 5345,-1733 5345,-1733 5339,-1733 5333,-1727 5333,-1721 5333,-1721 5333,-1624 5333,-1624 5333,-1618 5339,-1612 5345,-1612"/>
<text text-anchor="middle" x="5455" y="-1717.8" font-family="Times,serif" font-size="14.00">StatisticGraph</text>
<polyline fill="none" stroke="black" points="5333,-1710 5577,-1710 "/>
<text text-anchor="start" x="5341" y="-1694.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5341" y="-1679.8" font-family="Times,serif" font-size="14.00">statistic_index_id :integer</text>
<text text-anchor="start" x="5341" y="-1664.8" font-family="Times,serif" font-size="14.00">chart_type :character varying(255)</text>
<text text-anchor="start" x="5341" y="-1649.8" font-family="Times,serif" font-size="14.00">limit :integer</text>
<text text-anchor="start" x="5341" y="-1634.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5341" y="-1619.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- OAuth2Mapping -->
<g id="node39" class="node"><title>OAuth2Mapping</title>
<path fill="none" stroke="black" d="M6965,-2545C6965,-2545 7185,-2545 7185,-2545 7191,-2545 7197,-2551 7197,-2557 7197,-2557 7197,-2699 7197,-2699 7197,-2705 7191,-2711 7185,-2711 7185,-2711 6965,-2711 6965,-2711 6959,-2711 6953,-2705 6953,-2699 6953,-2699 6953,-2557 6953,-2557 6953,-2551 6959,-2545 6965,-2545"/>
<text text-anchor="middle" x="7075" y="-2695.8" font-family="Times,serif" font-size="14.00">OAuth2Mapping</text>
<polyline fill="none" stroke="black" points="6953,-2688 7197,-2688 "/>
<text text-anchor="start" x="6961" y="-2672.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="6961" y="-2657.8" font-family="Times,serif" font-size="14.00">o_auth2_provider_id :integer</text>
<text text-anchor="start" x="6961" y="-2642.8" font-family="Times,serif" font-size="14.00">local_field :character varying</text>
<text text-anchor="start" x="6961" y="-2627.8" font-family="Times,serif" font-size="14.00">api_field :character varying</text>
<text text-anchor="start" x="6961" y="-2612.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="6961" y="-2597.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="6961" y="-2582.8" font-family="Times,serif" font-size="14.00">local_model :character varying</text>
<text text-anchor="start" x="6961" y="-2567.8" font-family="Times,serif" font-size="14.00">api_endpoint :character varying</text>
<text text-anchor="start" x="6961" y="-2552.8" font-family="Times,serif" font-size="14.00">api_data_type :character varying</text>
<path fill="none" stroke="black" d="M6916,-2537.5C6916,-2537.5 7136,-2537.5 7136,-2537.5 7142,-2537.5 7148,-2543.5 7148,-2549.5 7148,-2549.5 7148,-2706.5 7148,-2706.5 7148,-2712.5 7142,-2718.5 7136,-2718.5 7136,-2718.5 6916,-2718.5 6916,-2718.5 6910,-2718.5 6904,-2712.5 6904,-2706.5 6904,-2706.5 6904,-2549.5 6904,-2549.5 6904,-2543.5 6910,-2537.5 6916,-2537.5"/>
<text text-anchor="middle" x="7026" y="-2703.3" font-family="Times,serif" font-size="14.00">OAuth2Mapping</text>
<polyline fill="none" stroke="black" points="6904,-2695.5 7148,-2695.5 "/>
<text text-anchor="start" x="6912" y="-2680.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="6912" y="-2665.3" font-family="Times,serif" font-size="14.00">o_auth2_provider_id :integer</text>
<text text-anchor="start" x="6912" y="-2650.3" font-family="Times,serif" font-size="14.00">local_field :character varying</text>
<text text-anchor="start" x="6912" y="-2635.3" font-family="Times,serif" font-size="14.00">api_field :character varying</text>
<text text-anchor="start" x="6912" y="-2620.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="6912" y="-2605.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="6912" y="-2590.3" font-family="Times,serif" font-size="14.00">local_model :character varying</text>
<text text-anchor="start" x="6912" y="-2575.3" font-family="Times,serif" font-size="14.00">api_endpoint :character varying</text>
<text text-anchor="start" x="6912" y="-2560.3" font-family="Times,serif" font-size="14.00">api_data_type :character varying</text>
<text text-anchor="start" x="6912" y="-2545.3" font-family="Times,serif" font-size="14.00">transformation :jsonb</text>
</g>
<!-- Licence -->
<g id="node40" class="node"><title>Licence</title>
@ -1014,67 +1035,67 @@
<text text-anchor="start" x="1618" y="-2597.8" font-family="Times,serif" font-size="14.00">description :text</text>
</g>
<!-- Licence&#45;&gt;Project -->
<g id="edge44" class="edge"><title>Licence&#45;&gt;Project</title>
<path fill="none" stroke="#cf045a" d="M1699,-2581.67C1699,-2499.67 1699,-2324.67 1699,-2210.66"/>
<ellipse fill="none" stroke="#cf045a" cx="1699" cy="-2585.77" rx="4" ry="4"/>
<polygon fill="#cf045a" stroke="#cf045a" points="1699,-2210.51 1703.5,-2200.51 1699,-2205.51 1699,-2200.51 1699,-2200.51 1699,-2200.51 1699,-2205.51 1694.5,-2200.51 1699,-2210.51 1699,-2210.51"/>
<g id="edge45" class="edge"><title>Licence&#45;&gt;Project</title>
<path fill="none" stroke="#10cb84" d="M1699,-2581.67C1699,-2499.67 1699,-2324.67 1699,-2210.66"/>
<ellipse fill="none" stroke="#10cb84" cx="1699" cy="-2585.77" rx="4" ry="4"/>
<polygon fill="#10cb84" stroke="#10cb84" points="1699,-2210.51 1703.5,-2200.51 1699,-2205.51 1699,-2200.51 1699,-2200.51 1699,-2200.51 1699,-2205.51 1694.5,-2200.51 1699,-2210.51 1699,-2210.51"/>
</g>
<!-- User&#45;&gt;Project -->
<g id="edge48" class="edge"><title>User&#45;&gt;Project</title>
<path fill="none" stroke="#9b116a" d="M2048.5,-2460.85C1967.49,-2378.02 1871.99,-2280.37 1801.31,-2208.1"/>
<ellipse fill="none" stroke="#9b116a" cx="2051.46" cy="-2463.87" rx="4.00002" ry="4.00002"/>
<polygon fill="#9b116a" stroke="#9b116a" points="1801.11,-2207.9 1797.33,-2197.6 1797.61,-2204.32 1794.11,-2200.75 1794.11,-2200.75 1794.11,-2200.75 1797.61,-2204.32 1790.9,-2203.9 1801.11,-2207.9 1801.11,-2207.9"/>
<g id="edge49" class="edge"><title>User&#45;&gt;Project</title>
<path fill="none" stroke="#8a9e90" d="M2048.5,-2460.85C1967.49,-2378.02 1871.99,-2280.37 1801.31,-2208.1"/>
<ellipse fill="none" stroke="#8a9e90" cx="2051.46" cy="-2463.87" rx="4.00002" ry="4.00002"/>
<polygon fill="#8a9e90" stroke="#8a9e90" points="1801.11,-2207.9 1797.33,-2197.6 1797.61,-2204.32 1794.11,-2200.75 1794.11,-2200.75 1794.11,-2200.75 1797.61,-2204.32 1790.9,-2203.9 1801.11,-2207.9 1801.11,-2207.9"/>
<text text-anchor="middle" x="1974" y="-2342.8" font-family="Times,serif" font-size="14.00">my_projects</text>
</g>
<!-- User&#45;&gt;Wallet -->
<g id="edge60" class="edge"><title>User&#45;&gt;Wallet</title>
<path fill="none" stroke="#702510" d="M2046.97,-2508.19C1973.54,-2459.8 1884.03,-2407.1 1797,-2372 1698.28,-2332.19 1662.51,-2358.78 1563,-2321 1240.04,-2198.39 893.083,-1974.68 739.322,-1870.15"/>
<ellipse fill="none" stroke="#702510" cx="2050.69" cy="-2510.65" rx="4.00002" ry="4.00002"/>
<ellipse fill="#702510" stroke="#702510" cx="735.899" cy="-1867.82" rx="4.00002" ry="4.00002"/>
<g id="edge61" class="edge"><title>User&#45;&gt;Wallet</title>
<path fill="none" stroke="#5df8b8" d="M2046.97,-2508.19C1973.54,-2459.8 1884.03,-2407.1 1797,-2372 1698.28,-2332.19 1662.51,-2358.78 1563,-2321 1240.04,-2198.39 893.083,-1974.68 739.322,-1870.15"/>
<ellipse fill="none" stroke="#5df8b8" cx="2050.69" cy="-2510.65" rx="4.00002" ry="4.00002"/>
<ellipse fill="#5df8b8" stroke="#5df8b8" cx="735.899" cy="-1867.82" rx="4.00002" ry="4.00002"/>
</g>
<!-- User&#45;&gt;Invoice -->
<g id="edge58" class="edge"><title>User&#45;&gt;Invoice</title>
<path fill="none" stroke="#6f6e8f" d="M2047.48,-2498.19C1975,-2448.81 1886.07,-2398.09 1797,-2372 1743.36,-2356.29 846.861,-2356.03 791,-2354 656.888,-2349.13 308.468,-2380.14 188,-2321 73.302,-2264.69 0,-2231.27 0,-2103.5 0,-2103.5 0,-2103.5 0,-707 0,-439.758 2069.15,-372.051 2618.46,-358.785"/>
<ellipse fill="none" stroke="#6f6e8f" cx="2051.15" cy="-2500.7" rx="4.00002" ry="4.00002"/>
<polygon fill="#6f6e8f" stroke="#6f6e8f" points="2618.8,-358.777 2628.9,-363.037 2623.8,-358.658 2628.8,-358.538 2628.8,-358.538 2628.8,-358.538 2623.8,-358.658 2628.69,-354.039 2618.8,-358.777 2618.8,-358.777"/>
</g>
<!-- User&#45;&gt;Credit -->
<g id="edge55" class="edge"><title>User&#45;&gt;Credit</title>
<path fill="none" stroke="#6f4f27" d="M2212.54,-2362.11C2216.83,-2219.6 2227.76,-2041.29 2254,-1884 2264.86,-1818.9 2280.8,-1805.66 2294,-1741 2347.51,-1478.82 2326.87,-1407.76 2372,-1144 2374.53,-1129.22 2369.22,-1122.36 2379,-1111 2393.86,-1093.73 2406.57,-1103.09 2427,-1093 2442.2,-1085.49 2457.81,-1076.91 2472.99,-1068.01"/>
<polygon fill="#6f4f27" stroke="#6f4f27" points="2212.54,-2362.31 2207.75,-2372.18 2212.39,-2367.31 2212.25,-2372.31 2212.25,-2372.31 2212.25,-2372.31 2212.39,-2367.31 2216.74,-2372.44 2212.54,-2362.31 2212.54,-2362.31"/>
<polygon fill="#6f4f27" stroke="#6f4f27" points="2473.28,-1067.85 2484.17,-1066.62 2477.58,-1065.3 2481.88,-1062.75 2481.88,-1062.75 2481.88,-1062.75 2477.58,-1065.3 2479.58,-1058.88 2473.28,-1067.85 2473.28,-1067.85"/>
<g id="edge59" class="edge"><title>User&#45;&gt;Invoice</title>
<path fill="none" stroke="#adad8b" d="M2047.48,-2498.19C1975,-2448.81 1886.07,-2398.09 1797,-2372 1743.36,-2356.29 846.861,-2356.03 791,-2354 656.888,-2349.13 308.468,-2380.14 188,-2321 73.302,-2264.69 0,-2231.27 0,-2103.5 0,-2103.5 0,-2103.5 0,-707 0,-449.368 1988.03,-374.827 2525.45,-359.384"/>
<ellipse fill="none" stroke="#adad8b" cx="2051.15" cy="-2500.7" rx="4.00002" ry="4.00002"/>
<polygon fill="#adad8b" stroke="#adad8b" points="2525.57,-359.38 2535.7,-363.593 2530.57,-359.238 2535.57,-359.095 2535.57,-359.095 2535.57,-359.095 2530.57,-359.238 2535.44,-354.597 2525.57,-359.38 2525.57,-359.38"/>
</g>
<!-- User&#45;&gt;Credit -->
<g id="edge56" class="edge"><title>User&#45;&gt;Credit</title>
<path fill="none" stroke="#15f767" d="M2243.53,-2362.26C2245.08,-2348.31 2246.58,-2334.49 2248,-2321 2268.37,-2127.07 2251.8,-2075.79 2287,-1884 2302.42,-1799.99 2461.39,-1222.52 2495,-1144 2505.51,-1119.45 2519.37,-1094 2532.97,-1071.24"/>
<polygon fill="#15f767" stroke="#15f767" points="2243.51,-2362.5 2237.92,-2371.94 2242.95,-2367.47 2242.39,-2372.44 2242.39,-2372.44 2242.39,-2372.44 2242.95,-2367.47 2246.87,-2372.94 2243.51,-2362.5 2243.51,-2362.5"/>
<polygon fill="#15f767" stroke="#15f767" points="2532.98,-1071.22 2542.01,-1064.99 2535.57,-1066.94 2538.16,-1062.66 2538.16,-1062.66 2538.16,-1062.66 2535.57,-1066.94 2534.31,-1060.33 2532.98,-1071.22 2532.98,-1071.22"/>
<text text-anchor="middle" x="2401.5" y="-1668.8" font-family="Times,serif" font-size="14.00">training_credits</text>
<path fill="none" stroke="#26cf78" d="M2212.54,-2362.11C2216.83,-2219.6 2227.76,-2041.29 2254,-1884 2264.86,-1818.9 2280.86,-1805.67 2294,-1741 2347.28,-1478.83 2322.3,-1407.06 2371,-1144 2373.75,-1129.16 2369.91,-1123.04 2379,-1111 2382.07,-1106.93 2414,-1088.35 2451.72,-1067.24"/>
<polygon fill="#26cf78" stroke="#26cf78" points="2212.54,-2362.31 2207.75,-2372.18 2212.39,-2367.31 2212.25,-2372.31 2212.25,-2372.31 2212.25,-2372.31 2212.39,-2367.31 2216.74,-2372.44 2212.54,-2362.31 2212.54,-2362.31"/>
<polygon fill="#26cf78" stroke="#26cf78" points="2452.16,-1066.99 2463.09,-1066.05 2456.53,-1064.55 2460.9,-1062.12 2460.9,-1062.12 2460.9,-1062.12 2456.53,-1064.55 2458.7,-1058.19 2452.16,-1066.99 2452.16,-1066.99"/>
</g>
<!-- User&#45;&gt;Credit -->
<g id="edge57" class="edge"><title>User&#45;&gt;Credit</title>
<path fill="none" stroke="#f52d91" d="M2185.89,-2362.14C2171.58,-2154.73 2163.02,-1859.53 2200,-1604 2230.54,-1393.01 2227.04,-1327.25 2336,-1144 2346.6,-1126.17 2351.24,-1121.72 2369,-1111 2392.11,-1097.05 2402.46,-1104.25 2427,-1093 2443.05,-1085.65 2459.43,-1076.92 2475.27,-1067.76"/>
<polygon fill="#f52d91" stroke="#f52d91" points="2185.9,-2362.29 2182.11,-2372.57 2186.25,-2367.27 2186.6,-2372.26 2186.6,-2372.26 2186.6,-2372.26 2186.25,-2367.27 2191.09,-2371.95 2185.9,-2362.29 2185.9,-2362.29"/>
<polygon fill="#f52d91" stroke="#f52d91" points="2475.38,-1067.7 2486.28,-1066.52 2479.69,-1065.17 2484,-1062.64 2484,-1062.64 2484,-1062.64 2479.69,-1065.17 2481.73,-1058.76 2475.38,-1067.7 2475.38,-1067.7"/>
<path fill="none" stroke="#6203c4" d="M2243.53,-2362.26C2245.08,-2348.31 2246.58,-2334.49 2248,-2321 2268.37,-2127.07 2251.8,-2075.79 2287,-1884 2302.42,-1799.99 2461.39,-1222.52 2495,-1144 2505.51,-1119.45 2519.37,-1094 2532.97,-1071.24"/>
<polygon fill="#6203c4" stroke="#6203c4" points="2243.51,-2362.5 2237.92,-2371.94 2242.95,-2367.47 2242.39,-2372.44 2242.39,-2372.44 2242.39,-2372.44 2242.95,-2367.47 2246.87,-2372.94 2243.51,-2362.5 2243.51,-2362.5"/>
<polygon fill="#6203c4" stroke="#6203c4" points="2532.98,-1071.22 2542.01,-1064.99 2535.57,-1066.94 2538.16,-1062.66 2538.16,-1062.66 2538.16,-1062.66 2535.57,-1066.94 2534.31,-1060.33 2532.98,-1071.22 2532.98,-1071.22"/>
<text text-anchor="middle" x="2401.5" y="-1668.8" font-family="Times,serif" font-size="14.00">training_credits</text>
</g>
<!-- User&#45;&gt;Credit -->
<g id="edge58" class="edge"><title>User&#45;&gt;Credit</title>
<path fill="none" stroke="#92a9b9" d="M2186.18,-2362.18C2172.02,-2154.79 2163.53,-1859.61 2200,-1604 2230.08,-1393.19 2222.86,-1325.64 2334,-1144 2345.16,-1125.76 2351.41,-1123.15 2369,-1111 2384.05,-1100.61 2389.76,-1101.41 2406,-1093 2421.64,-1084.9 2437.95,-1076.22 2454.07,-1067.51"/>
<polygon fill="#92a9b9" stroke="#92a9b9" points="2186.19,-2362.32 2182.39,-2372.61 2186.53,-2367.31 2186.88,-2372.3 2186.88,-2372.3 2186.88,-2372.3 2186.53,-2367.31 2191.37,-2371.99 2186.19,-2362.32 2186.19,-2362.32"/>
<polygon fill="#92a9b9" stroke="#92a9b9" points="2454.21,-1067.44 2465.14,-1066.63 2458.6,-1065.05 2463,-1062.67 2463,-1062.67 2463,-1062.67 2458.6,-1065.05 2460.85,-1058.71 2454.21,-1067.44 2454.21,-1067.44"/>
<text text-anchor="middle" x="2245" y="-1668.8" font-family="Times,serif" font-size="14.00">machine_credits</text>
</g>
<!-- Role -->
<g id="node49" class="node"><title>Role</title>
<path fill="none" stroke="black" d="M1881,-934C1881,-934 2101,-934 2101,-934 2107,-934 2113,-940 2113,-946 2113,-946 2113,-1043 2113,-1043 2113,-1049 2107,-1055 2101,-1055 2101,-1055 1881,-1055 1881,-1055 1875,-1055 1869,-1049 1869,-1043 1869,-1043 1869,-946 1869,-946 1869,-940 1875,-934 1881,-934"/>
<text text-anchor="middle" x="1991" y="-1039.8" font-family="Times,serif" font-size="14.00">Role</text>
<polyline fill="none" stroke="black" points="1869,-1032 2113,-1032 "/>
<text text-anchor="start" x="1877" y="-1016.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="1877" y="-1001.8" font-family="Times,serif" font-size="14.00">name :character varying(255)</text>
<text text-anchor="start" x="1877" y="-986.8" font-family="Times,serif" font-size="14.00">resource_id :integer</text>
<text text-anchor="start" x="1877" y="-971.8" font-family="Times,serif" font-size="14.00">resource_type :character varying(255)</text>
<text text-anchor="start" x="1877" y="-956.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="1877" y="-941.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M1860,-934C1860,-934 2080,-934 2080,-934 2086,-934 2092,-940 2092,-946 2092,-946 2092,-1043 2092,-1043 2092,-1049 2086,-1055 2080,-1055 2080,-1055 1860,-1055 1860,-1055 1854,-1055 1848,-1049 1848,-1043 1848,-1043 1848,-946 1848,-946 1848,-940 1854,-934 1860,-934"/>
<text text-anchor="middle" x="1970" y="-1039.8" font-family="Times,serif" font-size="14.00">Role</text>
<polyline fill="none" stroke="black" points="1848,-1032 2092,-1032 "/>
<text text-anchor="start" x="1856" y="-1016.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="1856" y="-1001.8" font-family="Times,serif" font-size="14.00">name :character varying(255)</text>
<text text-anchor="start" x="1856" y="-986.8" font-family="Times,serif" font-size="14.00">resource_id :integer</text>
<text text-anchor="start" x="1856" y="-971.8" font-family="Times,serif" font-size="14.00">resource_type :character varying(255)</text>
<text text-anchor="start" x="1856" y="-956.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="1856" y="-941.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- User&#45;&gt;Role -->
<g id="edge46" class="edge"><title>User&#45;&gt;Role</title>
<path fill="none" stroke="#1701aa" d="M2116.76,-2362.37C2094.96,-2280.47 2078,-2189.22 2078,-2103.5 2078,-2103.5 2078,-2103.5 2078,-1271.5 2078,-1198.36 2049.87,-1119.15 2025.6,-1064.43"/>
<polygon fill="#1701aa" stroke="#1701aa" points="2116.84,-2362.65 2115.1,-2373.48 2118.14,-2367.48 2119.44,-2372.31 2119.44,-2372.31 2119.44,-2372.31 2118.14,-2367.48 2123.79,-2371.13 2116.84,-2362.65 2116.84,-2362.65"/>
<polygon fill="#1701aa" stroke="#1701aa" points="2025.54,-1064.3 2025.53,-1053.33 2023.48,-1059.74 2021.43,-1055.18 2021.43,-1055.18 2021.43,-1055.18 2023.48,-1059.74 2017.33,-1057.03 2025.54,-1064.3 2025.54,-1064.3"/>
<g id="edge47" class="edge"><title>User&#45;&gt;Role</title>
<path fill="none" stroke="#34d90b" d="M2116.76,-2362.37C2094.96,-2280.47 2078,-2189.22 2078,-2103.5 2078,-2103.5 2078,-2103.5 2078,-1271.5 2078,-1196.8 2043.27,-1118.07 2013.2,-1063.9"/>
<polygon fill="#34d90b" stroke="#34d90b" points="2116.84,-2362.65 2115.1,-2373.48 2118.14,-2367.48 2119.44,-2372.31 2119.44,-2372.31 2119.44,-2372.31 2118.14,-2367.48 2123.79,-2371.13 2116.84,-2362.65 2116.84,-2362.65"/>
<polygon fill="#34d90b" stroke="#34d90b" points="2013.14,-1063.8 2012.15,-1052.88 2010.69,-1059.44 2008.23,-1055.09 2008.23,-1055.09 2008.23,-1055.09 2010.69,-1059.44 2004.31,-1057.3 2013.14,-1063.8 2013.14,-1063.8"/>
</g>
<!-- Notification -->
<g id="node54" class="node"><title>Notification</title>
@ -1094,16 +1115,16 @@
<text text-anchor="start" x="2304.5" y="-2012.3" font-family="Times,serif" font-size="14.00">meta_data :jsonb</text>
</g>
<!-- User&#45;&gt;Notification -->
<g id="edge45" class="edge"><title>User&#45;&gt;Notification</title>
<path fill="none" stroke="#529512" d="M2319.76,-2364.63C2342.44,-2309.9 2365.11,-2255.22 2383.8,-2210.13"/>
<ellipse fill="none" stroke="#529512" cx="2318.17" cy="-2368.46" rx="4.00002" ry="4.00002"/>
<polygon fill="#529512" stroke="#529512" points="2383.9,-2209.9 2391.88,-2202.38 2385.81,-2205.28 2387.73,-2200.66 2387.73,-2200.66 2387.73,-2200.66 2385.81,-2205.28 2383.57,-2198.94 2383.9,-2209.9 2383.9,-2209.9"/>
<g id="edge46" class="edge"><title>User&#45;&gt;Notification</title>
<path fill="none" stroke="#8dcd57" d="M2319.76,-2364.63C2342.44,-2309.9 2365.11,-2255.22 2383.8,-2210.13"/>
<ellipse fill="none" stroke="#8dcd57" cx="2318.17" cy="-2368.46" rx="4.00002" ry="4.00002"/>
<polygon fill="#8dcd57" stroke="#8dcd57" points="2383.9,-2209.9 2391.88,-2202.38 2385.81,-2205.28 2387.73,-2200.66 2387.73,-2200.66 2387.73,-2200.66 2385.81,-2205.28 2383.57,-2198.94 2383.9,-2209.9 2383.9,-2209.9"/>
</g>
<!-- User&#45;&gt;Subscription -->
<g id="edge53" class="edge"><title>User&#45;&gt;Subscription</title>
<path fill="none" stroke="#4c0d3c" d="M2141.86,-2364.23C2141.22,-2360.8 2140.6,-2357.39 2140,-2354 2120.53,-2243.86 2116,-2215.34 2116,-2103.5 2116,-2103.5 2116,-2103.5 2116,-1271.5 2116,-1198.19 2119.8,-1175.84 2154,-1111 2159.97,-1099.68 2167.3,-1088.6 2175.27,-1078.04"/>
<ellipse fill="none" stroke="#4c0d3c" cx="2142.64" cy="-2368.32" rx="4.00001" ry="4.00001"/>
<polygon fill="#4c0d3c" stroke="#4c0d3c" points="2175.33,-1077.97 2185.03,-1072.85 2178.41,-1074.03 2181.48,-1070.08 2181.48,-1070.08 2181.48,-1070.08 2178.41,-1074.03 2177.94,-1067.31 2175.33,-1077.97 2175.33,-1077.97"/>
<g id="edge54" class="edge"><title>User&#45;&gt;Subscription</title>
<path fill="none" stroke="#2359a5" d="M2141.86,-2364.23C2141.22,-2360.8 2140.6,-2357.39 2140,-2354 2120.53,-2243.86 2116,-2215.34 2116,-2103.5 2116,-2103.5 2116,-2103.5 2116,-1271.5 2116,-1198.3 2121.32,-1177 2153,-1111 2158.25,-1100.06 2164.56,-1089.09 2171.33,-1078.49"/>
<ellipse fill="none" stroke="#2359a5" cx="2142.64" cy="-2368.32" rx="4.00001" ry="4.00001"/>
<polygon fill="#2359a5" stroke="#2359a5" points="2171.37,-1078.44 2180.62,-1072.55 2174.11,-1074.26 2176.86,-1070.08 2176.86,-1070.08 2176.86,-1070.08 2174.11,-1074.26 2173.09,-1067.61 2171.37,-1078.44 2171.37,-1078.44"/>
</g>
<!-- Training -->
<g id="node56" class="node"><title>Training</title>
@ -1120,40 +1141,40 @@
<text text-anchor="start" x="3224" y="-2034.8" font-family="Times,serif" font-size="14.00">public_page :boolean</text>
</g>
<!-- User&#45;&gt;Training -->
<g id="edge52" class="edge"><title>User&#45;&gt;Training</title>
<path fill="none" stroke="#5e613b" d="M2377.67,-2604.59C2580.06,-2570.82 2924.6,-2491.71 3169,-2321 3218.9,-2286.14 3260.97,-2232.17 3290.64,-2186.72"/>
<polygon fill="#5e613b" stroke="#5e613b" points="2377.41,-2604.63 2366.81,-2601.82 2372.48,-2605.45 2367.54,-2606.26 2367.54,-2606.26 2367.54,-2606.26 2372.48,-2605.45 2368.28,-2610.7 2377.41,-2604.63 2377.41,-2604.63"/>
<polygon fill="#5e613b" stroke="#5e613b" points="3290.82,-2186.45 3300.01,-2180.48 3293.52,-2182.25 3296.23,-2178.04 3296.23,-2178.04 3296.23,-2178.04 3293.52,-2182.25 3292.44,-2175.61 3290.82,-2186.45 3290.82,-2186.45"/>
<g id="edge53" class="edge"><title>User&#45;&gt;Training</title>
<path fill="none" stroke="#a15087" d="M2377.67,-2604.59C2580.06,-2570.82 2924.6,-2491.71 3169,-2321 3218.9,-2286.14 3260.97,-2232.17 3290.64,-2186.72"/>
<polygon fill="#a15087" stroke="#a15087" points="2377.41,-2604.63 2366.81,-2601.82 2372.48,-2605.45 2367.54,-2606.26 2367.54,-2606.26 2367.54,-2606.26 2372.48,-2605.45 2368.28,-2610.7 2377.41,-2604.63 2377.41,-2604.63"/>
<polygon fill="#a15087" stroke="#a15087" points="3290.82,-2186.45 3300.01,-2180.48 3293.52,-2182.25 3296.23,-2178.04 3296.23,-2178.04 3296.23,-2178.04 3293.52,-2182.25 3292.44,-2175.61 3290.82,-2186.45 3290.82,-2186.45"/>
</g>
<!-- User&#45;&gt;Reservation -->
<g id="edge50" class="edge"><title>User&#45;&gt;Reservation</title>
<path fill="none" stroke="#e50380" d="M2375.73,-2622.21C2630.54,-2607.51 3126.57,-2549.2 3469,-2321 3533.49,-2278.03 3820.55,-1806.21 3882,-1759 3899.41,-1745.63 3912.82,-1756.86 3928,-1741 3978.35,-1688.41 3968.6,-1657.74 3981,-1586 3993.65,-1512.82 3993.91,-1428.55 3991.42,-1365.98"/>
<ellipse fill="none" stroke="#e50380" cx="2371.51" cy="-2622.44" rx="4" ry="4"/>
<polygon fill="#e50380" stroke="#e50380" points="3991.41,-1365.73 3995.48,-1355.54 3991.2,-1360.73 3990.98,-1355.74 3990.98,-1355.74 3990.98,-1355.74 3991.2,-1360.73 3986.49,-1355.93 3991.41,-1365.73 3991.41,-1365.73"/>
<g id="edge51" class="edge"><title>User&#45;&gt;Reservation</title>
<path fill="none" stroke="#b68989" d="M2375.73,-2622.21C2630.54,-2607.51 3126.57,-2549.2 3469,-2321 3533.49,-2278.03 3820.55,-1806.21 3882,-1759 3899.41,-1745.63 3912.82,-1756.86 3928,-1741 3978.35,-1688.41 3968.6,-1657.74 3981,-1586 3993.65,-1512.82 3993.91,-1428.55 3991.42,-1365.98"/>
<ellipse fill="none" stroke="#b68989" cx="2371.51" cy="-2622.44" rx="4" ry="4"/>
<polygon fill="#b68989" stroke="#b68989" points="3991.41,-1365.73 3995.48,-1355.54 3991.2,-1360.73 3990.98,-1355.74 3990.98,-1355.74 3990.98,-1355.74 3991.2,-1360.73 3986.49,-1355.93 3991.41,-1365.73 3991.41,-1365.73"/>
</g>
<!-- UsersCredit -->
<g id="node61" class="node"><title>UsersCredit</title>
<path fill="none" stroke="black" d="M2524,-647.5C2524,-647.5 2744,-647.5 2744,-647.5 2750,-647.5 2756,-653.5 2756,-659.5 2756,-659.5 2756,-756.5 2756,-756.5 2756,-762.5 2750,-768.5 2744,-768.5 2744,-768.5 2524,-768.5 2524,-768.5 2518,-768.5 2512,-762.5 2512,-756.5 2512,-756.5 2512,-659.5 2512,-659.5 2512,-653.5 2518,-647.5 2524,-647.5"/>
<text text-anchor="middle" x="2634" y="-753.3" font-family="Times,serif" font-size="14.00">UsersCredit</text>
<polyline fill="none" stroke="black" points="2512,-745.5 2756,-745.5 "/>
<text text-anchor="start" x="2520" y="-730.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="2520" y="-715.3" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="2520" y="-700.3" font-family="Times,serif" font-size="14.00">credit_id :integer</text>
<text text-anchor="start" x="2520" y="-685.3" font-family="Times,serif" font-size="14.00">hours_used :integer</text>
<text text-anchor="start" x="2520" y="-670.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="2520" y="-655.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M2503,-647.5C2503,-647.5 2723,-647.5 2723,-647.5 2729,-647.5 2735,-653.5 2735,-659.5 2735,-659.5 2735,-756.5 2735,-756.5 2735,-762.5 2729,-768.5 2723,-768.5 2723,-768.5 2503,-768.5 2503,-768.5 2497,-768.5 2491,-762.5 2491,-756.5 2491,-756.5 2491,-659.5 2491,-659.5 2491,-653.5 2497,-647.5 2503,-647.5"/>
<text text-anchor="middle" x="2613" y="-753.3" font-family="Times,serif" font-size="14.00">UsersCredit</text>
<polyline fill="none" stroke="black" points="2491,-745.5 2735,-745.5 "/>
<text text-anchor="start" x="2499" y="-730.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="2499" y="-715.3" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="2499" y="-700.3" font-family="Times,serif" font-size="14.00">credit_id :integer</text>
<text text-anchor="start" x="2499" y="-685.3" font-family="Times,serif" font-size="14.00">hours_used :integer</text>
<text text-anchor="start" x="2499" y="-670.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="2499" y="-655.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- User&#45;&gt;UsersCredit -->
<g id="edge54" class="edge"><title>User&#45;&gt;UsersCredit</title>
<path fill="none" stroke="#329bfb" d="M2173.49,-2364.11C2172.12,-2349.54 2170.94,-2335.1 2170,-2321 2161.29,-2190.36 2143.87,-1245.15 2227,-1144 2239.32,-1129.01 2380.35,-1106.79 2394,-1093 2458.21,-1028.14 2399.36,-970.561 2452,-896 2468.15,-873.123 2482.33,-877.888 2503,-859 2530.41,-833.954 2557.88,-803.523 2580.54,-776.633"/>
<ellipse fill="none" stroke="#329bfb" cx="2173.88" cy="-2368.23" rx="4" ry="4"/>
<polygon fill="#329bfb" stroke="#329bfb" points="2580.68,-776.455 2590.55,-771.668 2583.89,-772.618 2587.1,-768.782 2587.1,-768.782 2587.1,-768.782 2583.89,-772.618 2583.65,-765.896 2580.68,-776.455 2580.68,-776.455"/>
<g id="edge55" class="edge"><title>User&#45;&gt;UsersCredit</title>
<path fill="none" stroke="#a47d08" d="M2174.4,-2364.1C2173.07,-2349.54 2171.92,-2335.1 2171,-2321 2162.5,-2190.36 2144.05,-1246.89 2225,-1144 2268.02,-1089.32 2322.6,-1140.96 2373,-1093 2441.33,-1027.97 2403.01,-976.613 2452,-896 2456.14,-889.188 2509.9,-827.07 2554.18,-776.268"/>
<ellipse fill="none" stroke="#a47d08" cx="2174.78" cy="-2368.22" rx="4" ry="4"/>
<polygon fill="#a47d08" stroke="#a47d08" points="2554.34,-776.08 2564.31,-771.5 2557.63,-772.312 2560.91,-768.543 2560.91,-768.543 2560.91,-768.543 2557.63,-772.312 2557.52,-765.586 2554.34,-776.08 2554.34,-776.08"/>
</g>
<!-- User&#45;&gt;UserTag -->
<g id="edge59" class="edge"><title>User&#45;&gt;UserTag</title>
<path fill="none" stroke="#d555ba" d="M2375.51,-2586.38C2516.43,-2545.41 2718.99,-2471.23 2864,-2354 2928.17,-2302.13 2978.69,-2220.59 3008.4,-2164.72"/>
<ellipse fill="none" stroke="#d555ba" cx="2371.43" cy="-2587.56" rx="4.00001" ry="4.00001"/>
<polygon fill="#d555ba" stroke="#d555ba" points="3008.52,-2164.5 3017.15,-2157.73 3010.84,-2160.07 3013.17,-2155.64 3013.17,-2155.64 3013.17,-2155.64 3010.84,-2160.07 3009.18,-2153.55 3008.52,-2164.5 3008.52,-2164.5"/>
<g id="edge60" class="edge"><title>User&#45;&gt;UserTag</title>
<path fill="none" stroke="#ea0e6d" d="M2375.51,-2586.38C2516.43,-2545.41 2718.99,-2471.23 2864,-2354 2928.17,-2302.13 2978.69,-2220.59 3008.4,-2164.72"/>
<ellipse fill="none" stroke="#ea0e6d" cx="2371.43" cy="-2587.56" rx="4.00001" ry="4.00001"/>
<polygon fill="#ea0e6d" stroke="#ea0e6d" points="3008.52,-2164.5 3017.15,-2157.73 3010.84,-2160.07 3013.17,-2155.64 3013.17,-2155.64 3013.17,-2155.64 3010.84,-2160.07 3009.18,-2153.55 3008.52,-2164.5 3008.52,-2164.5"/>
</g>
<!-- Export -->
<g id="node67" class="node"><title>Export</title>
@ -1170,10 +1191,10 @@
<text text-anchor="start" x="2586" y="-2034.8" font-family="Times,serif" font-size="14.00">key :character varying</text>
</g>
<!-- User&#45;&gt;Export -->
<g id="edge61" class="edge"><title>User&#45;&gt;Export</title>
<path fill="none" stroke="#4d3f73" d="M2373.76,-2505.85C2438.47,-2453.19 2510.94,-2388.22 2568,-2321 2602.63,-2280.21 2634.04,-2229.32 2657.52,-2187.03"/>
<ellipse fill="none" stroke="#4d3f73" cx="2370.63" cy="-2508.39" rx="4.00002" ry="4.00002"/>
<polygon fill="#4d3f73" stroke="#4d3f73" points="2657.59,-2186.9 2666.36,-2180.31 2660,-2182.52 2662.41,-2178.14 2662.41,-2178.14 2662.41,-2178.14 2660,-2182.52 2658.47,-2175.97 2657.59,-2186.9 2657.59,-2186.9"/>
<g id="edge62" class="edge"><title>User&#45;&gt;Export</title>
<path fill="none" stroke="#f8ca5a" d="M2373.76,-2505.85C2438.47,-2453.19 2510.94,-2388.22 2568,-2321 2602.63,-2280.21 2634.04,-2229.32 2657.52,-2187.03"/>
<ellipse fill="none" stroke="#f8ca5a" cx="2370.63" cy="-2508.39" rx="4.00002" ry="4.00002"/>
<polygon fill="#f8ca5a" stroke="#f8ca5a" points="2657.59,-2186.9 2666.36,-2180.31 2660,-2182.52 2662.41,-2178.14 2662.41,-2178.14 2662.41,-2178.14 2660,-2182.52 2658.47,-2175.97 2657.59,-2186.9 2657.59,-2186.9"/>
</g>
<!-- UserTraining -->
<g id="node73" class="node"><title>UserTraining</title>
@ -1187,19 +1208,19 @@
<text text-anchor="start" x="2475" y="-1627.3" font-family="Times,serif" font-size="14.00">training_id :integer</text>
</g>
<!-- User&#45;&gt;UserTraining -->
<g id="edge51" class="edge"><title>User&#45;&gt;UserTraining</title>
<path fill="none" stroke="#c0d2d4" d="M2375.42,-2596.26C2523.32,-2558.96 2732.09,-2480.12 2831,-2321 2882.27,-2238.52 2871.26,-1972.37 2831,-1884 2801.8,-1819.91 2742.38,-1767.76 2689.73,-1731.4"/>
<ellipse fill="none" stroke="#c0d2d4" cx="2371.42" cy="-2597.26" rx="4.00001" ry="4.00001"/>
<polygon fill="#c0d2d4" stroke="#c0d2d4" points="2689.62,-1731.33 2683.87,-1721.98 2685.48,-1728.52 2681.34,-1725.71 2681.34,-1725.71 2681.34,-1725.71 2685.48,-1728.52 2678.81,-1729.43 2689.62,-1731.33 2689.62,-1731.33"/>
<g id="edge52" class="edge"><title>User&#45;&gt;UserTraining</title>
<path fill="none" stroke="#474906" d="M2375.42,-2596.26C2523.32,-2558.96 2732.09,-2480.12 2831,-2321 2882.27,-2238.52 2871.26,-1972.37 2831,-1884 2801.8,-1819.91 2742.38,-1767.76 2689.73,-1731.4"/>
<ellipse fill="none" stroke="#474906" cx="2371.42" cy="-2597.26" rx="4.00001" ry="4.00001"/>
<polygon fill="#474906" stroke="#474906" points="2689.62,-1731.33 2683.87,-1721.98 2685.48,-1728.52 2681.34,-1725.71 2681.34,-1725.71 2681.34,-1725.71 2685.48,-1728.52 2678.81,-1729.43 2689.62,-1731.33 2689.62,-1731.33"/>
</g>
<!-- User&#45;&gt;ProjectUser -->
<g id="edge49" class="edge"><title>User&#45;&gt;ProjectUser</title>
<path fill="none" stroke="#e638fc" d="M2046.97,-2508.19C1973.54,-2459.8 1884.03,-2407.1 1797,-2372 1698.28,-2332.19 1660.44,-2363.83 1563,-2321 1241.5,-2179.69 1177.53,-2101.48 917,-1866 877.622,-1830.41 838.477,-1785.9 807.994,-1748.65"/>
<ellipse fill="none" stroke="#e638fc" cx="2050.69" cy="-2510.65" rx="4.00002" ry="4.00002"/>
<polygon fill="#e638fc" stroke="#e638fc" points="807.933,-1748.58 805.115,-1737.98 804.778,-1744.7 801.624,-1740.82 801.624,-1740.82 801.624,-1740.82 804.778,-1744.7 798.132,-1743.66 807.933,-1748.58 807.933,-1748.58"/>
<g id="edge50" class="edge"><title>User&#45;&gt;ProjectUser</title>
<path fill="none" stroke="#752306" d="M2046.97,-2508.19C1973.54,-2459.8 1884.03,-2407.1 1797,-2372 1698.28,-2332.19 1660.44,-2363.83 1563,-2321 1241.5,-2179.69 1177.53,-2101.48 917,-1866 877.622,-1830.41 838.477,-1785.9 807.994,-1748.65"/>
<ellipse fill="none" stroke="#752306" cx="2050.69" cy="-2510.65" rx="4.00002" ry="4.00002"/>
<polygon fill="#752306" stroke="#752306" points="807.933,-1748.58 805.115,-1737.98 804.778,-1744.7 801.624,-1740.82 801.624,-1740.82 801.624,-1740.82 804.778,-1744.7 798.132,-1743.66 807.933,-1748.58 807.933,-1748.58"/>
</g>
<!-- Profile -->
<g id="node86" class="node"><title>Profile</title>
<g id="node87" class="node"><title>Profile</title>
<path fill="none" stroke="black" d="M209,-1884.5C209,-1884.5 429,-1884.5 429,-1884.5 435,-1884.5 441,-1890.5 441,-1896.5 441,-1896.5 441,-2308.5 441,-2308.5 441,-2314.5 435,-2320.5 429,-2320.5 429,-2320.5 209,-2320.5 209,-2320.5 203,-2320.5 197,-2314.5 197,-2308.5 197,-2308.5 197,-1896.5 197,-1896.5 197,-1890.5 203,-1884.5 209,-1884.5"/>
<text text-anchor="middle" x="319" y="-2305.3" font-family="Times,serif" font-size="14.00">Profile</text>
<polyline fill="none" stroke="black" points="197,-2297.5 441,-2297.5 "/>
@ -1232,10 +1253,10 @@
<text text-anchor="start" x="205" y="-1892.3" font-family="Times,serif" font-size="14.00">job :character varying</text>
</g>
<!-- User&#45;&gt;Profile -->
<g id="edge47" class="edge"><title>User&#45;&gt;Profile</title>
<path fill="none" stroke="#65680b" d="M2047.47,-2498.23C1974.99,-2448.86 1886.06,-2398.13 1797,-2372 1694.95,-2342.05 943.466,-2378.61 840,-2354 698.381,-2320.32 549.994,-2244.39 447.968,-2184.9"/>
<ellipse fill="none" stroke="#65680b" cx="2051.13" cy="-2500.74" rx="4.00002" ry="4.00002"/>
<ellipse fill="#65680b" stroke="#65680b" cx="444.461" cy="-2182.85" rx="4.00002" ry="4.00002"/>
<g id="edge48" class="edge"><title>User&#45;&gt;Profile</title>
<path fill="none" stroke="#d861ed" d="M2047.47,-2498.23C1974.99,-2448.86 1886.06,-2398.13 1797,-2372 1694.95,-2342.05 943.466,-2378.61 840,-2354 698.381,-2320.32 549.994,-2244.39 447.968,-2184.9"/>
<ellipse fill="none" stroke="#d861ed" cx="2051.13" cy="-2500.74" rx="4.00002" ry="4.00002"/>
<ellipse fill="#d861ed" stroke="#d861ed" cx="444.461" cy="-2182.85" rx="4.00002" ry="4.00002"/>
</g>
<!-- ProjectStepImage -->
<g id="node42" class="node"><title>ProjectStepImage</title>
@ -1251,10 +1272,10 @@
<text text-anchor="start" x="898" y="-1212.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Credit&#45;&gt;UsersCredit -->
<g id="edge62" class="edge"><title>Credit&#45;&gt;UsersCredit</title>
<path fill="none" stroke="#ab650a" d="M2596.45,-918.458C2604.21,-875.187 2613.9,-821.143 2621.49,-778.791"/>
<ellipse fill="none" stroke="#ab650a" cx="2595.73" cy="-922.5" rx="4.00001" ry="4.00001"/>
<polygon fill="#ab650a" stroke="#ab650a" points="2621.51,-778.685 2627.7,-769.636 2622.39,-773.763 2623.27,-768.842 2623.27,-768.842 2623.27,-768.842 2622.39,-773.763 2618.84,-768.048 2621.51,-778.685 2621.51,-778.685"/>
<g id="edge63" class="edge"><title>Credit&#45;&gt;UsersCredit</title>
<path fill="none" stroke="#189ac6" d="M2590.91,-918.458C2595.48,-875.187 2601.17,-821.143 2605.64,-778.791"/>
<ellipse fill="none" stroke="#189ac6" cx="2590.49" cy="-922.46" rx="4" ry="4"/>
<polygon fill="#189ac6" stroke="#189ac6" points="2605.64,-778.787 2611.16,-769.314 2606.17,-773.814 2606.69,-768.842 2606.69,-768.842 2606.69,-768.842 2606.17,-773.814 2602.21,-768.37 2605.64,-778.787 2605.64,-778.787"/>
</g>
<!-- PartnerPlan -->
<g id="node45" class="node"><title>PartnerPlan</title>
@ -1278,151 +1299,151 @@
<text text-anchor="start" x="2550" y="-1152.3" font-family="Times,serif" font-size="14.00">interval_count :integer</text>
</g>
<!-- PartnerPlan&#45;&gt;Price -->
<g id="edge69" class="edge"><title>PartnerPlan&#45;&gt;Price</title>
<path fill="none" stroke="#644f4c" d="M2793.51,-1145.16C2794.33,-1144.77 2795.17,-1144.38 2796,-1144 2838.23,-1124.78 2957.88,-1131.06 3004,-1126 3114.53,-1113.87 3148.99,-1134.87 3252,-1093 3263.61,-1088.28 3275.11,-1082.29 3286.2,-1075.6"/>
<ellipse fill="none" stroke="#644f4c" cx="2789.67" cy="-1147.1" rx="4.00002" ry="4.00002"/>
<polygon fill="#644f4c" stroke="#644f4c" points="3286.52,-1075.4 3297.38,-1073.91 3290.76,-1072.75 3294.99,-1070.1 3294.99,-1070.1 3294.99,-1070.1 3290.76,-1072.75 3292.61,-1066.28 3286.52,-1075.4 3286.52,-1075.4"/>
<g id="edge70" class="edge"><title>PartnerPlan&#45;&gt;Price</title>
<path fill="none" stroke="#05a07f" d="M2793.51,-1145.16C2794.33,-1144.77 2795.17,-1144.38 2796,-1144 2838.23,-1124.78 2957.88,-1131.06 3004,-1126 3114.53,-1113.87 3148.99,-1134.87 3252,-1093 3263.61,-1088.28 3275.11,-1082.29 3286.2,-1075.6"/>
<ellipse fill="none" stroke="#05a07f" cx="2789.67" cy="-1147.1" rx="4.00002" ry="4.00002"/>
<polygon fill="#05a07f" stroke="#05a07f" points="3286.52,-1075.4 3297.38,-1073.91 3290.76,-1072.75 3294.99,-1070.1 3294.99,-1070.1 3294.99,-1070.1 3290.76,-1072.75 3292.61,-1066.28 3286.52,-1075.4 3286.52,-1075.4"/>
</g>
<!-- PartnerPlan&#45;&gt;PlanFile -->
<g id="edge68" class="edge"><title>PartnerPlan&#45;&gt;PlanFile</title>
<path fill="none" stroke="#e139d2" d="M2793.58,-1145.31C2794.38,-1144.87 2795.19,-1144.43 2796,-1144 2829.7,-1126.05 2856,-1155.69 2880,-1126 2892.61,-1110.4 2894.16,-1090.25 2890.74,-1070.46"/>
<ellipse fill="none" stroke="#e139d2" cx="2789.84" cy="-1147.47" rx="4.00002" ry="4.00002"/>
<ellipse fill="#e139d2" stroke="#e139d2" cx="2889.93" cy="-1066.53" rx="4.00001" ry="4.00001"/>
</g>
<!-- PartnerPlan&#45;&gt;Credit -->
<g id="edge63" class="edge"><title>PartnerPlan&#45;&gt;Credit</title>
<path fill="none" stroke="#2552f7" d="M2553.26,-1137.03C2551.71,-1133.38 2550.29,-1129.7 2549,-1126 2543.03,-1108.83 2543.81,-1090.08 2547.79,-1072.28"/>
<ellipse fill="none" stroke="#2552f7" cx="2554.96" cy="-1140.83" rx="4.00002" ry="4.00002"/>
<polygon fill="#2552f7" stroke="#2552f7" points="2547.82,-1072.18 2554.67,-1063.62 2549.07,-1067.34 2550.31,-1062.5 2550.31,-1062.5 2550.31,-1062.5 2549.07,-1067.34 2545.96,-1061.38 2547.82,-1072.18 2547.82,-1072.18"/>
<g id="edge69" class="edge"><title>PartnerPlan&#45;&gt;PlanFile</title>
<path fill="none" stroke="#90bfe5" d="M2793.58,-1145.31C2794.38,-1144.87 2795.19,-1144.43 2796,-1144 2829.7,-1126.05 2856,-1155.69 2880,-1126 2892.61,-1110.4 2894.16,-1090.25 2890.74,-1070.46"/>
<ellipse fill="none" stroke="#90bfe5" cx="2789.84" cy="-1147.47" rx="4.00002" ry="4.00002"/>
<ellipse fill="#90bfe5" stroke="#90bfe5" cx="2889.93" cy="-1066.53" rx="4.00001" ry="4.00001"/>
</g>
<!-- PartnerPlan&#45;&gt;Credit -->
<g id="edge64" class="edge"><title>PartnerPlan&#45;&gt;Credit</title>
<path fill="none" stroke="#00ca97" d="M2572.46,-1136.51C2571.2,-1133.02 2570.04,-1129.51 2569,-1126 2564,-1109.2 2563.27,-1090.72 2564.69,-1073.08"/>
<ellipse fill="none" stroke="#00ca97" cx="2573.95" cy="-1140.39" rx="4.00001" ry="4.00001"/>
<polygon fill="#00ca97" stroke="#00ca97" points="2564.73,-1072.76 2570.24,-1063.28 2565.25,-1067.79 2565.76,-1062.81 2565.76,-1062.81 2565.76,-1062.81 2565.25,-1067.79 2561.29,-1062.35 2564.73,-1072.76 2564.73,-1072.76"/>
<text text-anchor="middle" x="2611.5" y="-1114.8" font-family="Times,serif" font-size="14.00">training_credits</text>
<path fill="none" stroke="#a71152" d="M2553.26,-1137.03C2551.71,-1133.38 2550.29,-1129.7 2549,-1126 2543.03,-1108.83 2543.81,-1090.08 2547.79,-1072.28"/>
<ellipse fill="none" stroke="#a71152" cx="2554.96" cy="-1140.83" rx="4.00002" ry="4.00002"/>
<polygon fill="#a71152" stroke="#a71152" points="2547.82,-1072.18 2554.67,-1063.62 2549.07,-1067.34 2550.31,-1062.5 2550.31,-1062.5 2550.31,-1062.5 2549.07,-1067.34 2545.96,-1061.38 2547.82,-1072.18 2547.82,-1072.18"/>
</g>
<!-- PartnerPlan&#45;&gt;Credit -->
<g id="edge65" class="edge"><title>PartnerPlan&#45;&gt;Credit</title>
<path fill="none" stroke="#e741a2" d="M2660.4,-1136.29C2658.69,-1127.65 2656.58,-1119.15 2654,-1111 2649.8,-1097.73 2643.75,-1084.42 2636.93,-1071.81"/>
<ellipse fill="none" stroke="#e741a2" cx="2661.14" cy="-1140.33" rx="4.00001" ry="4.00001"/>
<polygon fill="#e741a2" stroke="#e741a2" points="2636.74,-1071.48 2635.76,-1060.55 2634.29,-1067.12 2631.84,-1062.76 2631.84,-1062.76 2631.84,-1062.76 2634.29,-1067.12 2627.92,-1064.96 2636.74,-1071.48 2636.74,-1071.48"/>
<path fill="none" stroke="#a802df" d="M2572.46,-1136.51C2571.2,-1133.02 2570.04,-1129.51 2569,-1126 2564,-1109.2 2563.27,-1090.72 2564.69,-1073.08"/>
<ellipse fill="none" stroke="#a802df" cx="2573.95" cy="-1140.39" rx="4.00001" ry="4.00001"/>
<polygon fill="#a802df" stroke="#a802df" points="2564.73,-1072.76 2570.24,-1063.28 2565.25,-1067.79 2565.76,-1062.81 2565.76,-1062.81 2565.76,-1062.81 2565.25,-1067.79 2561.29,-1062.35 2564.73,-1072.76 2564.73,-1072.76"/>
<text text-anchor="middle" x="2611.5" y="-1114.8" font-family="Times,serif" font-size="14.00">training_credits</text>
</g>
<!-- PartnerPlan&#45;&gt;Credit -->
<g id="edge66" class="edge"><title>PartnerPlan&#45;&gt;Credit</title>
<path fill="none" stroke="#af1897" d="M2660.4,-1136.29C2658.69,-1127.65 2656.58,-1119.15 2654,-1111 2649.8,-1097.73 2643.75,-1084.42 2636.93,-1071.81"/>
<ellipse fill="none" stroke="#af1897" cx="2661.14" cy="-1140.33" rx="4.00001" ry="4.00001"/>
<polygon fill="#af1897" stroke="#af1897" points="2636.74,-1071.48 2635.76,-1060.55 2634.29,-1067.12 2631.84,-1062.76 2631.84,-1062.76 2631.84,-1062.76 2634.29,-1067.12 2627.92,-1064.96 2636.74,-1071.48 2636.74,-1071.48"/>
<text text-anchor="middle" x="2703" y="-1114.8" font-family="Times,serif" font-size="14.00">machine_credits</text>
</g>
<!-- PartnerPlan&#45;&gt;Role -->
<g id="edge70" class="edge"><title>PartnerPlan&#45;&gt;Role</title>
<path fill="none" stroke="#aadb30" d="M2533.9,-1241.27C2421.07,-1212.14 2255.4,-1162.28 2122,-1093 2104.65,-1083.99 2087.13,-1072.75 2070.81,-1061.15"/>
<ellipse fill="none" stroke="#aadb30" cx="2538.05" cy="-1242.33" rx="4.00001" ry="4.00001"/>
<polygon fill="#aadb30" stroke="#aadb30" points="2070.49,-1060.92 2065.02,-1051.41 2066.44,-1057.99 2062.38,-1055.06 2062.38,-1055.06 2062.38,-1055.06 2066.44,-1057.99 2059.75,-1058.7 2070.49,-1060.92 2070.49,-1060.92"/>
<g id="edge71" class="edge"><title>PartnerPlan&#45;&gt;Role</title>
<path fill="none" stroke="#bd8e90" d="M2533.94,-1243.34C2416.64,-1214.94 2241.51,-1164.98 2101,-1093 2083.6,-1084.08 2066.06,-1072.89 2049.73,-1061.3"/>
<ellipse fill="none" stroke="#bd8e90" cx="2538.04" cy="-1244.32" rx="4.00001" ry="4.00001"/>
<polygon fill="#bd8e90" stroke="#bd8e90" points="2049.41,-1061.07 2043.94,-1051.57 2045.35,-1058.14 2041.3,-1055.22 2041.3,-1055.22 2041.3,-1055.22 2045.35,-1058.14 2038.67,-1058.86 2049.41,-1061.07 2049.41,-1061.07"/>
</g>
<!-- PartnerPlan&#45;&gt;Subscription -->
<g id="edge66" class="edge"><title>PartnerPlan&#45;&gt;Subscription</title>
<path fill="none" stroke="#a4b893" d="M2535.01,-1190.2C2503.08,-1169.6 2469.11,-1147.27 2438,-1126 2414.91,-1110.22 2390.47,-1092.91 2367.3,-1076.21"/>
<ellipse fill="none" stroke="#a4b893" cx="2538.43" cy="-1192.4" rx="4.00002" ry="4.00002"/>
<polygon fill="#a4b893" stroke="#a4b893" points="2367.27,-1076.19 2361.79,-1066.69 2363.21,-1073.26 2359.16,-1070.34 2359.16,-1070.34 2359.16,-1070.34 2363.21,-1073.26 2356.52,-1073.99 2367.27,-1076.19 2367.27,-1076.19"/>
<g id="edge67" class="edge"><title>PartnerPlan&#45;&gt;Subscription</title>
<path fill="none" stroke="#6fe3a8" d="M2535.21,-1188.71C2503.42,-1168.24 2469.46,-1146.34 2438,-1126 2412.89,-1109.76 2386.03,-1092.36 2360.39,-1075.72"/>
<ellipse fill="none" stroke="#6fe3a8" cx="2538.6" cy="-1190.89" rx="4.00002" ry="4.00002"/>
<polygon fill="#6fe3a8" stroke="#6fe3a8" points="2360.14,-1075.55 2354.2,-1066.33 2355.94,-1072.83 2351.75,-1070.11 2351.75,-1070.11 2351.75,-1070.11 2355.94,-1072.83 2349.3,-1073.88 2360.14,-1075.55 2360.14,-1075.55"/>
</g>
<!-- PartnerPlan&#45;&gt;PlanImage -->
<g id="edge67" class="edge"><title>PartnerPlan&#45;&gt;PlanImage</title>
<path fill="none" stroke="#3a71a8" d="M2793.56,-1145.27C2794.37,-1144.84 2795.18,-1144.42 2796,-1144 2837.42,-1122.93 2854.1,-1137.97 2899,-1126 2940.57,-1114.92 2952.12,-1113.39 2990,-1093 3003.94,-1085.49 3018.04,-1076.62 3031.56,-1067.33"/>
<ellipse fill="none" stroke="#3a71a8" cx="2789.79" cy="-1147.36" rx="4.00002" ry="4.00002"/>
<ellipse fill="#3a71a8" stroke="#3a71a8" cx="3034.86" cy="-1065.03" rx="4.00002" ry="4.00002"/>
<g id="edge68" class="edge"><title>PartnerPlan&#45;&gt;PlanImage</title>
<path fill="none" stroke="#1894ae" d="M2793.56,-1145.27C2794.37,-1144.84 2795.18,-1144.42 2796,-1144 2837.42,-1122.93 2854.1,-1137.97 2899,-1126 2940.57,-1114.92 2952.12,-1113.39 2990,-1093 3003.94,-1085.49 3018.04,-1076.62 3031.56,-1067.33"/>
<ellipse fill="none" stroke="#1894ae" cx="2789.79" cy="-1147.36" rx="4.00002" ry="4.00002"/>
<ellipse fill="#1894ae" stroke="#1894ae" cx="3034.86" cy="-1065.03" rx="4.00002" ry="4.00002"/>
</g>
<!-- OAuth2Provider -->
<g id="node46" class="node"><title>OAuth2Provider</title>
<path fill="none" stroke="black" d="M6965,-2921.5C6965,-2921.5 7185,-2921.5 7185,-2921.5 7191,-2921.5 7197,-2927.5 7197,-2933.5 7197,-2933.5 7197,-3075.5 7197,-3075.5 7197,-3081.5 7191,-3087.5 7185,-3087.5 7185,-3087.5 6965,-3087.5 6965,-3087.5 6959,-3087.5 6953,-3081.5 6953,-3075.5 6953,-3075.5 6953,-2933.5 6953,-2933.5 6953,-2927.5 6959,-2921.5 6965,-2921.5"/>
<text text-anchor="middle" x="7075" y="-3072.3" font-family="Times,serif" font-size="14.00">OAuth2Provider</text>
<polyline fill="none" stroke="black" points="6953,-3064.5 7197,-3064.5 "/>
<text text-anchor="start" x="6961" y="-3049.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="6961" y="-3034.3" font-family="Times,serif" font-size="14.00">base_url :character varying</text>
<text text-anchor="start" x="6961" y="-3019.3" font-family="Times,serif" font-size="14.00">token_endpoint :character varying</text>
<text text-anchor="start" x="6961" y="-3004.3" font-family="Times,serif" font-size="14.00">authorization_endpoint :character varying</text>
<text text-anchor="start" x="6961" y="-2989.3" font-family="Times,serif" font-size="14.00">client_id :character varying</text>
<text text-anchor="start" x="6961" y="-2974.3" font-family="Times,serif" font-size="14.00">client_secret :character varying</text>
<text text-anchor="start" x="6961" y="-2959.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="6961" y="-2944.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="6961" y="-2929.3" font-family="Times,serif" font-size="14.00">profile_url :character varying</text>
<path fill="none" stroke="black" d="M6916,-2921.5C6916,-2921.5 7136,-2921.5 7136,-2921.5 7142,-2921.5 7148,-2927.5 7148,-2933.5 7148,-2933.5 7148,-3075.5 7148,-3075.5 7148,-3081.5 7142,-3087.5 7136,-3087.5 7136,-3087.5 6916,-3087.5 6916,-3087.5 6910,-3087.5 6904,-3081.5 6904,-3075.5 6904,-3075.5 6904,-2933.5 6904,-2933.5 6904,-2927.5 6910,-2921.5 6916,-2921.5"/>
<text text-anchor="middle" x="7026" y="-3072.3" font-family="Times,serif" font-size="14.00">OAuth2Provider</text>
<polyline fill="none" stroke="black" points="6904,-3064.5 7148,-3064.5 "/>
<text text-anchor="start" x="6912" y="-3049.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="6912" y="-3034.3" font-family="Times,serif" font-size="14.00">base_url :character varying</text>
<text text-anchor="start" x="6912" y="-3019.3" font-family="Times,serif" font-size="14.00">token_endpoint :character varying</text>
<text text-anchor="start" x="6912" y="-3004.3" font-family="Times,serif" font-size="14.00">authorization_endpoint :character varying</text>
<text text-anchor="start" x="6912" y="-2989.3" font-family="Times,serif" font-size="14.00">client_id :character varying</text>
<text text-anchor="start" x="6912" y="-2974.3" font-family="Times,serif" font-size="14.00">client_secret :character varying</text>
<text text-anchor="start" x="6912" y="-2959.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="6912" y="-2944.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="6912" y="-2929.3" font-family="Times,serif" font-size="14.00">profile_url :character varying</text>
</g>
<!-- OAuth2Provider&#45;&gt;OAuth2Mapping -->
<g id="edge72" class="edge"><title>OAuth2Provider&#45;&gt;OAuth2Mapping</title>
<path fill="none" stroke="#6b3044" d="M7075,-2913.16C7075,-2855.17 7075,-2780.08 7075,-2721.65"/>
<ellipse fill="none" stroke="#6b3044" cx="7075" cy="-2917.31" rx="4" ry="4"/>
<polygon fill="#6b3044" stroke="#6b3044" points="7075,-2721.32 7079.5,-2711.32 7075,-2716.32 7075,-2711.32 7075,-2711.32 7075,-2711.32 7075,-2716.32 7070.5,-2711.32 7075,-2721.32 7075,-2721.32"/>
<g id="edge73" class="edge"><title>OAuth2Provider&#45;&gt;OAuth2Mapping</title>
<path fill="none" stroke="#fa7940" d="M7026,-2913.11C7026,-2857.44 7026,-2786 7026,-2728.69"/>
<ellipse fill="none" stroke="#fa7940" cx="7026" cy="-2917.31" rx="4" ry="4"/>
<polygon fill="#fa7940" stroke="#fa7940" points="7026,-2728.52 7030.5,-2718.52 7026,-2723.52 7026,-2718.52 7026,-2718.52 7026,-2718.52 7026,-2723.52 7021.5,-2718.52 7026,-2728.52 7026,-2728.52"/>
</g>
<!-- AuthProvider -->
<g id="node71" class="node"><title>AuthProvider</title>
<path fill="none" stroke="black" d="M7227,-2560C7227,-2560 7447,-2560 7447,-2560 7453,-2560 7459,-2566 7459,-2572 7459,-2572 7459,-2684 7459,-2684 7459,-2690 7453,-2696 7447,-2696 7447,-2696 7227,-2696 7227,-2696 7221,-2696 7215,-2690 7215,-2684 7215,-2684 7215,-2572 7215,-2572 7215,-2566 7221,-2560 7227,-2560"/>
<text text-anchor="middle" x="7337" y="-2680.8" font-family="Times,serif" font-size="14.00">AuthProvider</text>
<polyline fill="none" stroke="black" points="7215,-2673 7459,-2673 "/>
<text text-anchor="start" x="7223" y="-2657.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="7223" y="-2642.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="7223" y="-2627.8" font-family="Times,serif" font-size="14.00">status :character varying</text>
<text text-anchor="start" x="7223" y="-2612.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="7223" y="-2597.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="7223" y="-2582.8" font-family="Times,serif" font-size="14.00">providable_type :character varying</text>
<text text-anchor="start" x="7223" y="-2567.8" font-family="Times,serif" font-size="14.00">providable_id :integer</text>
<path fill="none" stroke="black" d="M7178,-2560C7178,-2560 7398,-2560 7398,-2560 7404,-2560 7410,-2566 7410,-2572 7410,-2572 7410,-2684 7410,-2684 7410,-2690 7404,-2696 7398,-2696 7398,-2696 7178,-2696 7178,-2696 7172,-2696 7166,-2690 7166,-2684 7166,-2684 7166,-2572 7166,-2572 7166,-2566 7172,-2560 7178,-2560"/>
<text text-anchor="middle" x="7288" y="-2680.8" font-family="Times,serif" font-size="14.00">AuthProvider</text>
<polyline fill="none" stroke="black" points="7166,-2673 7410,-2673 "/>
<text text-anchor="start" x="7174" y="-2657.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="7174" y="-2642.8" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="7174" y="-2627.8" font-family="Times,serif" font-size="14.00">status :character varying</text>
<text text-anchor="start" x="7174" y="-2612.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="7174" y="-2597.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="7174" y="-2582.8" font-family="Times,serif" font-size="14.00">providable_type :character varying</text>
<text text-anchor="start" x="7174" y="-2567.8" font-family="Times,serif" font-size="14.00">providable_id :integer</text>
</g>
<!-- OAuth2Provider&#45;&gt;AuthProvider -->
<g id="edge71" class="edge"><title>OAuth2Provider&#45;&gt;AuthProvider</title>
<path fill="none" stroke="#c79750" d="M7178.87,-2915.43C7188.55,-2905.3 7197.79,-2894.73 7206,-2884 7248.6,-2828.31 7283.98,-2756.69 7307.19,-2703.54"/>
<ellipse fill="none" stroke="#c79750" cx="7175.91" cy="-2918.48" rx="4.00002" ry="4.00002"/>
<ellipse fill="#c79750" stroke="#c79750" cx="7308.8" cy="-2699.84" rx="4.00002" ry="4.00002"/>
<g id="edge72" class="edge"><title>OAuth2Provider&#45;&gt;AuthProvider</title>
<path fill="none" stroke="#67e662" d="M7129.87,-2915.43C7139.55,-2905.3 7148.79,-2894.73 7157,-2884 7199.6,-2828.31 7234.98,-2756.69 7258.19,-2703.54"/>
<ellipse fill="none" stroke="#67e662" cx="7126.91" cy="-2918.48" rx="4.00002" ry="4.00002"/>
<ellipse fill="#67e662" stroke="#67e662" cx="7259.8" cy="-2699.84" rx="4.00002" ry="4.00002"/>
</g>
<!-- Asset -->
<g id="node50" class="node"><title>Asset</title>
<path fill="none" stroke="black" d="M7489,-2936.5C7489,-2936.5 7709,-2936.5 7709,-2936.5 7715,-2936.5 7721,-2942.5 7721,-2948.5 7721,-2948.5 7721,-3060.5 7721,-3060.5 7721,-3066.5 7715,-3072.5 7709,-3072.5 7709,-3072.5 7489,-3072.5 7489,-3072.5 7483,-3072.5 7477,-3066.5 7477,-3060.5 7477,-3060.5 7477,-2948.5 7477,-2948.5 7477,-2942.5 7483,-2936.5 7489,-2936.5"/>
<text text-anchor="middle" x="7599" y="-3057.3" font-family="Times,serif" font-size="14.00">Asset</text>
<polyline fill="none" stroke="black" points="7477,-3049.5 7721,-3049.5 "/>
<text text-anchor="start" x="7485" y="-3034.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="7485" y="-3019.3" font-family="Times,serif" font-size="14.00">viewable_id :integer</text>
<text text-anchor="start" x="7485" y="-3004.3" font-family="Times,serif" font-size="14.00">viewable_type :character varying(255)</text>
<text text-anchor="start" x="7485" y="-2989.3" font-family="Times,serif" font-size="14.00">attachment :character varying(255)</text>
<text text-anchor="start" x="7485" y="-2974.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="7485" y="-2959.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="7485" y="-2944.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M7440,-2936.5C7440,-2936.5 7660,-2936.5 7660,-2936.5 7666,-2936.5 7672,-2942.5 7672,-2948.5 7672,-2948.5 7672,-3060.5 7672,-3060.5 7672,-3066.5 7666,-3072.5 7660,-3072.5 7660,-3072.5 7440,-3072.5 7440,-3072.5 7434,-3072.5 7428,-3066.5 7428,-3060.5 7428,-3060.5 7428,-2948.5 7428,-2948.5 7428,-2942.5 7434,-2936.5 7440,-2936.5"/>
<text text-anchor="middle" x="7550" y="-3057.3" font-family="Times,serif" font-size="14.00">Asset</text>
<polyline fill="none" stroke="black" points="7428,-3049.5 7672,-3049.5 "/>
<text text-anchor="start" x="7436" y="-3034.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="7436" y="-3019.3" font-family="Times,serif" font-size="14.00">viewable_id :integer</text>
<text text-anchor="start" x="7436" y="-3004.3" font-family="Times,serif" font-size="14.00">viewable_type :character varying(255)</text>
<text text-anchor="start" x="7436" y="-2989.3" font-family="Times,serif" font-size="14.00">attachment :character varying(255)</text>
<text text-anchor="start" x="7436" y="-2974.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="7436" y="-2959.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="7436" y="-2944.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Project::OpenlabSync -->
<g id="node51" class="node"><title>Project::OpenlabSync</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="7874.5,-3022.5 7739.5,-3022.5 7739.5,-2986.5 7874.5,-2986.5 7874.5,-3022.5"/>
<text text-anchor="middle" x="7807" y="-3000.8" font-family="Times,serif" font-size="14.00">Project::OpenlabSync</text>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="7825.5,-3022.5 7690.5,-3022.5 7690.5,-2986.5 7825.5,-2986.5 7825.5,-3022.5"/>
<text text-anchor="middle" x="7758" y="-3000.8" font-family="Times,serif" font-size="14.00">Project::OpenlabSync</text>
</g>
<!-- DatabaseProvider -->
<g id="node52" class="node"><title>DatabaseProvider</title>
<path fill="none" stroke="black" d="M7227,-2966.5C7227,-2966.5 7447,-2966.5 7447,-2966.5 7453,-2966.5 7459,-2972.5 7459,-2978.5 7459,-2978.5 7459,-3030.5 7459,-3030.5 7459,-3036.5 7453,-3042.5 7447,-3042.5 7447,-3042.5 7227,-3042.5 7227,-3042.5 7221,-3042.5 7215,-3036.5 7215,-3030.5 7215,-3030.5 7215,-2978.5 7215,-2978.5 7215,-2972.5 7221,-2966.5 7227,-2966.5"/>
<text text-anchor="middle" x="7337" y="-3027.3" font-family="Times,serif" font-size="14.00">DatabaseProvider</text>
<polyline fill="none" stroke="black" points="7215,-3019.5 7459,-3019.5 "/>
<text text-anchor="start" x="7223" y="-3004.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="7223" y="-2989.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="7223" y="-2974.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M7178,-2966.5C7178,-2966.5 7398,-2966.5 7398,-2966.5 7404,-2966.5 7410,-2972.5 7410,-2978.5 7410,-2978.5 7410,-3030.5 7410,-3030.5 7410,-3036.5 7404,-3042.5 7398,-3042.5 7398,-3042.5 7178,-3042.5 7178,-3042.5 7172,-3042.5 7166,-3036.5 7166,-3030.5 7166,-3030.5 7166,-2978.5 7166,-2978.5 7166,-2972.5 7172,-2966.5 7178,-2966.5"/>
<text text-anchor="middle" x="7288" y="-3027.3" font-family="Times,serif" font-size="14.00">DatabaseProvider</text>
<polyline fill="none" stroke="black" points="7166,-3019.5 7410,-3019.5 "/>
<text text-anchor="start" x="7174" y="-3004.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="7174" y="-2989.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="7174" y="-2974.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- DatabaseProvider&#45;&gt;AuthProvider -->
<g id="edge73" class="edge"><title>DatabaseProvider&#45;&gt;AuthProvider</title>
<path fill="none" stroke="#ca673c" d="M7337,-2958.16C7337,-2895.19 7337,-2780.44 7337,-2704.45"/>
<ellipse fill="none" stroke="#ca673c" cx="7337" cy="-2962.22" rx="4" ry="4"/>
<ellipse fill="#ca673c" stroke="#ca673c" cx="7337" cy="-2700.3" rx="4" ry="4"/>
<g id="edge74" class="edge"><title>DatabaseProvider&#45;&gt;AuthProvider</title>
<path fill="none" stroke="#0aea59" d="M7288,-2958.16C7288,-2895.19 7288,-2780.44 7288,-2704.45"/>
<ellipse fill="none" stroke="#0aea59" cx="7288" cy="-2962.22" rx="4" ry="4"/>
<ellipse fill="#0aea59" stroke="#0aea59" cx="7288" cy="-2700.3" rx="4" ry="4"/>
</g>
<!-- Availability&#45;&gt;AvailabilityTag -->
<g id="edge81" class="edge"><title>Availability&#45;&gt;AvailabilityTag</title>
<path fill="none" stroke="#a01a30" d="M4043.7,-2544.9C4090.74,-2439.66 4171.24,-2259.56 4213.4,-2165.24"/>
<ellipse fill="none" stroke="#a01a30" cx="4042.03" cy="-2548.62" rx="4.00002" ry="4.00002"/>
<polygon fill="#a01a30" stroke="#a01a30" points="4213.53,-2164.96 4221.72,-2157.67 4215.57,-2160.4 4217.61,-2155.83 4217.61,-2155.83 4217.61,-2155.83 4215.57,-2160.4 4213.5,-2153.99 4213.53,-2164.96 4213.53,-2164.96"/>
<g id="edge82" class="edge"><title>Availability&#45;&gt;AvailabilityTag</title>
<path fill="none" stroke="#b1e440" d="M4043.7,-2544.9C4090.74,-2439.66 4171.24,-2259.56 4213.4,-2165.24"/>
<ellipse fill="none" stroke="#b1e440" cx="4042.03" cy="-2548.62" rx="4.00002" ry="4.00002"/>
<polygon fill="#b1e440" stroke="#b1e440" points="4213.53,-2164.96 4221.72,-2157.67 4215.57,-2160.4 4217.61,-2155.83 4217.61,-2155.83 4217.61,-2155.83 4215.57,-2160.4 4213.5,-2153.99 4213.53,-2164.96 4213.53,-2164.96"/>
</g>
<!-- Availability&#45;&gt;Event -->
<g id="edge80" class="edge"><title>Availability&#45;&gt;Event</title>
<path fill="none" stroke="#c80500" d="M4113.39,-2547.23C4188.98,-2488.36 4291.03,-2404.32 4372,-2321 4403.82,-2288.26 4435.67,-2249.92 4463.17,-2214.63"/>
<ellipse fill="none" stroke="#c80500" cx="4109.78" cy="-2550.04" rx="4.00002" ry="4.00002"/>
<ellipse fill="#c80500" stroke="#c80500" cx="4465.8" cy="-2211.24" rx="4.00002" ry="4.00002"/>
<g id="edge81" class="edge"><title>Availability&#45;&gt;Event</title>
<path fill="none" stroke="#8ac918" d="M4071.16,-2546.09C4117.69,-2491.47 4184.58,-2420.71 4255,-2372 4301.65,-2339.73 4327.11,-2355.68 4372,-2321 4410,-2291.64 4444.4,-2252.05 4472.21,-2214.69"/>
<ellipse fill="none" stroke="#8ac918" cx="4068.46" cy="-2549.28" rx="4.00002" ry="4.00002"/>
<ellipse fill="#8ac918" stroke="#8ac918" cx="4474.6" cy="-2211.45" rx="4.00002" ry="4.00002"/>
</g>
<!-- Availability&#45;&gt;Training -->
<g id="edge77" class="edge"><title>Availability&#45;&gt;Training</title>
<path fill="none" stroke="#8b7905" d="M3934.11,-2544.91C3887.67,-2493.78 3825.44,-2427.43 3767,-2372 3750.53,-2356.37 3748.6,-2348.56 3728,-2339 3684.26,-2318.7 3665.21,-2340.27 3621,-2321 3546.42,-2288.5 3473.9,-2232.13 3420.94,-2184.92"/>
<polygon fill="#8b7905" stroke="#8b7905" points="3934.13,-2544.93 3937.52,-2555.36 3937.49,-2548.63 3940.85,-2552.34 3940.85,-2552.34 3940.85,-2552.34 3937.49,-2548.63 3944.18,-2549.31 3934.13,-2544.93 3934.13,-2544.93"/>
<polygon fill="#8b7905" stroke="#8b7905" points="3420.71,-2184.71 3416.28,-2174.67 3416.99,-2181.36 3413.28,-2178.02 3413.28,-2178.02 3413.28,-2178.02 3416.99,-2181.36 3410.27,-2181.37 3420.71,-2184.71 3420.71,-2184.71"/>
<g id="edge78" class="edge"><title>Availability&#45;&gt;Training</title>
<path fill="none" stroke="#1662e2" d="M3956.31,-2543.96C3920.95,-2490.55 3870.18,-2422.04 3814,-2372 3792.43,-2352.78 3785.32,-2348.4 3758,-2339 3699.93,-2319.01 3677.73,-2344.52 3621,-2321 3545.43,-2289.68 3472.55,-2232.82 3419.68,-2185.1"/>
<polygon fill="#1662e2" stroke="#1662e2" points="3956.36,-2544.03 3958.09,-2554.86 3959.11,-2548.21 3961.85,-2552.39 3961.85,-2552.39 3961.85,-2552.39 3959.11,-2548.21 3965.61,-2549.92 3956.36,-2544.03 3956.36,-2544.03"/>
<polygon fill="#1662e2" stroke="#1662e2" points="3419.42,-2184.86 3415.05,-2174.8 3415.72,-2181.5 3412.02,-2178.13 3412.02,-2178.13 3412.02,-2178.13 3415.72,-2181.5 3408.99,-2181.46 3419.42,-2184.86 3419.42,-2184.86"/>
</g>
<!-- Availability&#45;&gt;Reservation -->
<g id="edge79" class="edge"><title>Availability&#45;&gt;Reservation</title>
<path fill="none" stroke="#9b0026" d="M4012.19,-2542.1C4015.28,-2488.24 4018.97,-2417.05 4021,-2354 4034.36,-1938.64 4089.8,-1830.1 4029,-1419 4026.39,-1401.38 4022.1,-1382.93 4017.2,-1365.33"/>
<polygon fill="#9b0026" stroke="#9b0026" points="4012.18,-2542.31 4007.11,-2552.04 4011.89,-2547.3 4011.6,-2552.3 4011.6,-2552.3 4011.6,-2552.3 4011.89,-2547.3 4016.09,-2552.55 4012.18,-2542.31 4012.18,-2542.31"/>
<polygon fill="#9b0026" stroke="#9b0026" points="4017.18,-1365.25 4018.74,-1354.4 4015.8,-1360.45 4014.42,-1355.64 4014.42,-1355.64 4014.42,-1355.64 4015.8,-1360.45 4010.09,-1356.88 4017.18,-1365.25 4017.18,-1365.25"/>
<g id="edge80" class="edge"><title>Availability&#45;&gt;Reservation</title>
<path fill="none" stroke="#a5e52c" d="M4012.19,-2542.1C4015.28,-2488.24 4018.97,-2417.05 4021,-2354 4034.36,-1938.64 4089.8,-1830.1 4029,-1419 4026.39,-1401.38 4022.1,-1382.93 4017.2,-1365.33"/>
<polygon fill="#a5e52c" stroke="#a5e52c" points="4012.18,-2542.31 4007.11,-2552.04 4011.89,-2547.3 4011.6,-2552.3 4011.6,-2552.3 4011.6,-2552.3 4011.89,-2547.3 4016.09,-2552.55 4012.18,-2542.31 4012.18,-2542.31"/>
<polygon fill="#a5e52c" stroke="#a5e52c" points="4017.18,-1365.25 4018.74,-1354.4 4015.8,-1360.45 4014.42,-1355.64 4014.42,-1355.64 4014.42,-1355.64 4015.8,-1360.45 4010.09,-1356.88 4017.18,-1365.25 4017.18,-1365.25"/>
</g>
<!-- Slot -->
<g id="node63" class="node"><title>Slot</title>
@ -1442,10 +1463,10 @@
<text text-anchor="start" x="3969" y="-904.3" font-family="Times,serif" font-size="14.00">offered :boolean</text>
</g>
<!-- Availability&#45;&gt;Slot -->
<g id="edge78" class="edge"><title>Availability&#45;&gt;Slot</title>
<path fill="none" stroke="#25c429" d="M4020.92,-2544.25C4030.83,-2482.81 4043.79,-2396.87 4052,-2321 4096.07,-1913.5 4101.77,-1810.63 4116,-1401 4119.97,-1286.85 4127.73,-1257.62 4116,-1144 4114.61,-1130.51 4112.52,-1116.43 4110.07,-1102.56"/>
<ellipse fill="none" stroke="#25c429" cx="4020.24" cy="-2548.43" rx="4.00001" ry="4.00001"/>
<polygon fill="#25c429" stroke="#25c429" points="4110.03,-1102.34 4112.66,-1091.69 4109.13,-1097.42 4108.23,-1092.5 4108.23,-1092.5 4108.23,-1092.5 4109.13,-1097.42 4103.81,-1093.31 4110.03,-1102.34 4110.03,-1102.34"/>
<g id="edge79" class="edge"><title>Availability&#45;&gt;Slot</title>
<path fill="none" stroke="#0a851e" d="M4020.92,-2544.25C4030.83,-2482.81 4043.79,-2396.87 4052,-2321 4096.07,-1913.5 4101.77,-1810.63 4116,-1401 4119.97,-1286.85 4127.73,-1257.62 4116,-1144 4114.61,-1130.51 4112.52,-1116.43 4110.07,-1102.56"/>
<ellipse fill="none" stroke="#0a851e" cx="4020.24" cy="-2548.43" rx="4.00001" ry="4.00001"/>
<polygon fill="#0a851e" stroke="#0a851e" points="4110.03,-1102.34 4112.66,-1091.69 4109.13,-1097.42 4108.23,-1092.5 4108.23,-1092.5 4108.23,-1092.5 4109.13,-1097.42 4103.81,-1093.31 4110.03,-1102.34 4110.03,-1102.34"/>
</g>
<!-- MachinesAvailability -->
<g id="node68" class="node"><title>MachinesAvailability</title>
@ -1457,13 +1478,13 @@
<text text-anchor="start" x="3713" y="-1242.3" font-family="Times,serif" font-size="14.00">availability_id :integer</text>
</g>
<!-- Availability&#45;&gt;MachinesAvailability -->
<g id="edge74" class="edge"><title>Availability&#45;&gt;MachinesAvailability</title>
<path fill="none" stroke="#bc16f0" d="M4009.91,-2544.18C4015.79,-2357.12 4025.9,-1906.77 3993,-1759 3954.83,-1587.58 3853.16,-1403.07 3803.33,-1319.4"/>
<ellipse fill="none" stroke="#bc16f0" cx="4009.77" cy="-2548.35" rx="4" ry="4"/>
<polygon fill="#bc16f0" stroke="#bc16f0" points="3803.24,-1319.24 3801.96,-1308.35 3800.67,-1314.95 3798.1,-1310.67 3798.1,-1310.67 3798.1,-1310.67 3800.67,-1314.95 3794.24,-1312.98 3803.24,-1319.24 3803.24,-1319.24"/>
<g id="edge75" class="edge"><title>Availability&#45;&gt;MachinesAvailability</title>
<path fill="none" stroke="#296f1a" d="M4009.91,-2544.18C4015.79,-2357.12 4025.9,-1906.77 3993,-1759 3954.83,-1587.58 3853.16,-1403.07 3803.33,-1319.4"/>
<ellipse fill="none" stroke="#296f1a" cx="4009.77" cy="-2548.35" rx="4" ry="4"/>
<polygon fill="#296f1a" stroke="#296f1a" points="3803.24,-1319.24 3801.96,-1308.35 3800.67,-1314.95 3798.1,-1310.67 3798.1,-1310.67 3798.1,-1310.67 3800.67,-1314.95 3794.24,-1312.98 3803.24,-1319.24 3803.24,-1319.24"/>
</g>
<!-- TrainingsAvailability -->
<g id="node79" class="node"><title>TrainingsAvailability</title>
<g id="node80" class="node"><title>TrainingsAvailability</title>
<path fill="none" stroke="black" d="M3641,-1619.5C3641,-1619.5 3861,-1619.5 3861,-1619.5 3867,-1619.5 3873,-1625.5 3873,-1631.5 3873,-1631.5 3873,-1713.5 3873,-1713.5 3873,-1719.5 3867,-1725.5 3861,-1725.5 3861,-1725.5 3641,-1725.5 3641,-1725.5 3635,-1725.5 3629,-1719.5 3629,-1713.5 3629,-1713.5 3629,-1631.5 3629,-1631.5 3629,-1625.5 3635,-1619.5 3641,-1619.5"/>
<text text-anchor="middle" x="3751" y="-1710.3" font-family="Times,serif" font-size="14.00">TrainingsAvailability</text>
<polyline fill="none" stroke="black" points="3629,-1702.5 3873,-1702.5 "/>
@ -1474,97 +1495,97 @@
<text text-anchor="start" x="3637" y="-1627.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Availability&#45;&gt;TrainingsAvailability -->
<g id="edge76" class="edge"><title>Availability&#45;&gt;TrainingsAvailability</title>
<path fill="none" stroke="#217e7a" d="M3984.82,-2544.38C3934.45,-2356.76 3812.35,-1902.02 3767.71,-1735.73"/>
<ellipse fill="none" stroke="#217e7a" cx="3985.87" cy="-2548.32" rx="4.00001" ry="4.00001"/>
<polygon fill="#217e7a" stroke="#217e7a" points="3767.6,-1735.33 3769.35,-1724.5 3766.3,-1730.5 3765.01,-1725.67 3765.01,-1725.67 3765.01,-1725.67 3766.3,-1730.5 3760.66,-1726.84 3767.6,-1735.33 3767.6,-1735.33"/>
<g id="edge77" class="edge"><title>Availability&#45;&gt;TrainingsAvailability</title>
<path fill="none" stroke="#3c23a0" d="M3984.82,-2544.38C3934.45,-2356.76 3812.35,-1902.02 3767.71,-1735.73"/>
<ellipse fill="none" stroke="#3c23a0" cx="3985.87" cy="-2548.32" rx="4.00001" ry="4.00001"/>
<polygon fill="#3c23a0" stroke="#3c23a0" points="3767.6,-1735.33 3769.35,-1724.5 3766.3,-1730.5 3765.01,-1725.67 3765.01,-1725.67 3765.01,-1725.67 3766.3,-1730.5 3760.66,-1726.84 3767.6,-1735.33 3767.6,-1735.33"/>
</g>
<!-- Availability&#45;&gt;Machine -->
<g id="edge75" class="edge"><title>Availability&#45;&gt;Machine</title>
<path fill="none" stroke="#f658b9" d="M3950.53,-2544.11C3835.21,-2375.65 3574.63,-1999.5 3469,-1884 3424.06,-1834.86 3368.3,-1785.7 3321.64,-1747.26"/>
<polygon fill="#f658b9" stroke="#f658b9" points="3950.6,-2544.2 3952.54,-2555 3953.43,-2548.33 3956.25,-2552.46 3956.25,-2552.46 3956.25,-2552.46 3953.43,-2548.33 3959.96,-2549.92 3950.6,-2544.2 3950.6,-2544.2"/>
<polygon fill="#f658b9" stroke="#f658b9" points="3321.37,-1747.04 3316.49,-1737.22 3317.5,-1743.87 3313.63,-1740.7 3313.63,-1740.7 3313.63,-1740.7 3317.5,-1743.87 3310.78,-1744.18 3321.37,-1747.04 3321.37,-1747.04"/>
<g id="edge76" class="edge"><title>Availability&#45;&gt;Machine</title>
<path fill="none" stroke="#6450db" d="M3950.53,-2544.11C3835.21,-2375.65 3574.63,-1999.5 3469,-1884 3424.06,-1834.86 3368.3,-1785.7 3321.64,-1747.26"/>
<polygon fill="#6450db" stroke="#6450db" points="3950.6,-2544.2 3952.54,-2555 3953.43,-2548.33 3956.25,-2552.46 3956.25,-2552.46 3956.25,-2552.46 3953.43,-2548.33 3959.96,-2549.92 3950.6,-2544.2 3950.6,-2544.2"/>
<polygon fill="#6450db" stroke="#6450db" points="3321.37,-1747.04 3316.49,-1737.22 3317.5,-1743.87 3313.63,-1740.7 3313.63,-1740.7 3313.63,-1740.7 3317.5,-1743.87 3310.78,-1744.18 3321.37,-1747.04 3321.37,-1747.04"/>
</g>
<!-- Subscription&#45;&gt;Invoice -->
<g id="edge82" class="edge"><title>Subscription&#45;&gt;Invoice</title>
<path fill="none" stroke="#eaa478" d="M2227.83,-911.195C2198.95,-816.993 2169.4,-662.186 2241,-557 2325.06,-433.515 2497.77,-385.893 2618.81,-367.528"/>
<ellipse fill="none" stroke="#eaa478" cx="2229.07" cy="-915.175" rx="4.00001" ry="4.00001"/>
<polygon fill="#eaa478" stroke="#eaa478" points="2619,-367.5 2629.55,-370.5 2623.95,-366.774 2628.9,-366.048 2628.9,-366.048 2628.9,-366.048 2623.95,-366.774 2628.24,-361.595 2619,-367.5 2619,-367.5"/>
<g id="edge83" class="edge"><title>Subscription&#45;&gt;Invoice</title>
<path fill="none" stroke="#415b2a" d="M2207.62,-911.065C2179.79,-817.425 2151.5,-663.798 2220,-557 2286.95,-452.615 2423.2,-401.725 2526.06,-377.377"/>
<ellipse fill="none" stroke="#415b2a" cx="2208.81" cy="-914.989" rx="4.00001" ry="4.00001"/>
<polygon fill="#415b2a" stroke="#415b2a" points="2526.16,-377.353 2536.92,-379.487 2531.03,-376.228 2535.91,-375.102 2535.91,-375.102 2535.91,-375.102 2531.03,-376.228 2534.89,-370.718 2526.16,-377.353 2526.16,-377.353"/>
</g>
<!-- Subscription&#45;&gt;OfferDay -->
<g id="edge83" class="edge"><title>Subscription&#45;&gt;OfferDay</title>
<path fill="none" stroke="#8bf4c3" d="M2290.96,-911.253C2307.83,-869.147 2328.14,-818.454 2344.21,-778.353"/>
<ellipse fill="none" stroke="#8bf4c3" cx="2289.44" cy="-915.038" rx="4.00001" ry="4.00001"/>
<polygon fill="#8bf4c3" stroke="#8bf4c3" points="2344.27,-778.205 2352.17,-770.596 2346.13,-773.564 2347.99,-768.922 2347.99,-768.922 2347.99,-768.922 2346.13,-773.564 2343.81,-767.249 2344.27,-778.205 2344.27,-778.205"/>
<g id="edge84" class="edge"><title>Subscription&#45;&gt;OfferDay</title>
<path fill="none" stroke="#138393" d="M2269.96,-911.253C2286.83,-869.147 2307.14,-818.454 2323.21,-778.353"/>
<ellipse fill="none" stroke="#138393" cx="2268.44" cy="-915.038" rx="4.00001" ry="4.00001"/>
<polygon fill="#138393" stroke="#138393" points="2323.27,-778.205 2331.17,-770.596 2325.13,-773.564 2326.99,-768.922 2326.99,-768.922 2326.99,-768.922 2325.13,-773.564 2322.81,-767.249 2323.27,-778.205 2323.27,-778.205"/>
</g>
<!-- Training&#45;&gt;TrainingImage -->
<g id="edge84" class="edge"><title>Training&#45;&gt;TrainingImage</title>
<path fill="none" stroke="#c51060" d="M3367.02,-2019.24C3394.67,-1940.87 3435.93,-1823.92 3462.66,-1748.17"/>
<ellipse fill="none" stroke="#c51060" cx="3365.63" cy="-2023.18" rx="4.00001" ry="4.00001"/>
<ellipse fill="#c51060" stroke="#c51060" cx="3464.03" cy="-1744.29" rx="4.00001" ry="4.00001"/>
<g id="edge85" class="edge"><title>Training&#45;&gt;TrainingImage</title>
<path fill="none" stroke="#25c9d2" d="M3367.02,-2019.24C3394.67,-1940.87 3435.93,-1823.92 3462.66,-1748.17"/>
<ellipse fill="none" stroke="#25c9d2" cx="3365.63" cy="-2023.18" rx="4.00001" ry="4.00001"/>
<ellipse fill="#25c9d2" stroke="#25c9d2" cx="3464.03" cy="-1744.29" rx="4.00001" ry="4.00001"/>
</g>
<!-- Training&#45;&gt;TrainingsPricing -->
<g id="edge89" class="edge"><title>Training&#45;&gt;TrainingsPricing</title>
<path fill="none" stroke="#d84593" d="M3307.99,-2019.22C3286.15,-1971.59 3251.63,-1915.07 3202,-1884 3170.18,-1864.08 3062.45,-1890.5 3034,-1866 2996.75,-1833.93 3033.67,-1799.63 3006,-1759 3001.57,-1752.49 2996.47,-1746.3 2990.94,-1740.44"/>
<ellipse fill="none" stroke="#d84593" cx="3309.75" cy="-2023.14" rx="4.00002" ry="4.00002"/>
<polygon fill="#d84593" stroke="#d84593" points="2990.78,-1740.28 2986.91,-1730.02 2987.25,-1736.74 2983.72,-1733.2 2983.72,-1733.2 2983.72,-1733.2 2987.25,-1736.74 2980.53,-1736.38 2990.78,-1740.28 2990.78,-1740.28"/>
<g id="edge90" class="edge"><title>Training&#45;&gt;TrainingsPricing</title>
<path fill="none" stroke="#6a533c" d="M3307.99,-2019.22C3286.15,-1971.59 3251.63,-1915.07 3202,-1884 3170.18,-1864.08 3062.45,-1890.5 3034,-1866 2996.75,-1833.93 3033.67,-1799.63 3006,-1759 3001.57,-1752.49 2996.47,-1746.3 2990.94,-1740.44"/>
<ellipse fill="none" stroke="#6a533c" cx="3309.75" cy="-2023.14" rx="4.00002" ry="4.00002"/>
<polygon fill="#6a533c" stroke="#6a533c" points="2990.78,-1740.28 2986.91,-1730.02 2987.25,-1736.74 2983.72,-1733.2 2983.72,-1733.2 2983.72,-1733.2 2987.25,-1736.74 2980.53,-1736.38 2990.78,-1740.28 2990.78,-1740.28"/>
</g>
<!-- Training&#45;&gt;Plan -->
<g id="edge91" class="edge"><title>Training&#45;&gt;Plan</title>
<path fill="none" stroke="#b49b52" d="M3288.06,-2018.23C3262.98,-1977.3 3231.68,-1927.54 3202,-1884 3157.44,-1818.63 3131.9,-1811.5 3096,-1741 3067.04,-1684.13 3073.93,-1664.29 3053,-1604 3030.73,-1539.85 3004.19,-1469.45 2981.22,-1410.17"/>
<polygon fill="#b49b52" stroke="#b49b52" points="3288.1,-2018.29 3289.48,-2029.17 3290.71,-2022.56 3293.32,-2026.82 3293.32,-2026.82 3293.32,-2026.82 3290.71,-2022.56 3297.16,-2024.48 3288.1,-2018.29 3288.1,-2018.29"/>
<polygon fill="#b49b52" stroke="#b49b52" points="2981.18,-1410.08 2981.76,-1399.13 2979.37,-1405.42 2977.56,-1400.76 2977.56,-1400.76 2977.56,-1400.76 2979.37,-1405.42 2973.37,-1402.39 2981.18,-1410.08 2981.18,-1410.08"/>
<g id="edge92" class="edge"><title>Training&#45;&gt;Plan</title>
<path fill="none" stroke="#733a25" d="M3288.06,-2018.23C3262.98,-1977.3 3231.68,-1927.54 3202,-1884 3157.44,-1818.63 3131.9,-1811.5 3096,-1741 3067.04,-1684.13 3073.93,-1664.29 3053,-1604 3030.73,-1539.85 3004.19,-1469.45 2981.22,-1410.17"/>
<polygon fill="#733a25" stroke="#733a25" points="3288.1,-2018.29 3289.48,-2029.17 3290.71,-2022.56 3293.32,-2026.82 3293.32,-2026.82 3293.32,-2026.82 3290.71,-2022.56 3297.16,-2024.48 3288.1,-2018.29 3288.1,-2018.29"/>
<polygon fill="#733a25" stroke="#733a25" points="2981.18,-1410.08 2981.76,-1399.13 2979.37,-1405.42 2977.56,-1400.76 2977.56,-1400.76 2977.56,-1400.76 2979.37,-1405.42 2973.37,-1402.39 2981.18,-1410.08 2981.18,-1410.08"/>
</g>
<!-- Training&#45;&gt;Credit -->
<g id="edge90" class="edge"><title>Training&#45;&gt;Credit</title>
<path fill="none" stroke="#f2e816" d="M3305.49,-2019.54C3282.66,-1972.61 3247.48,-1916.72 3199,-1884 3163.02,-1859.71 3136.54,-1893.56 3103,-1866 3056.77,-1828.01 3071.16,-1798.01 3053,-1741 3033.99,-1681.33 3060.64,-1651.65 3020,-1604 3010.49,-1592.85 2541.13,-1413.2 2533,-1401 2467.14,-1302.2 2508.79,-1159.22 2545.51,-1072.09"/>
<ellipse fill="none" stroke="#f2e816" cx="3307.33" cy="-2023.38" rx="4.00002" ry="4.00002"/>
<polygon fill="#f2e816" stroke="#f2e816" points="2545.56,-1071.98 2553.64,-1064.57 2547.53,-1067.39 2549.5,-1062.79 2549.5,-1062.79 2549.5,-1062.79 2547.53,-1067.39 2545.37,-1061.02 2545.56,-1071.98 2545.56,-1071.98"/>
<g id="edge91" class="edge"><title>Training&#45;&gt;Credit</title>
<path fill="none" stroke="#f12079" d="M3305.49,-2019.54C3282.66,-1972.61 3247.48,-1916.72 3199,-1884 3163.02,-1859.71 3136.54,-1893.56 3103,-1866 3056.77,-1828.01 3071.16,-1798.01 3053,-1741 3033.99,-1681.33 3060.64,-1651.65 3020,-1604 3010.49,-1592.85 2541.13,-1413.2 2533,-1401 2467.14,-1302.2 2508.79,-1159.22 2545.51,-1072.09"/>
<ellipse fill="none" stroke="#f12079" cx="3307.33" cy="-2023.38" rx="4.00002" ry="4.00002"/>
<polygon fill="#f12079" stroke="#f12079" points="2545.56,-1071.98 2553.64,-1064.57 2547.53,-1067.39 2549.5,-1062.79 2549.5,-1062.79 2549.5,-1062.79 2547.53,-1067.39 2545.37,-1061.02 2545.56,-1071.98 2545.56,-1071.98"/>
</g>
<!-- Training&#45;&gt;Reservation -->
<g id="edge87" class="edge"><title>Training&#45;&gt;Reservation</title>
<path fill="none" stroke="#71f89e" d="M3458.79,-2022.25C3617.97,-1917.7 3878.44,-1746.19 3882,-1741 3959.6,-1627.86 3979.95,-1466.24 3984.62,-1365.71"/>
<ellipse fill="none" stroke="#71f89e" cx="3455.1" cy="-2024.67" rx="4.00002" ry="4.00002"/>
<polygon fill="#71f89e" stroke="#71f89e" points="3984.62,-1365.56 3989.54,-1355.76 3984.83,-1360.56 3985.05,-1355.57 3985.05,-1355.57 3985.05,-1355.57 3984.83,-1360.56 3980.55,-1355.38 3984.62,-1365.56 3984.62,-1365.56"/>
<g id="edge88" class="edge"><title>Training&#45;&gt;Reservation</title>
<path fill="none" stroke="#0e20e9" d="M3458.79,-2022.25C3617.97,-1917.7 3878.44,-1746.19 3882,-1741 3959.6,-1627.86 3979.95,-1466.24 3984.62,-1365.71"/>
<ellipse fill="none" stroke="#0e20e9" cx="3455.1" cy="-2024.67" rx="4.00002" ry="4.00002"/>
<polygon fill="#0e20e9" stroke="#0e20e9" points="3984.62,-1365.56 3989.54,-1355.76 3984.83,-1360.56 3985.05,-1355.57 3985.05,-1355.57 3985.05,-1355.57 3984.83,-1360.56 3980.55,-1355.38 3984.62,-1365.56 3984.62,-1365.56"/>
</g>
<!-- Training&#45;&gt;UserTraining -->
<g id="edge88" class="edge"><title>Training&#45;&gt;UserTraining</title>
<path fill="none" stroke="#adf959" d="M3296.42,-2019.76C3267.5,-1971.83 3224.23,-1914.81 3169,-1884 3103.8,-1847.63 3071.23,-1893.93 3002,-1866 2930.03,-1836.96 2935.06,-1790.21 2864,-1759 2820.25,-1739.78 2804,-1753.93 2758,-1741 2745.64,-1737.52 2732.94,-1733.45 2720.33,-1729.06"/>
<ellipse fill="none" stroke="#adf959" cx="3298.54" cy="-2023.32" rx="4.00002" ry="4.00002"/>
<polygon fill="#adf959" stroke="#adf959" points="2720.13,-1728.99 2712.22,-1721.4 2715.42,-1727.31 2710.71,-1725.64 2710.71,-1725.64 2710.71,-1725.64 2715.42,-1727.31 2709.2,-1729.88 2720.13,-1728.99 2720.13,-1728.99"/>
<g id="edge89" class="edge"><title>Training&#45;&gt;UserTraining</title>
<path fill="none" stroke="#c40e86" d="M3296.42,-2019.76C3267.5,-1971.83 3224.23,-1914.81 3169,-1884 3103.8,-1847.63 3071.23,-1893.93 3002,-1866 2930.03,-1836.96 2935.06,-1790.21 2864,-1759 2820.25,-1739.78 2804,-1753.93 2758,-1741 2745.64,-1737.52 2732.94,-1733.45 2720.33,-1729.06"/>
<ellipse fill="none" stroke="#c40e86" cx="3298.54" cy="-2023.32" rx="4.00002" ry="4.00002"/>
<polygon fill="#c40e86" stroke="#c40e86" points="2720.13,-1728.99 2712.22,-1721.4 2715.42,-1727.31 2710.71,-1725.64 2710.71,-1725.64 2710.71,-1725.64 2715.42,-1727.31 2709.2,-1729.88 2720.13,-1728.99 2720.13,-1728.99"/>
</g>
<!-- Training&#45;&gt;TrainingsAvailability -->
<g id="edge86" class="edge"><title>Training&#45;&gt;TrainingsAvailability</title>
<path fill="none" stroke="#7a3c62" d="M3415.62,-2021.06C3496.39,-1937.36 3620.98,-1808.24 3693.4,-1733.2"/>
<ellipse fill="none" stroke="#7a3c62" cx="3412.72" cy="-2024.07" rx="4.00002" ry="4.00002"/>
<polygon fill="#7a3c62" stroke="#7a3c62" points="3693.72,-1732.86 3703.91,-1728.78 3697.2,-1729.26 3700.67,-1725.66 3700.67,-1725.66 3700.67,-1725.66 3697.2,-1729.26 3697.43,-1722.54 3693.72,-1732.86 3693.72,-1732.86"/>
<g id="edge87" class="edge"><title>Training&#45;&gt;TrainingsAvailability</title>
<path fill="none" stroke="#5f0c7f" d="M3415.62,-2021.06C3496.39,-1937.36 3620.98,-1808.24 3693.4,-1733.2"/>
<ellipse fill="none" stroke="#5f0c7f" cx="3412.72" cy="-2024.07" rx="4.00002" ry="4.00002"/>
<polygon fill="#5f0c7f" stroke="#5f0c7f" points="3693.72,-1732.86 3703.91,-1728.78 3697.2,-1729.26 3700.67,-1725.66 3700.67,-1725.66 3700.67,-1725.66 3697.2,-1729.26 3697.43,-1722.54 3693.72,-1732.86 3693.72,-1732.86"/>
</g>
<!-- Training&#45;&gt;Machine -->
<g id="edge85" class="edge"><title>Training&#45;&gt;Machine</title>
<path fill="none" stroke="#8a2530" d="M3316.15,-2017.27C3296.03,-1939.69 3266.43,-1825.56 3246.94,-1750.4"/>
<polygon fill="#8a2530" stroke="#8a2530" points="3316.15,-2017.27 3314.31,-2028.08 3317.41,-2022.11 3318.67,-2026.95 3318.67,-2026.95 3318.67,-2026.95 3317.41,-2022.11 3323.02,-2025.82 3316.15,-2017.27 3316.15,-2017.27"/>
<polygon fill="#8a2530" stroke="#8a2530" points="3246.89,-1750.19 3248.74,-1739.38 3245.64,-1745.35 3244.38,-1740.51 3244.38,-1740.51 3244.38,-1740.51 3245.64,-1745.35 3240.02,-1741.64 3246.89,-1750.19 3246.89,-1750.19"/>
<g id="edge86" class="edge"><title>Training&#45;&gt;Machine</title>
<path fill="none" stroke="#17a248" d="M3316.15,-2017.27C3296.03,-1939.69 3266.43,-1825.56 3246.94,-1750.4"/>
<polygon fill="#17a248" stroke="#17a248" points="3316.15,-2017.27 3314.31,-2028.08 3317.41,-2022.11 3318.67,-2026.95 3318.67,-2026.95 3318.67,-2026.95 3317.41,-2022.11 3323.02,-2025.82 3316.15,-2017.27 3316.15,-2017.27"/>
<polygon fill="#17a248" stroke="#17a248" points="3246.89,-1750.19 3248.74,-1739.38 3245.64,-1745.35 3244.38,-1740.51 3244.38,-1740.51 3244.38,-1740.51 3245.64,-1745.35 3240.02,-1741.64 3246.89,-1750.19 3246.89,-1750.19"/>
</g>
<!-- ProjectStep&#45;&gt;ProjectStepImage -->
<g id="edge92" class="edge"><title>ProjectStep&#45;&gt;ProjectStepImage</title>
<path fill="none" stroke="#6980ce" d="M1012,-1596.08C1012,-1525.1 1012,-1419.4 1012,-1348.54"/>
<ellipse fill="none" stroke="#6980ce" cx="1012" cy="-1600.43" rx="4" ry="4"/>
<ellipse fill="#6980ce" stroke="#6980ce" cx="1012" cy="-1344.51" rx="4" ry="4"/>
<g id="edge93" class="edge"><title>ProjectStep&#45;&gt;ProjectStepImage</title>
<path fill="none" stroke="#a38493" d="M1012,-1596.08C1012,-1525.1 1012,-1419.4 1012,-1348.54"/>
<ellipse fill="none" stroke="#a38493" cx="1012" cy="-1600.43" rx="4" ry="4"/>
<ellipse fill="#a38493" stroke="#a38493" cx="1012" cy="-1344.51" rx="4" ry="4"/>
</g>
<!-- Reservation&#45;&gt;Invoice -->
<g id="edge95" class="edge"><title>Reservation&#45;&gt;Invoice</title>
<path fill="none" stroke="#f804cf" d="M3908.48,-1183.54C3822.88,-1092.3 3674.96,-954.906 3514,-896 3405.83,-856.415 3092.47,-923.436 2997,-859 2880.33,-780.256 2816.94,-629.669 2783.88,-513.702"/>
<ellipse fill="none" stroke="#f804cf" cx="3911.3" cy="-1186.56" rx="4.00002" ry="4.00002"/>
<ellipse fill="#f804cf" stroke="#f804cf" cx="2782.73" cy="-509.615" rx="4.00001" ry="4.00001"/>
<g id="edge96" class="edge"><title>Reservation&#45;&gt;Invoice</title>
<path fill="none" stroke="#d14f9b" d="M3908.5,-1183.48C3822.92,-1092.2 3675.02,-954.754 3514,-896 3402.88,-855.453 3084.86,-919.14 2983,-859 2914.07,-818.299 2810.46,-644.553 2738.85,-512.554"/>
<ellipse fill="none" stroke="#d14f9b" cx="3911.32" cy="-1186.5" rx="4.00002" ry="4.00002"/>
<ellipse fill="#d14f9b" stroke="#d14f9b" cx="2736.94" cy="-509.027" rx="4.00002" ry="4.00002"/>
</g>
<!-- Reservation&#45;&gt;Slot -->
<g id="edge93" class="edge"><title>Reservation&#45;&gt;Slot</title>
<path fill="none" stroke="#b68c4c" d="M4017.47,-1181.89C4026.66,-1156.53 4036.75,-1128.68 4046.26,-1102.42"/>
<ellipse fill="none" stroke="#b68c4c" cx="4016.1" cy="-1185.68" rx="4.00001" ry="4.00001"/>
<polygon fill="#b68c4c" stroke="#b68c4c" points="4046.33,-1102.22 4053.97,-1094.35 4048.04,-1097.52 4049.74,-1092.82 4049.74,-1092.82 4049.74,-1092.82 4048.04,-1097.52 4045.51,-1091.28 4046.33,-1102.22 4046.33,-1102.22"/>
<g id="edge94" class="edge"><title>Reservation&#45;&gt;Slot</title>
<path fill="none" stroke="#1c1555" d="M4017.47,-1181.89C4026.66,-1156.53 4036.75,-1128.68 4046.26,-1102.42"/>
<ellipse fill="none" stroke="#1c1555" cx="4016.1" cy="-1185.68" rx="4.00001" ry="4.00001"/>
<polygon fill="#1c1555" stroke="#1c1555" points="4046.33,-1102.22 4053.97,-1094.35 4048.04,-1097.52 4049.74,-1092.82 4049.74,-1092.82 4049.74,-1092.82 4048.04,-1097.52 4045.51,-1091.28 4046.33,-1102.22 4046.33,-1102.22"/>
</g>
<!-- Ticket -->
<g id="node88" class="node"><title>Ticket</title>
<g id="node89" class="node"><title>Ticket</title>
<path fill="none" stroke="black" d="M4300,-934C4300,-934 4520,-934 4520,-934 4526,-934 4532,-940 4532,-946 4532,-946 4532,-1043 4532,-1043 4532,-1049 4526,-1055 4520,-1055 4520,-1055 4300,-1055 4300,-1055 4294,-1055 4288,-1049 4288,-1043 4288,-1043 4288,-946 4288,-946 4288,-940 4294,-934 4300,-934"/>
<text text-anchor="middle" x="4410" y="-1039.8" font-family="Times,serif" font-size="14.00">Ticket</text>
<polyline fill="none" stroke="black" points="4288,-1032 4532,-1032 "/>
@ -1576,155 +1597,155 @@
<text text-anchor="start" x="4296" y="-941.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Reservation&#45;&gt;Ticket -->
<g id="edge94" class="edge"><title>Reservation&#45;&gt;Ticket</title>
<path fill="none" stroke="#6f035f" d="M4113.81,-1187.85C4176.61,-1147.07 4251.01,-1098.75 4309.53,-1060.75"/>
<ellipse fill="none" stroke="#6f035f" cx="4110.43" cy="-1190.05" rx="4.00002" ry="4.00002"/>
<polygon fill="#6f035f" stroke="#6f035f" points="4309.66,-1060.66 4320.5,-1058.99 4313.85,-1057.94 4318.05,-1055.22 4318.05,-1055.22 4318.05,-1055.22 4313.85,-1057.94 4315.6,-1051.44 4309.66,-1060.66 4309.66,-1060.66"/>
<g id="edge95" class="edge"><title>Reservation&#45;&gt;Ticket</title>
<path fill="none" stroke="#1bcdd4" d="M4113.81,-1187.85C4176.61,-1147.07 4251.01,-1098.75 4309.53,-1060.75"/>
<ellipse fill="none" stroke="#1bcdd4" cx="4110.43" cy="-1190.05" rx="4.00002" ry="4.00002"/>
<polygon fill="#1bcdd4" stroke="#1bcdd4" points="4309.66,-1060.66 4320.5,-1058.99 4313.85,-1057.94 4318.05,-1055.22 4318.05,-1055.22 4318.05,-1055.22 4313.85,-1057.94 4315.6,-1051.44 4309.66,-1060.66 4309.66,-1060.66"/>
</g>
<!-- StatisticIndex&#45;&gt;StatisticType -->
<g id="edge96" class="edge"><title>StatisticIndex&#45;&gt;StatisticType</title>
<path fill="none" stroke="#ba8888" d="M5640.95,-2178.8C5651.06,-2275.11 5664.48,-2441.46 5670.32,-2542.16"/>
<ellipse fill="none" stroke="#ba8888" cx="5640.5" cy="-2174.54" rx="4" ry="4"/>
<polygon fill="#ba8888" stroke="#ba8888" points="5670.33,-2542.29 5666.41,-2552.53 5670.62,-2547.28 5670.9,-2552.27 5670.9,-2552.27 5670.9,-2552.27 5670.62,-2547.28 5675.39,-2552.02 5670.33,-2542.29 5670.33,-2542.29"/>
<g id="edge97" class="edge"><title>StatisticIndex&#45;&gt;StatisticType</title>
<path fill="none" stroke="#5d82c3" d="M5721.91,-2178.8C5724.29,-2275.11 5724.36,-2441.46 5722.13,-2542.16"/>
<ellipse fill="none" stroke="#5d82c3" cx="5721.8" cy="-2174.56" rx="4" ry="4"/>
<polygon fill="#5d82c3" stroke="#5d82c3" points="5722.13,-2542.28 5717.39,-2552.17 5722.01,-2547.27 5721.89,-2552.27 5721.89,-2552.27 5721.89,-2552.27 5722.01,-2547.27 5726.39,-2552.38 5722.13,-2542.28 5722.13,-2542.28"/>
</g>
<!-- StatisticIndex&#45;&gt;StatisticGraph -->
<g id="edge98" class="edge"><title>StatisticIndex&#45;&gt;StatisticGraph</title>
<path fill="none" stroke="#13cef3" d="M5584.54,-2027.24C5534.99,-1946.29 5456.41,-1817.92 5408.78,-1740.11"/>
<ellipse fill="none" stroke="#13cef3" cx="5586.69" cy="-2030.74" rx="4.00002" ry="4.00002"/>
<ellipse fill="#13cef3" stroke="#13cef3" cx="5406.64" cy="-1736.62" rx="4.00002" ry="4.00002"/>
<g id="edge99" class="edge"><title>StatisticIndex&#45;&gt;StatisticGraph</title>
<path fill="none" stroke="#92f2db" d="M5672.68,-2027.31C5647.42,-1985.19 5615.11,-1931.54 5586,-1884 5556.47,-1835.76 5522.74,-1781.59 5496.9,-1740.28"/>
<ellipse fill="none" stroke="#92f2db" cx="5674.77" cy="-2030.8" rx="4.00002" ry="4.00002"/>
<ellipse fill="#92f2db" stroke="#92f2db" cx="5494.62" cy="-1736.63" rx="4.00002" ry="4.00002"/>
</g>
<!-- StatisticField -->
<g id="node60" class="node"><title>StatisticField</title>
<path fill="none" stroke="black" d="M5520,-1604.5C5520,-1604.5 5740,-1604.5 5740,-1604.5 5746,-1604.5 5752,-1610.5 5752,-1616.5 5752,-1616.5 5752,-1728.5 5752,-1728.5 5752,-1734.5 5746,-1740.5 5740,-1740.5 5740,-1740.5 5520,-1740.5 5520,-1740.5 5514,-1740.5 5508,-1734.5 5508,-1728.5 5508,-1728.5 5508,-1616.5 5508,-1616.5 5508,-1610.5 5514,-1604.5 5520,-1604.5"/>
<text text-anchor="middle" x="5630" y="-1725.3" font-family="Times,serif" font-size="14.00">StatisticField</text>
<polyline fill="none" stroke="black" points="5508,-1717.5 5752,-1717.5 "/>
<text text-anchor="start" x="5516" y="-1702.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5516" y="-1687.3" font-family="Times,serif" font-size="14.00">statistic_index_id :integer</text>
<text text-anchor="start" x="5516" y="-1672.3" font-family="Times,serif" font-size="14.00">key :character varying(255)</text>
<text text-anchor="start" x="5516" y="-1657.3" font-family="Times,serif" font-size="14.00">label :character varying(255)</text>
<text text-anchor="start" x="5516" y="-1642.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5516" y="-1627.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="5516" y="-1612.3" font-family="Times,serif" font-size="14.00">data_type :character varying(255)</text>
<path fill="none" stroke="black" d="M5607,-1604.5C5607,-1604.5 5827,-1604.5 5827,-1604.5 5833,-1604.5 5839,-1610.5 5839,-1616.5 5839,-1616.5 5839,-1728.5 5839,-1728.5 5839,-1734.5 5833,-1740.5 5827,-1740.5 5827,-1740.5 5607,-1740.5 5607,-1740.5 5601,-1740.5 5595,-1734.5 5595,-1728.5 5595,-1728.5 5595,-1616.5 5595,-1616.5 5595,-1610.5 5601,-1604.5 5607,-1604.5"/>
<text text-anchor="middle" x="5717" y="-1725.3" font-family="Times,serif" font-size="14.00">StatisticField</text>
<polyline fill="none" stroke="black" points="5595,-1717.5 5839,-1717.5 "/>
<text text-anchor="start" x="5603" y="-1702.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="5603" y="-1687.3" font-family="Times,serif" font-size="14.00">statistic_index_id :integer</text>
<text text-anchor="start" x="5603" y="-1672.3" font-family="Times,serif" font-size="14.00">key :character varying(255)</text>
<text text-anchor="start" x="5603" y="-1657.3" font-family="Times,serif" font-size="14.00">label :character varying(255)</text>
<text text-anchor="start" x="5603" y="-1642.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="5603" y="-1627.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="5603" y="-1612.3" font-family="Times,serif" font-size="14.00">data_type :character varying(255)</text>
</g>
<!-- StatisticIndex&#45;&gt;StatisticField -->
<g id="edge97" class="edge"><title>StatisticIndex&#45;&gt;StatisticField</title>
<path fill="none" stroke="#b609b4" d="M5624.71,-2026C5622.78,-1948.69 5622.76,-1829.11 5624.66,-1751.06"/>
<ellipse fill="none" stroke="#b609b4" cx="5624.82" cy="-2030.16" rx="4" ry="4"/>
<polygon fill="#b609b4" stroke="#b609b4" points="5624.67,-1750.8 5629.42,-1740.92 5624.8,-1745.8 5624.93,-1740.81 5624.93,-1740.81 5624.93,-1740.81 5624.8,-1745.8 5620.43,-1740.69 5624.67,-1750.8 5624.67,-1750.8"/>
<g id="edge98" class="edge"><title>StatisticIndex&#45;&gt;StatisticField</title>
<path fill="none" stroke="#644b81" d="M5711.71,-2026C5709.78,-1948.69 5709.76,-1829.11 5711.66,-1751.06"/>
<ellipse fill="none" stroke="#644b81" cx="5711.82" cy="-2030.16" rx="4" ry="4"/>
<polygon fill="#644b81" stroke="#644b81" points="5711.67,-1750.8 5716.42,-1740.92 5711.8,-1745.8 5711.93,-1740.81 5711.93,-1740.81 5711.93,-1740.81 5711.8,-1745.8 5707.43,-1740.69 5711.67,-1750.8 5711.67,-1750.8"/>
</g>
<!-- StatisticField&#45;&gt;StatisticIndex -->
<g id="edge99" class="edge"><title>StatisticField&#45;&gt;StatisticIndex</title>
<path fill="none" stroke="#46ab7a" d="M5635.29,-1749.16C5637.24,-1827.15 5637.24,-1948.06 5635.29,-2026"/>
<ellipse fill="none" stroke="#46ab7a" cx="5635.18" cy="-1744.8" rx="4" ry="4"/>
<ellipse fill="#46ab7a" stroke="#46ab7a" cx="5635.18" cy="-2030.16" rx="4" ry="4"/>
<g id="edge100" class="edge"><title>StatisticField&#45;&gt;StatisticIndex</title>
<path fill="none" stroke="#056b79" d="M5722.29,-1749.16C5724.24,-1827.15 5724.24,-1948.06 5722.29,-2026"/>
<ellipse fill="none" stroke="#056b79" cx="5722.18" cy="-1744.8" rx="4" ry="4"/>
<ellipse fill="#056b79" stroke="#056b79" cx="5722.18" cy="-2030.16" rx="4" ry="4"/>
</g>
<!-- WalletTransaction&#45;&gt;Invoice -->
<g id="edge100" class="edge"><title>WalletTransaction&#45;&gt;Invoice</title>
<path fill="none" stroke="#d03759" d="M715.385,-1412.12C752.511,-1336.52 797,-1224.1 797,-1119.5 797,-1119.5 797,-1119.5 797,-707 797,-521.206 2183.22,-399.382 2620.5,-365.575"/>
<ellipse fill="none" stroke="#d03759" cx="713.594" cy="-1415.73" rx="4.00002" ry="4.00002"/>
<ellipse fill="#d03759" stroke="#d03759" cx="2624.78" cy="-365.245" rx="4" ry="4"/>
<g id="edge101" class="edge"><title>WalletTransaction&#45;&gt;Invoice</title>
<path fill="none" stroke="#e19f5e" d="M714.385,-1412.12C751.511,-1336.52 796,-1224.1 796,-1119.5 796,-1119.5 796,-1119.5 796,-707 796,-530.491 2104.81,-403.231 2527.83,-366.708"/>
<ellipse fill="none" stroke="#e19f5e" cx="712.594" cy="-1415.73" rx="4.00002" ry="4.00002"/>
<ellipse fill="#e19f5e" stroke="#e19f5e" cx="2531.84" cy="-366.363" rx="4" ry="4"/>
</g>
<!-- EventPriceCategory&#45;&gt;Ticket -->
<g id="edge101" class="edge"><title>EventPriceCategory&#45;&gt;Ticket</title>
<path fill="none" stroke="#1d0cb2" d="M4626.78,-1206.17C4582.23,-1162.88 4523.94,-1106.23 4479.03,-1062.58"/>
<ellipse fill="none" stroke="#1d0cb2" cx="4629.86" cy="-1209.16" rx="4.00002" ry="4.00002"/>
<polygon fill="#1d0cb2" stroke="#1d0cb2" points="4478.83,-1062.39 4474.79,-1052.19 4475.24,-1058.9 4471.65,-1055.42 4471.65,-1055.42 4471.65,-1055.42 4475.24,-1058.9 4468.52,-1058.64 4478.83,-1062.39 4478.83,-1062.39"/>
<g id="edge102" class="edge"><title>EventPriceCategory&#45;&gt;Ticket</title>
<path fill="none" stroke="#b58008" d="M4626.01,-1206.17C4581.62,-1162.88 4523.54,-1106.23 4478.78,-1062.58"/>
<ellipse fill="none" stroke="#b58008" cx="4629.08" cy="-1209.16" rx="4.00002" ry="4.00002"/>
<polygon fill="#b58008" stroke="#b58008" points="4478.6,-1062.4 4474.58,-1052.2 4475.02,-1058.91 4471.44,-1055.42 4471.44,-1055.42 4471.44,-1055.42 4475.02,-1058.91 4468.29,-1058.64 4478.6,-1062.4 4478.6,-1062.4"/>
</g>
<!-- Avoir -->
<g id="node69" class="node"><title>Avoir</title>
<path fill="none" stroke="black" d="M3280,-557.5C3280,-557.5 3500,-557.5 3500,-557.5 3506,-557.5 3512,-563.5 3512,-569.5 3512,-569.5 3512,-846.5 3512,-846.5 3512,-852.5 3506,-858.5 3500,-858.5 3500,-858.5 3280,-858.5 3280,-858.5 3274,-858.5 3268,-852.5 3268,-846.5 3268,-846.5 3268,-569.5 3268,-569.5 3268,-563.5 3274,-557.5 3280,-557.5"/>
<text text-anchor="middle" x="3390" y="-843.3" font-family="Times,serif" font-size="14.00">Avoir</text>
<polyline fill="none" stroke="black" points="3268,-835.5 3512,-835.5 "/>
<text text-anchor="start" x="3276" y="-820.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="3276" y="-805.3" font-family="Times,serif" font-size="14.00">invoiced_id :integer</text>
<text text-anchor="start" x="3276" y="-790.3" font-family="Times,serif" font-size="14.00">invoiced_type :character varying(255)</text>
<text text-anchor="start" x="3276" y="-775.3" font-family="Times,serif" font-size="14.00">stp_invoice_id :character varying(255)</text>
<text text-anchor="start" x="3276" y="-760.3" font-family="Times,serif" font-size="14.00">total :integer</text>
<text text-anchor="start" x="3276" y="-745.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="3276" y="-730.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="3276" y="-715.3" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="3276" y="-700.3" font-family="Times,serif" font-size="14.00">reference :character varying(255)</text>
<text text-anchor="start" x="3276" y="-685.3" font-family="Times,serif" font-size="14.00">avoir_mode :character varying(255)</text>
<text text-anchor="start" x="3276" y="-670.3" font-family="Times,serif" font-size="14.00">avoir_date :timestamp without time zone</text>
<text text-anchor="start" x="3276" y="-655.3" font-family="Times,serif" font-size="14.00">invoice_id :integer</text>
<text text-anchor="start" x="3276" y="-640.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="3276" y="-625.3" font-family="Times,serif" font-size="14.00">subscription_to_expire :boolean</text>
<text text-anchor="start" x="3276" y="-610.3" font-family="Times,serif" font-size="14.00">description :text</text>
<text text-anchor="start" x="3276" y="-595.3" font-family="Times,serif" font-size="14.00">wallet_amount :integer</text>
<text text-anchor="start" x="3276" y="-580.3" font-family="Times,serif" font-size="14.00">wallet_transaction_id :integer</text>
<text text-anchor="start" x="3276" y="-565.3" font-family="Times,serif" font-size="14.00">coupon_id :integer</text>
<path fill="none" stroke="black" d="M3266,-557.5C3266,-557.5 3486,-557.5 3486,-557.5 3492,-557.5 3498,-563.5 3498,-569.5 3498,-569.5 3498,-846.5 3498,-846.5 3498,-852.5 3492,-858.5 3486,-858.5 3486,-858.5 3266,-858.5 3266,-858.5 3260,-858.5 3254,-852.5 3254,-846.5 3254,-846.5 3254,-569.5 3254,-569.5 3254,-563.5 3260,-557.5 3266,-557.5"/>
<text text-anchor="middle" x="3376" y="-843.3" font-family="Times,serif" font-size="14.00">Avoir</text>
<polyline fill="none" stroke="black" points="3254,-835.5 3498,-835.5 "/>
<text text-anchor="start" x="3262" y="-820.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="3262" y="-805.3" font-family="Times,serif" font-size="14.00">invoiced_id :integer</text>
<text text-anchor="start" x="3262" y="-790.3" font-family="Times,serif" font-size="14.00">invoiced_type :character varying(255)</text>
<text text-anchor="start" x="3262" y="-775.3" font-family="Times,serif" font-size="14.00">stp_invoice_id :character varying(255)</text>
<text text-anchor="start" x="3262" y="-760.3" font-family="Times,serif" font-size="14.00">total :integer</text>
<text text-anchor="start" x="3262" y="-745.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="3262" y="-730.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="3262" y="-715.3" font-family="Times,serif" font-size="14.00">user_id :integer</text>
<text text-anchor="start" x="3262" y="-700.3" font-family="Times,serif" font-size="14.00">reference :character varying(255)</text>
<text text-anchor="start" x="3262" y="-685.3" font-family="Times,serif" font-size="14.00">avoir_mode :character varying(255)</text>
<text text-anchor="start" x="3262" y="-670.3" font-family="Times,serif" font-size="14.00">avoir_date :timestamp without time zone</text>
<text text-anchor="start" x="3262" y="-655.3" font-family="Times,serif" font-size="14.00">invoice_id :integer</text>
<text text-anchor="start" x="3262" y="-640.3" font-family="Times,serif" font-size="14.00">type :character varying(255)</text>
<text text-anchor="start" x="3262" y="-625.3" font-family="Times,serif" font-size="14.00">subscription_to_expire :boolean</text>
<text text-anchor="start" x="3262" y="-610.3" font-family="Times,serif" font-size="14.00">description :text</text>
<text text-anchor="start" x="3262" y="-595.3" font-family="Times,serif" font-size="14.00">wallet_amount :integer</text>
<text text-anchor="start" x="3262" y="-580.3" font-family="Times,serif" font-size="14.00">wallet_transaction_id :integer</text>
<text text-anchor="start" x="3262" y="-565.3" font-family="Times,serif" font-size="14.00">coupon_id :integer</text>
</g>
<!-- Avoir&#45;&gt;InvoiceItem -->
<g id="edge102" class="edge"><title>Avoir&#45;&gt;InvoiceItem</title>
<path fill="none" stroke="#c282f9" d="M3355.6,-549.542C3329.88,-431.836 3295.61,-274.936 3274.17,-176.825"/>
<ellipse fill="none" stroke="#c282f9" cx="3356.48" cy="-553.592" rx="4.00001" ry="4.00001"/>
<polygon fill="#c282f9" stroke="#c282f9" points="3274.14,-176.698 3276.4,-165.968 3273.08,-171.814 3272.01,-166.929 3272.01,-166.929 3272.01,-166.929 3273.08,-171.814 3267.61,-167.889 3274.14,-176.698 3274.14,-176.698"/>
<g id="edge103" class="edge"><title>Avoir&#45;&gt;InvoiceItem</title>
<path fill="none" stroke="#e262c2" d="M3320.23,-549.907C3278.39,-432.045 3222.54,-274.731 3187.68,-176.538"/>
<ellipse fill="none" stroke="#e262c2" cx="3321.59" cy="-553.73" rx="4.00001" ry="4.00001"/>
<polygon fill="#e262c2" stroke="#e262c2" points="3187.61,-176.353 3188.5,-165.423 3185.94,-171.641 3184.26,-166.929 3184.26,-166.929 3184.26,-166.929 3185.94,-171.641 3180.02,-168.434 3187.61,-176.353 3187.61,-176.353"/>
</g>
<!-- Avoir&#45;&gt;Invoice -->
<g id="edge103" class="edge"><title>Avoir&#45;&gt;Invoice</title>
<path fill="none" stroke="#0b9b03" d="M3261.22,-558.586C3260.48,-558.052 3259.74,-557.524 3259,-557 3142.95,-475.055 2988.8,-420.192 2880.86,-388.773"/>
<ellipse fill="none" stroke="#0b9b03" cx="3264.62" cy="-561.122" rx="4.00002" ry="4.00002"/>
<ellipse fill="#0b9b03" stroke="#0b9b03" cx="2877.01" cy="-387.662" rx="4.00001" ry="4.00001"/>
<text text-anchor="middle" x="3237" y="-527.8" font-family="Times,serif" font-size="14.00">avoir</text>
<g id="edge104" class="edge"><title>Avoir&#45;&gt;Invoice</title>
<path fill="none" stroke="#ca2a75" d="M3247.26,-558.534C3246.51,-558.017 3245.75,-557.506 3245,-557 3103.79,-462.166 2913.45,-407.849 2788.31,-380.147"/>
<ellipse fill="none" stroke="#ca2a75" cx="3250.7" cy="-560.996" rx="4.00002" ry="4.00002"/>
<ellipse fill="#ca2a75" stroke="#ca2a75" cx="2784.07" cy="-379.217" rx="4.00001" ry="4.00001"/>
<text text-anchor="middle" x="3217" y="-527.8" font-family="Times,serif" font-size="14.00">avoir</text>
</g>
<!-- NotificationType -->
<g id="node70" class="node"><title>NotificationType</title>
<polygon fill="none" stroke="black" points="7893,-2981.5 7893,-3027.5 8003,-3027.5 8003,-2981.5 7893,-2981.5"/>
<text text-anchor="middle" x="7948" y="-3012.3" font-family="Times,serif" font-size="14.00">NotificationType</text>
<polyline fill="none" stroke="black" points="7893,-3004.5 8003,-3004.5 "/>
<text text-anchor="middle" x="7948" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<polygon fill="none" stroke="black" points="7844,-2981.5 7844,-3027.5 7954,-3027.5 7954,-2981.5 7844,-2981.5"/>
<text text-anchor="middle" x="7899" y="-3012.3" font-family="Times,serif" font-size="14.00">NotificationType</text>
<polyline fill="none" stroke="black" points="7844,-3004.5 7954,-3004.5 "/>
<text text-anchor="middle" x="7899" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- Stylesheet -->
<g id="node72" class="node"><title>Stylesheet</title>
<path fill="none" stroke="black" d="M8033,-2959C8033,-2959 8253,-2959 8253,-2959 8259,-2959 8265,-2965 8265,-2971 8265,-2971 8265,-3038 8265,-3038 8265,-3044 8259,-3050 8253,-3050 8253,-3050 8033,-3050 8033,-3050 8027,-3050 8021,-3044 8021,-3038 8021,-3038 8021,-2971 8021,-2971 8021,-2965 8027,-2959 8033,-2959"/>
<text text-anchor="middle" x="8143" y="-3034.8" font-family="Times,serif" font-size="14.00">Stylesheet</text>
<polyline fill="none" stroke="black" points="8021,-3027 8265,-3027 "/>
<text text-anchor="start" x="8029" y="-3011.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="8029" y="-2996.8" font-family="Times,serif" font-size="14.00">contents :text</text>
<text text-anchor="start" x="8029" y="-2981.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="8029" y="-2966.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<path fill="none" stroke="black" d="M7984,-2959C7984,-2959 8204,-2959 8204,-2959 8210,-2959 8216,-2965 8216,-2971 8216,-2971 8216,-3038 8216,-3038 8216,-3044 8210,-3050 8204,-3050 8204,-3050 7984,-3050 7984,-3050 7978,-3050 7972,-3044 7972,-3038 7972,-3038 7972,-2971 7972,-2971 7972,-2965 7978,-2959 7984,-2959"/>
<text text-anchor="middle" x="8094" y="-3034.8" font-family="Times,serif" font-size="14.00">Stylesheet</text>
<polyline fill="none" stroke="black" points="7972,-3027 8216,-3027 "/>
<text text-anchor="start" x="7980" y="-3011.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="7980" y="-2996.8" font-family="Times,serif" font-size="14.00">contents :text</text>
<text text-anchor="start" x="7980" y="-2981.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="7980" y="-2966.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Coupon -->
<g id="node77" class="node"><title>Coupon</title>
<path fill="none" stroke="black" d="M3018,-617.5C3018,-617.5 3238,-617.5 3238,-617.5 3244,-617.5 3250,-623.5 3250,-629.5 3250,-629.5 3250,-786.5 3250,-786.5 3250,-792.5 3244,-798.5 3238,-798.5 3238,-798.5 3018,-798.5 3018,-798.5 3012,-798.5 3006,-792.5 3006,-786.5 3006,-786.5 3006,-629.5 3006,-629.5 3006,-623.5 3012,-617.5 3018,-617.5"/>
<text text-anchor="middle" x="3128" y="-783.3" font-family="Times,serif" font-size="14.00">Coupon</text>
<polyline fill="none" stroke="black" points="3006,-775.5 3250,-775.5 "/>
<text text-anchor="start" x="3014" y="-760.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="3014" y="-745.3" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="3014" y="-730.3" font-family="Times,serif" font-size="14.00">code :character varying</text>
<text text-anchor="start" x="3014" y="-715.3" font-family="Times,serif" font-size="14.00">percent_off :integer</text>
<text text-anchor="start" x="3014" y="-700.3" font-family="Times,serif" font-size="14.00">valid_until :timestamp without time zone</text>
<text text-anchor="start" x="3014" y="-685.3" font-family="Times,serif" font-size="14.00">max_usages :integer</text>
<text text-anchor="start" x="3014" y="-670.3" font-family="Times,serif" font-size="14.00">active :boolean</text>
<text text-anchor="start" x="3014" y="-655.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="3014" y="-640.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="3014" y="-625.3" font-family="Times,serif" font-size="14.00">validity_per_user :character varying</text>
<g id="node78" class="node"><title>Coupon</title>
<path fill="none" stroke="black" d="M3004,-617.5C3004,-617.5 3224,-617.5 3224,-617.5 3230,-617.5 3236,-623.5 3236,-629.5 3236,-629.5 3236,-786.5 3236,-786.5 3236,-792.5 3230,-798.5 3224,-798.5 3224,-798.5 3004,-798.5 3004,-798.5 2998,-798.5 2992,-792.5 2992,-786.5 2992,-786.5 2992,-629.5 2992,-629.5 2992,-623.5 2998,-617.5 3004,-617.5"/>
<text text-anchor="middle" x="3114" y="-783.3" font-family="Times,serif" font-size="14.00">Coupon</text>
<polyline fill="none" stroke="black" points="2992,-775.5 3236,-775.5 "/>
<text text-anchor="start" x="3000" y="-760.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="3000" y="-745.3" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="3000" y="-730.3" font-family="Times,serif" font-size="14.00">code :character varying</text>
<text text-anchor="start" x="3000" y="-715.3" font-family="Times,serif" font-size="14.00">percent_off :integer</text>
<text text-anchor="start" x="3000" y="-700.3" font-family="Times,serif" font-size="14.00">valid_until :timestamp without time zone</text>
<text text-anchor="start" x="3000" y="-685.3" font-family="Times,serif" font-size="14.00">max_usages :integer</text>
<text text-anchor="start" x="3000" y="-670.3" font-family="Times,serif" font-size="14.00">active :boolean</text>
<text text-anchor="start" x="3000" y="-655.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="3000" y="-640.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="3000" y="-625.3" font-family="Times,serif" font-size="14.00">validity_per_user :character varying</text>
</g>
<!-- Coupon&#45;&gt;Invoice -->
<g id="edge104" class="edge"><title>Coupon&#45;&gt;Invoice</title>
<path fill="none" stroke="#6f81a0" d="M3065.24,-610.491C3043.83,-581.083 3018.55,-549.752 2992,-524 2958.9,-491.892 2919.12,-461.508 2881.51,-435.636"/>
<ellipse fill="none" stroke="#6f81a0" cx="3067.69" cy="-613.884" rx="4.00002" ry="4.00002"/>
<polygon fill="#6f81a0" stroke="#6f81a0" points="2881.28,-435.478 2875.55,-426.127 2877.15,-432.661 2873.02,-429.844 2873.02,-429.844 2873.02,-429.844 2877.15,-432.661 2870.48,-433.562 2881.28,-435.478 2881.28,-435.478"/>
<g id="edge105" class="edge"><title>Coupon&#45;&gt;Invoice</title>
<path fill="none" stroke="#426e2a" d="M3054.71,-610.618C3033.09,-580.448 3006.81,-548.637 2978,-524 2922.33,-476.382 2850.87,-437.254 2789.61,-408.776"/>
<ellipse fill="none" stroke="#426e2a" cx="3057.22" cy="-614.167" rx="4.00002" ry="4.00002"/>
<polygon fill="#426e2a" stroke="#426e2a" points="2789.35,-408.654 2782.14,-400.387 2784.81,-406.565 2780.26,-404.475 2780.26,-404.475 2780.26,-404.475 2784.81,-406.565 2778.38,-408.563 2789.35,-408.654 2789.35,-408.654"/>
</g>
<!-- Category -->
<g id="node78" class="node"><title>Category</title>
<path fill="none" stroke="black" d="M4608,-2575C4608,-2575 4828,-2575 4828,-2575 4834,-2575 4840,-2581 4840,-2587 4840,-2587 4840,-2669 4840,-2669 4840,-2675 4834,-2681 4828,-2681 4828,-2681 4608,-2681 4608,-2681 4602,-2681 4596,-2675 4596,-2669 4596,-2669 4596,-2587 4596,-2587 4596,-2581 4602,-2575 4608,-2575"/>
<text text-anchor="middle" x="4718" y="-2665.8" font-family="Times,serif" font-size="14.00">Category</text>
<polyline fill="none" stroke="black" points="4596,-2658 4840,-2658 "/>
<text text-anchor="start" x="4604" y="-2642.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4604" y="-2627.8" font-family="Times,serif" font-size="14.00">name :character varying(255)</text>
<text text-anchor="start" x="4604" y="-2612.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4604" y="-2597.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="4604" y="-2582.8" font-family="Times,serif" font-size="14.00">slug :character varying</text>
<g id="node79" class="node"><title>Category</title>
<path fill="none" stroke="black" d="M4538,-2575C4538,-2575 4758,-2575 4758,-2575 4764,-2575 4770,-2581 4770,-2587 4770,-2587 4770,-2669 4770,-2669 4770,-2675 4764,-2681 4758,-2681 4758,-2681 4538,-2681 4538,-2681 4532,-2681 4526,-2675 4526,-2669 4526,-2669 4526,-2587 4526,-2587 4526,-2581 4532,-2575 4538,-2575"/>
<text text-anchor="middle" x="4648" y="-2665.8" font-family="Times,serif" font-size="14.00">Category</text>
<polyline fill="none" stroke="black" points="4526,-2658 4770,-2658 "/>
<text text-anchor="start" x="4534" y="-2642.8" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="4534" y="-2627.8" font-family="Times,serif" font-size="14.00">name :character varying(255)</text>
<text text-anchor="start" x="4534" y="-2612.8" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="4534" y="-2597.8" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<text text-anchor="start" x="4534" y="-2582.8" font-family="Times,serif" font-size="14.00">slug :character varying</text>
</g>
<!-- Category&#45;&gt;Event -->
<g id="edge105" class="edge"><title>Category&#45;&gt;Event</title>
<path fill="none" stroke="#c39c91" d="M4698.12,-2567.19C4669.92,-2482.36 4617.77,-2325.46 4582.01,-2217.86"/>
<ellipse fill="none" stroke="#c39c91" cx="4699.42" cy="-2571.1" rx="4.00001" ry="4.00001"/>
<polygon fill="#c39c91" stroke="#c39c91" points="4581.97,-2217.74 4583.09,-2206.83 4580.39,-2213 4578.82,-2208.25 4578.82,-2208.25 4578.82,-2208.25 4580.39,-2213 4574.55,-2209.67 4581.97,-2217.74 4581.97,-2217.74"/>
<g id="edge106" class="edge"><title>Category&#45;&gt;Event</title>
<path fill="none" stroke="#368a81" d="M4635.95,-2566.93C4618.94,-2482.12 4587.56,-2325.65 4566,-2218.17"/>
<ellipse fill="none" stroke="#368a81" cx="4636.76" cy="-2570.97" rx="4.00001" ry="4.00001"/>
<polygon fill="#368a81" stroke="#368a81" points="4565.98,-2218.06 4568.42,-2207.37 4564.99,-2213.15 4564.01,-2208.25 4564.01,-2208.25 4564.01,-2208.25 4564.99,-2213.15 4559.6,-2209.14 4565.98,-2218.06 4565.98,-2218.06"/>
</g>
<!-- MachineImage -->
<g id="node80" class="node"><title>MachineImage</title>
<g id="node81" class="node"><title>MachineImage</title>
<path fill="none" stroke="black" d="M3417,-1204.5C3417,-1204.5 3637,-1204.5 3637,-1204.5 3643,-1204.5 3649,-1210.5 3649,-1216.5 3649,-1216.5 3649,-1328.5 3649,-1328.5 3649,-1334.5 3643,-1340.5 3637,-1340.5 3637,-1340.5 3417,-1340.5 3417,-1340.5 3411,-1340.5 3405,-1334.5 3405,-1328.5 3405,-1328.5 3405,-1216.5 3405,-1216.5 3405,-1210.5 3411,-1204.5 3417,-1204.5"/>
<text text-anchor="middle" x="3527" y="-1325.3" font-family="Times,serif" font-size="14.00">MachineImage</text>
<polyline fill="none" stroke="black" points="3405,-1317.5 3649,-1317.5 "/>
@ -1737,97 +1758,97 @@
<text text-anchor="start" x="3413" y="-1212.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Feed -->
<g id="node81" class="node"><title>Feed</title>
<polygon fill="none" stroke="black" points="8283,-2981.5 8283,-3027.5 8337,-3027.5 8337,-2981.5 8283,-2981.5"/>
<text text-anchor="middle" x="8310" y="-3012.3" font-family="Times,serif" font-size="14.00">Feed</text>
<polyline fill="none" stroke="black" points="8283,-3004.5 8337,-3004.5 "/>
<text text-anchor="middle" x="8310" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
<g id="node82" class="node"><title>Feed</title>
<polygon fill="none" stroke="black" points="8234,-2981.5 8234,-3027.5 8288,-3027.5 8288,-2981.5 8234,-2981.5"/>
<text text-anchor="middle" x="8261" y="-3012.3" font-family="Times,serif" font-size="14.00">Feed</text>
<polyline fill="none" stroke="black" points="8234,-3004.5 8288,-3004.5 "/>
<text text-anchor="middle" x="8261" y="-2989.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- Machine&#45;&gt;Price -->
<g id="edge109" class="edge"><title>Machine&#45;&gt;Price</title>
<path fill="none" stroke="#351e55" d="M3272.71,-1597.34C3302.7,-1544.63 3339.65,-1471.04 3358,-1401 3386.32,-1292.93 3389.17,-1163.36 3387.22,-1080.26"/>
<ellipse fill="none" stroke="#351e55" cx="3270.7" cy="-1600.84" rx="4.00002" ry="4.00002"/>
<polygon fill="#351e55" stroke="#351e55" points="3387.22,-1080.11 3391.45,-1069.99 3387.08,-1075.11 3386.95,-1070.11 3386.95,-1070.11 3386.95,-1070.11 3387.08,-1075.11 3382.45,-1070.23 3387.22,-1080.11 3387.22,-1080.11"/>
<g id="edge110" class="edge"><title>Machine&#45;&gt;Price</title>
<path fill="none" stroke="#56d0c3" d="M3272.71,-1597.34C3302.7,-1544.63 3339.65,-1471.04 3358,-1401 3386.32,-1292.93 3389.17,-1163.36 3387.22,-1080.26"/>
<ellipse fill="none" stroke="#56d0c3" cx="3270.7" cy="-1600.84" rx="4.00002" ry="4.00002"/>
<polygon fill="#56d0c3" stroke="#56d0c3" points="3387.22,-1080.11 3391.45,-1069.99 3387.08,-1075.11 3386.95,-1070.11 3386.95,-1070.11 3386.95,-1070.11 3387.08,-1075.11 3382.45,-1070.23 3387.22,-1080.11 3387.22,-1080.11"/>
</g>
<!-- Machine&#45;&gt;Plan -->
<g id="edge112" class="edge"><title>Machine&#45;&gt;Plan</title>
<path fill="none" stroke="#2b2878" d="M3098.92,-1596.59C3096.09,-1593.18 3093.44,-1589.66 3091,-1586 3049.26,-1523.37 3096.34,-1486.47 3063,-1419 3060.4,-1413.74 3057.55,-1408.53 3054.48,-1403.4"/>
<polygon fill="#2b2878" stroke="#2b2878" points="3099.16,-1596.86 3102.48,-1607.31 3102.49,-1600.58 3105.83,-1604.31 3105.83,-1604.31 3105.83,-1604.31 3102.49,-1600.58 3109.18,-1601.31 3099.16,-1596.86 3099.16,-1596.86"/>
<polygon fill="#2b2878" stroke="#2b2878" points="3054.44,-1403.32 3052.96,-1392.46 3051.79,-1399.08 3049.14,-1394.84 3049.14,-1394.84 3049.14,-1394.84 3051.79,-1399.08 3045.33,-1397.22 3054.44,-1403.32 3054.44,-1403.32"/>
<g id="edge113" class="edge"><title>Machine&#45;&gt;Plan</title>
<path fill="none" stroke="#1650b6" d="M3098.92,-1596.59C3096.09,-1593.18 3093.44,-1589.66 3091,-1586 3049.26,-1523.37 3096.34,-1486.47 3063,-1419 3060.4,-1413.74 3057.55,-1408.53 3054.48,-1403.4"/>
<polygon fill="#1650b6" stroke="#1650b6" points="3099.16,-1596.86 3102.48,-1607.31 3102.49,-1600.58 3105.83,-1604.31 3105.83,-1604.31 3105.83,-1604.31 3102.49,-1600.58 3109.18,-1601.31 3099.16,-1596.86 3099.16,-1596.86"/>
<polygon fill="#1650b6" stroke="#1650b6" points="3054.44,-1403.32 3052.96,-1392.46 3051.79,-1399.08 3049.14,-1394.84 3049.14,-1394.84 3049.14,-1394.84 3051.79,-1399.08 3045.33,-1397.22 3054.44,-1403.32 3054.44,-1403.32"/>
</g>
<!-- Machine&#45;&gt;MachineFile -->
<g id="edge107" class="edge"><title>Machine&#45;&gt;MachineFile</title>
<path fill="none" stroke="#a70897" d="M3227,-1596.08C3227,-1525.82 3227,-1421.54 3227,-1350.71"/>
<ellipse fill="none" stroke="#a70897" cx="3227" cy="-1600.43" rx="4" ry="4"/>
<polygon fill="#a70897" stroke="#a70897" points="3227,-1350.51 3231.5,-1340.51 3227,-1345.51 3227,-1340.51 3227,-1340.51 3227,-1340.51 3227,-1345.51 3222.5,-1340.51 3227,-1350.51 3227,-1350.51"/>
<g id="edge108" class="edge"><title>Machine&#45;&gt;MachineFile</title>
<path fill="none" stroke="#e0b276" d="M3227,-1596.08C3227,-1525.82 3227,-1421.54 3227,-1350.71"/>
<ellipse fill="none" stroke="#e0b276" cx="3227" cy="-1600.43" rx="4" ry="4"/>
<polygon fill="#e0b276" stroke="#e0b276" points="3227,-1350.51 3231.5,-1340.51 3227,-1345.51 3227,-1340.51 3227,-1340.51 3227,-1340.51 3227,-1345.51 3222.5,-1340.51 3227,-1350.51 3227,-1350.51"/>
</g>
<!-- Machine&#45;&gt;Credit -->
<g id="edge111" class="edge"><title>Machine&#45;&gt;Credit</title>
<path fill="none" stroke="#fea73a" d="M3183.46,-1597.36C3154.27,-1544.37 3117.4,-1470.44 3096,-1401 3062,-1290.66 3121.71,-1240.29 3058,-1144 2995.82,-1050.02 2833.27,-1128.89 2728,-1093 2710.03,-1086.87 2692.18,-1077.91 2675.46,-1067.87"/>
<ellipse fill="none" stroke="#fea73a" cx="3185.41" cy="-1600.87" rx="4.00002" ry="4.00002"/>
<polygon fill="#fea73a" stroke="#fea73a" points="2675.33,-1067.8 2669.2,-1058.71 2671.08,-1065.17 2666.83,-1062.53 2666.83,-1062.53 2666.83,-1062.53 2671.08,-1065.17 2664.46,-1066.36 2675.33,-1067.8 2675.33,-1067.8"/>
<g id="edge112" class="edge"><title>Machine&#45;&gt;Credit</title>
<path fill="none" stroke="#e9a441" d="M3183.46,-1597.36C3154.27,-1544.37 3117.4,-1470.44 3096,-1401 3062,-1290.66 3121.71,-1240.29 3058,-1144 2995.82,-1050.02 2833.27,-1128.89 2728,-1093 2710.03,-1086.87 2692.18,-1077.91 2675.46,-1067.87"/>
<ellipse fill="none" stroke="#e9a441" cx="3185.41" cy="-1600.87" rx="4.00002" ry="4.00002"/>
<polygon fill="#e9a441" stroke="#e9a441" points="2675.33,-1067.8 2669.2,-1058.71 2671.08,-1065.17 2666.83,-1062.53 2666.83,-1062.53 2666.83,-1062.53 2671.08,-1065.17 2664.46,-1066.36 2675.33,-1067.8 2675.33,-1067.8"/>
</g>
<!-- Machine&#45;&gt;Reservation -->
<g id="edge110" class="edge"><title>Machine&#45;&gt;Reservation</title>
<path fill="none" stroke="#4a60e4" d="M3356.89,-1604.32C3357.26,-1604.21 3357.63,-1604.11 3358,-1604 3449.3,-1577.74 3481.17,-1616.93 3571,-1586 3713.08,-1537.07 3736.72,-1494.95 3854,-1401 3868.76,-1389.17 3883.76,-1375.94 3898.07,-1362.6"/>
<ellipse fill="none" stroke="#4a60e4" cx="3352.94" cy="-1605.55" rx="4.00001" ry="4.00001"/>
<polygon fill="#4a60e4" stroke="#4a60e4" points="3898.2,-1362.47 3908.57,-1358.89 3901.84,-1359.04 3905.49,-1355.62 3905.49,-1355.62 3905.49,-1355.62 3901.84,-1359.04 3902.4,-1352.34 3898.2,-1362.47 3898.2,-1362.47"/>
<g id="edge111" class="edge"><title>Machine&#45;&gt;Reservation</title>
<path fill="none" stroke="#b09aef" d="M3356.89,-1604.32C3357.26,-1604.21 3357.63,-1604.11 3358,-1604 3449.3,-1577.74 3481.17,-1616.93 3571,-1586 3713.08,-1537.07 3736.72,-1494.95 3854,-1401 3868.76,-1389.17 3883.76,-1375.94 3898.07,-1362.6"/>
<ellipse fill="none" stroke="#b09aef" cx="3352.94" cy="-1605.55" rx="4.00001" ry="4.00001"/>
<polygon fill="#b09aef" stroke="#b09aef" points="3898.2,-1362.47 3908.57,-1358.89 3901.84,-1359.04 3905.49,-1355.62 3905.49,-1355.62 3905.49,-1355.62 3901.84,-1359.04 3902.4,-1352.34 3898.2,-1362.47 3898.2,-1362.47"/>
</g>
<!-- Machine&#45;&gt;MachinesAvailability -->
<g id="edge108" class="edge"><title>Machine&#45;&gt;MachinesAvailability</title>
<path fill="none" stroke="#94dec1" d="M3356.91,-1604.38C3357.27,-1604.25 3357.64,-1604.12 3358,-1604 3398.63,-1590.01 3414.51,-1605.11 3453,-1586 3581.24,-1522.35 3691.3,-1389.04 3743.2,-1318.88"/>
<ellipse fill="none" stroke="#94dec1" cx="3353.01" cy="-1605.79" rx="4.00001" ry="4.00001"/>
<polygon fill="#94dec1" stroke="#94dec1" points="3743.32,-1318.71 3752.86,-1313.31 3746.28,-1314.68 3749.23,-1310.65 3749.23,-1310.65 3749.23,-1310.65 3746.28,-1314.68 3745.61,-1307.99 3743.32,-1318.71 3743.32,-1318.71"/>
<g id="edge109" class="edge"><title>Machine&#45;&gt;MachinesAvailability</title>
<path fill="none" stroke="#0a7e7e" d="M3356.91,-1604.38C3357.27,-1604.25 3357.64,-1604.12 3358,-1604 3398.63,-1590.01 3414.51,-1605.11 3453,-1586 3581.24,-1522.35 3691.3,-1389.04 3743.2,-1318.88"/>
<ellipse fill="none" stroke="#0a7e7e" cx="3353.01" cy="-1605.79" rx="4.00001" ry="4.00001"/>
<polygon fill="#0a7e7e" stroke="#0a7e7e" points="3743.32,-1318.71 3752.86,-1313.31 3746.28,-1314.68 3749.23,-1310.65 3749.23,-1310.65 3749.23,-1310.65 3746.28,-1314.68 3745.61,-1307.99 3743.32,-1318.71 3743.32,-1318.71"/>
</g>
<!-- Machine&#45;&gt;MachineImage -->
<g id="edge106" class="edge"><title>Machine&#45;&gt;MachineImage</title>
<path fill="none" stroke="#d84c34" d="M3356.49,-1604.41C3376.31,-1594.06 3390.49,-1586.55 3391,-1586 3453.94,-1518.49 3490.67,-1417.23 3509.76,-1348.41"/>
<ellipse fill="none" stroke="#d84c34" cx="3352.81" cy="-1606.34" rx="4.00002" ry="4.00002"/>
<ellipse fill="#d84c34" stroke="#d84c34" cx="3510.84" cy="-1344.46" rx="4.00001" ry="4.00001"/>
<g id="edge107" class="edge"><title>Machine&#45;&gt;MachineImage</title>
<path fill="none" stroke="#fcc614" d="M3356.49,-1604.41C3376.31,-1594.06 3390.49,-1586.55 3391,-1586 3453.94,-1518.49 3490.67,-1417.23 3509.76,-1348.41"/>
<ellipse fill="none" stroke="#fcc614" cx="3352.81" cy="-1606.34" rx="4.00002" ry="4.00002"/>
<ellipse fill="#fcc614" stroke="#fcc614" cx="3510.84" cy="-1344.46" rx="4.00001" ry="4.00001"/>
</g>
<!-- Abuse -->
<g id="node83" class="node"><title>Abuse</title>
<path fill="none" stroke="black" d="M8367,-2921.5C8367,-2921.5 8587,-2921.5 8587,-2921.5 8593,-2921.5 8599,-2927.5 8599,-2933.5 8599,-2933.5 8599,-3075.5 8599,-3075.5 8599,-3081.5 8593,-3087.5 8587,-3087.5 8587,-3087.5 8367,-3087.5 8367,-3087.5 8361,-3087.5 8355,-3081.5 8355,-3075.5 8355,-3075.5 8355,-2933.5 8355,-2933.5 8355,-2927.5 8361,-2921.5 8367,-2921.5"/>
<text text-anchor="middle" x="8477" y="-3072.3" font-family="Times,serif" font-size="14.00">Abuse</text>
<polyline fill="none" stroke="black" points="8355,-3064.5 8599,-3064.5 "/>
<text text-anchor="start" x="8363" y="-3049.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="8363" y="-3034.3" font-family="Times,serif" font-size="14.00">signaled_id :integer</text>
<text text-anchor="start" x="8363" y="-3019.3" font-family="Times,serif" font-size="14.00">signaled_type :character varying</text>
<text text-anchor="start" x="8363" y="-3004.3" font-family="Times,serif" font-size="14.00">first_name :character varying</text>
<text text-anchor="start" x="8363" y="-2989.3" font-family="Times,serif" font-size="14.00">last_name :character varying</text>
<text text-anchor="start" x="8363" y="-2974.3" font-family="Times,serif" font-size="14.00">email :character varying</text>
<text text-anchor="start" x="8363" y="-2959.3" font-family="Times,serif" font-size="14.00">message :text</text>
<text text-anchor="start" x="8363" y="-2944.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="8363" y="-2929.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<g id="node84" class="node"><title>Abuse</title>
<path fill="none" stroke="black" d="M8318,-2921.5C8318,-2921.5 8538,-2921.5 8538,-2921.5 8544,-2921.5 8550,-2927.5 8550,-2933.5 8550,-2933.5 8550,-3075.5 8550,-3075.5 8550,-3081.5 8544,-3087.5 8538,-3087.5 8538,-3087.5 8318,-3087.5 8318,-3087.5 8312,-3087.5 8306,-3081.5 8306,-3075.5 8306,-3075.5 8306,-2933.5 8306,-2933.5 8306,-2927.5 8312,-2921.5 8318,-2921.5"/>
<text text-anchor="middle" x="8428" y="-3072.3" font-family="Times,serif" font-size="14.00">Abuse</text>
<polyline fill="none" stroke="black" points="8306,-3064.5 8550,-3064.5 "/>
<text text-anchor="start" x="8314" y="-3049.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="8314" y="-3034.3" font-family="Times,serif" font-size="14.00">signaled_id :integer</text>
<text text-anchor="start" x="8314" y="-3019.3" font-family="Times,serif" font-size="14.00">signaled_type :character varying</text>
<text text-anchor="start" x="8314" y="-3004.3" font-family="Times,serif" font-size="14.00">first_name :character varying</text>
<text text-anchor="start" x="8314" y="-2989.3" font-family="Times,serif" font-size="14.00">last_name :character varying</text>
<text text-anchor="start" x="8314" y="-2974.3" font-family="Times,serif" font-size="14.00">email :character varying</text>
<text text-anchor="start" x="8314" y="-2959.3" font-family="Times,serif" font-size="14.00">message :text</text>
<text text-anchor="start" x="8314" y="-2944.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="8314" y="-2929.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
<!-- Profile&#45;&gt;UserAvatar -->
<g id="edge113" class="edge"><title>Profile&#45;&gt;UserAvatar</title>
<path fill="none" stroke="#2d2db1" d="M387.806,-1876.7C401.96,-1830.45 415.909,-1784.88 426.998,-1748.65"/>
<ellipse fill="none" stroke="#2d2db1" cx="386.63" cy="-1880.54" rx="4.00001" ry="4.00001"/>
<ellipse fill="#2d2db1" stroke="#2d2db1" cx="428.293" cy="-1744.42" rx="4.00001" ry="4.00001"/>
<g id="edge114" class="edge"><title>Profile&#45;&gt;UserAvatar</title>
<path fill="none" stroke="#af542b" d="M387.806,-1876.7C401.96,-1830.45 415.909,-1784.88 426.998,-1748.65"/>
<ellipse fill="none" stroke="#af542b" cx="386.63" cy="-1880.54" rx="4.00001" ry="4.00001"/>
<ellipse fill="#af542b" stroke="#af542b" cx="428.293" cy="-1744.42" rx="4.00001" ry="4.00001"/>
</g>
<!-- Profile&#45;&gt;Address -->
<g id="edge114" class="edge"><title>Profile&#45;&gt;Address</title>
<path fill="none" stroke="#015e66" d="M191.536,-1968.95C139.045,-1905.32 84.2238,-1824.77 57,-1741 17.3181,-1618.9 63.0298,-1473.93 105.528,-1378.15"/>
<ellipse fill="none" stroke="#015e66" cx="194.378" cy="-1972.37" rx="4.00002" ry="4.00002"/>
<ellipse fill="#015e66" stroke="#015e66" cx="107.203" cy="-1374.42" rx="4.00002" ry="4.00002"/>
<g id="edge115" class="edge"><title>Profile&#45;&gt;Address</title>
<path fill="none" stroke="#9185dc" d="M191.536,-1968.95C139.045,-1905.32 84.2238,-1824.77 57,-1741 17.3358,-1618.96 62.6798,-1473.98 104.883,-1378.18"/>
<ellipse fill="none" stroke="#9185dc" cx="194.378" cy="-1972.37" rx="4.00002" ry="4.00002"/>
<ellipse fill="#9185dc" stroke="#9185dc" cx="106.546" cy="-1374.45" rx="4.00002" ry="4.00002"/>
</g>
<!-- Profile&#45;&gt;Organization -->
<g id="edge115" class="edge"><title>Profile&#45;&gt;Organization</title>
<path fill="none" stroke="#c9241d" d="M250.101,-1876.39C233.967,-1823.68 218.11,-1771.87 206.457,-1733.8"/>
<ellipse fill="none" stroke="#c9241d" cx="251.37" cy="-1880.54" rx="4.00001" ry="4.00001"/>
<ellipse fill="#c9241d" stroke="#c9241d" cx="205.207" cy="-1729.72" rx="4.00001" ry="4.00001"/>
<g id="edge116" class="edge"><title>Profile&#45;&gt;Organization</title>
<path fill="none" stroke="#c2ae3a" d="M250.101,-1876.39C233.967,-1823.68 218.11,-1771.87 206.457,-1733.8"/>
<ellipse fill="none" stroke="#c2ae3a" cx="251.37" cy="-1880.54" rx="4.00001" ry="4.00001"/>
<ellipse fill="#c2ae3a" stroke="#c2ae3a" cx="205.207" cy="-1729.72" rx="4.00001" ry="4.00001"/>
</g>
<!-- Setting -->
<g id="node87" class="node"><title>Setting</title>
<path fill="none" stroke="black" d="M8629,-2951.5C8629,-2951.5 8849,-2951.5 8849,-2951.5 8855,-2951.5 8861,-2957.5 8861,-2963.5 8861,-2963.5 8861,-3045.5 8861,-3045.5 8861,-3051.5 8855,-3057.5 8849,-3057.5 8849,-3057.5 8629,-3057.5 8629,-3057.5 8623,-3057.5 8617,-3051.5 8617,-3045.5 8617,-3045.5 8617,-2963.5 8617,-2963.5 8617,-2957.5 8623,-2951.5 8629,-2951.5"/>
<text text-anchor="middle" x="8739" y="-3042.3" font-family="Times,serif" font-size="14.00">Setting</text>
<polyline fill="none" stroke="black" points="8617,-3034.5 8861,-3034.5 "/>
<text text-anchor="start" x="8625" y="-3019.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="8625" y="-3004.3" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="8625" y="-2989.3" font-family="Times,serif" font-size="14.00">value :text</text>
<text text-anchor="start" x="8625" y="-2974.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="8625" y="-2959.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
<g id="node88" class="node"><title>Setting</title>
<path fill="none" stroke="black" d="M8580,-2951.5C8580,-2951.5 8800,-2951.5 8800,-2951.5 8806,-2951.5 8812,-2957.5 8812,-2963.5 8812,-2963.5 8812,-3045.5 8812,-3045.5 8812,-3051.5 8806,-3057.5 8800,-3057.5 8800,-3057.5 8580,-3057.5 8580,-3057.5 8574,-3057.5 8568,-3051.5 8568,-3045.5 8568,-3045.5 8568,-2963.5 8568,-2963.5 8568,-2957.5 8574,-2951.5 8580,-2951.5"/>
<text text-anchor="middle" x="8690" y="-3042.3" font-family="Times,serif" font-size="14.00">Setting</text>
<polyline fill="none" stroke="black" points="8568,-3034.5 8812,-3034.5 "/>
<text text-anchor="start" x="8576" y="-3019.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="8576" y="-3004.3" font-family="Times,serif" font-size="14.00">name :character varying</text>
<text text-anchor="start" x="8576" y="-2989.3" font-family="Times,serif" font-size="14.00">value :text</text>
<text text-anchor="start" x="8576" y="-2974.3" font-family="Times,serif" font-size="14.00">created_at :timestamp without time zone</text>
<text text-anchor="start" x="8576" y="-2959.3" font-family="Times,serif" font-size="14.00">updated_at :timestamp without time zone</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 189 KiB

After

Width:  |  Height:  |  Size: 192 KiB

View File

@ -1,95 +1,105 @@
# How to add an authentication method to the FabLab ?
# How to add an authentication method to the Fab-Manager ?
First, take a look at the [OmniAuth list of strategies](https://github.com/intridea/omniauth/wiki/List-of-Strategies)
for the Strategy or Developer Strategy you want to add to the FabLab.
First, take a look at the [OmniAuth list of strategies](https://github.com/intridea/omniauth/wiki/List-of-Strategies) for the Strategy or Developer Strategy you want to add to the Fab-Manager.
For this guide, we will consider you want to add a generic *developer strategy*, like LDAP.
Create the OmniAuth implementation ( **lib/omni_auth/strategies/ldap_provider.rb** )
# first require the OmniAuth gem you added to your Gemfile (see the link above for a list of gems)
require 'omniauth-ldap'
module OmniAuth
module Strategies
# in the class name, replace Ldap with the kind of authentication you are implementing
class SsoLdapProvider < OmniAuth::Strategies::LDAP
# implement the logic here, see the gem specific documentation for more details
end
end
```ruby
# first require the OmniAuth gem you added to your Gemfile (see the link above for a list of gems)
require 'omniauth-ldap'
module OmniAuth
module Strategies
# in the class name, replace Ldap with the kind of authentication you are implementing
class SsoLdapProvider < OmniAuth::Strategies::LDAP
# implement the logic here, see the gem specific documentation for more details
end
end
end
```
Create the ActiveRecord models ( **from the terminal** )
# in the models names, replace Ldap with the kind of authentication you are implementing
# replace ldap_fields with the fields you need for implementing LDAP or whatever you are implementing
$ rails g model LdapProvider ...ldap_fields
$ rails g model LdapMapping ldap_provider:belongs_to local_field:string local_model:string ...ldap_fields
```bash
# in the models names, replace Ldap with the kind of authentication you are implementing
# replace ldap_fields with the fields you need for implementing LDAP or whatever you are implementing
rails g model LdapProvider ...ldap_fields
rails g model LdapMapping ldap_provider:belongs_to local_field:string local_model:string ...ldap_fields
```
Complete the Provider Model ( **app/model/ldap_provider.rb** )
class LdapProvider < ActiveRecord::Base
has_one :auth_provider, as: :providable
has_many :ldap_mappings, dependent: :destroy
accepts_nested_attributes_for :ldap_mappings, allow_destroy: true
# return here the fields you want to protect from being directly on the FabLab, typically mapped fields
def protected_fields
fields = []
ldap_mappings.each do |mapping|
fields.push(mapping.local_model+'.'+mapping.local_field)
end
fields
end
# return here the link the current users will have to follow to edit his profile on the SSO
def profile_url
# you can also create a profile_url field in the Database model
```ruby
class LdapProvider < ActiveRecord::Base
has_one :auth_provider, as: :providable
has_many :ldap_mappings, dependent: :destroy
accepts_nested_attributes_for :ldap_mappings, allow_destroy: true
# return the fields you want to protect from being directly managed by the Fab-Manager, typically mapped fields
def protected_fields
fields = []
ldap_mappings.each do |mapping|
fields.push(mapping.local_model+'.'+mapping.local_field)
end
fields
end
# return the link, that the current user will have to follow, to edit his profile on the SSO
def profile_url
# you can also create a profile_url field in the Database model
end
end
```
Whitelist your implementation's fields in the controller ( **app/controllers/api/auth_providers_controller.rb** )
```ruby
class API::AuthProvidersController < API::ApiController
...
private
def provider_params
if params['auth_provider']['providable_type'] == DatabaseProvider.name
...
elsif if params['auth_provider']['providable_type'] == LdapProvider.name
params.require(:auth_provider).permit(:name, :providable_type, providable_attributes: [
# list here your LdapProvider model's fields, followed by the mappings :
ldap_mappings_attributes: [
:id, :local_model, :local_field, ...
# add your other customs LdapMapping fields, don't forget the :_destroy symbol if
# you want your admin to be able to remove mappings
]
])
end
end
Whitelist your implementation fields in the controller ( **app/controllers/api/auth_providers_controller.rb** )
end
```
class API::AuthProvidersController < API::ApiController
...
private
def provider_params
if params['auth_provider']['providable_type'] == DatabaseProvider.name
...
elsif if params['auth_provider']['providable_type'] == LdapProvider.name
params.require(:auth_provider).permit(:name, :providable_type, providable_attributes: [
# list here your LdapProvider model's fields, followed by the mappings :
ldap_mappings_attributes: [
:id, :local_model, :local_field, ...
# add your other customs LdapMapping fields, don't forget the :_destroy symbol if
# you want your admin to be able to remove mappings
]
])
end
end
end
List the fields to display in the JSON API view ( **app/views/api/auth_providers/show.json.jbuilder** )
json.partial! 'api/auth_providers/auth_provider', auth_provider: @provider
...
if @provider.providable_type == LdapProvider.name
json.providable_attributes do
json.extract! @provider.providable, :id, ... # list LdapProvider fields here
json.ldap_mappings_attributes @provider.providable.ldap_mappings do |m|
json.extract! m, :id, :local_model, :local_field, ... # list LdapMapping fields here
end
end
```ruby
json.partial! 'api/auth_providers/auth_provider', auth_provider: @provider
...
if @provider.providable_type == LdapProvider.name
json.providable_attributes do
json.extract! @provider.providable, :id, ... # list LdapProvider fields here
json.ldap_mappings_attributes @provider.providable.ldap_mappings do |m|
json.extract! m, :id, :local_model, :local_field, ... # list LdapMapping fields here
end
end
end
```
Configure the initializer ( **config/initializers/devise.rb** )
require_relative '../../lib/omni_auth/omni_auth'
...
elsif active_provider.providable_type == LdapProvider.name
config.omniauth OmniAuth::Strategies::SsoLdapProvider.name.to_sym, # pass here the required parameters, see the gem documentation for details
end
```ruby
require_relative '../../lib/omni_auth/omni_auth'
...
elsif active_provider.providable_type == LdapProvider.name
config.omniauth OmniAuth::Strategies::SsoLdapProvider.name.to_sym, # pass here the required parameters, see the gem documentation for details
end
```
Finally you have to create an admin interface with AngularJS:
@ -97,34 +107,38 @@ Finally you have to create an admin interface with AngularJS:
- **app/assets/templates/admin/authentifications/_ldap_mapping.html.erb** must contains html partial to configure the LdapMappings, see _oauth2_mapping.html.erb for a working example
- **app/assets/javascript/controllers/admin/authentifications.coffee**
```coffeescript
## list of supported authentication methods
METHODS = {
...
'LdapProvider' : 'LDAP' # add the name of your ActiveRecord model class here as a hash key, associated with a human readable name as a hash value (string)
}
## list of supported authentication methods
METHODS = {
...
'LdapProvider' : 'LDAP' # add the name of your ActiveRecord model class here as a hash key, associated with a human readable name as a hash value (string)
}
Application.Controllers.controller "newAuthentificationController", ...
$scope.updateProvidable = ->
...
if $scope.provider.providable_type == 'LdapProvider'
# you may want to do some stuff to initialize your provider here
Application.Controllers.controller "newAuthentificationController", ...
$scope.updateProvidable = ->
...
if $scope.provider.providable_type == 'LdapProvider'
# you may want to do some stuff to initialize your provider here
$scope.registerProvider = ->
...
# === LdapProvider ===
else if $scope.provider.providable_type == 'LdapProvider'
# here you may want to do some data validation
# then: save the settings
AuthProvider.save auth_provider: $scope.provider, (provider) ->
# register was a success, display a message, redirect, etc.
$scope.registerProvider = ->
...
# === LdapProvider ===
else if $scope.provider.providable_type == 'LdapProvider'
# here you may want to do some data validation
# then: save the settings
AuthProvider.save auth_provider: $scope.provider, (provider) ->
# register was a success, display a message, redirect, etc.
```
And to include this interface into the existing one ( **app/assets/templates/admin/authentifications/edit.html.erb**)
<form role="form" name="providerForm" class="form-horizontal" novalidate>
...
<!-- Add the following ng-include inside the providerForm -->
<ng-include src="'<%= asset_path 'admin/authentifications/_ldap.html'%>'" ng-if="provider.providable_type == 'LdapProvider'"></ng-include>
</form>
```html
<form role="form" name="providerForm" class="form-horizontal" novalidate>
...
<!-- Add the following ng-include inside the providerForm -->
<ng-include src="'<%= asset_path 'admin/authentifications/_ldap.html'%>'" ng-if="provider.providable_type == 'LdapProvider'"></ng-include>
</form>
```
Do not forget that you can find examples and inspiration in the OAuth 2.0 implementation.

64
doc/sso_with_github.md Normal file
View File

@ -0,0 +1,64 @@
# How to configure Fab-manager to use a Single Sign-On authentication?
For this guide, we will use [GitHub](https://developer.github.com/v3/oauth/) as an example authentication provider, because uses OAuth 2.0 which is currently implemented in fab-manager, it has a standard implementation of that protocol and it is free to use for everyone.
- First, you must have a GitHub account. This is free, so create one if you don't have any.
Visit https://github.com/join?source=login to create an account.
- Secondly, you will need to register your fab-manager instance as an application in GitHub.
Visit https://github.com/settings/applications/new to register your instance.
- In `Application name`, we advise you to set the same name as your fab-manager's instance title.
- In `Homepage URL`, put the public URL where your fab-manager's instance is located (eg. https://example.com).
- In `Authorization callback URL`, you must specify an URL that will match this scheme: https://example.com/users/auth/oauth2-github/callback
- **example.com** is your own fab-manager's address
- **oauth2-github** match the provider's "strategy name" in the fab-manager.
It is composed of: **SSO's protocol**, _dash_, **slug of the provider's name**.
If you have a doubt about what it will be, start by creating the authentication provider in your fab-manager (see below), then the strategy's name will be shown in the providers list.
- You'll be redirected to a page displaying two important informations: your **Client ID** and your **Client Secret**.
- Now go to your fab-manager's instance, login as an administrator, go to `Users management` and `Authentication`.
Click `Add a new authentication provider`, and select _OAuth 2.0_ in the `Authentication type` drop-down list.
In `name`, you can set whatever you want, but you must be aware that:
1. You will need to type this name in a terminal to activate the provider, so prefer avoiding chars that must be escaped.
2. This name will be occasionally displayed to end users, so prefer sweet and speaking names.
3. The slug of this name is used in the callback URL provided to the SSO server (eg. /users/auth/oauth2-**github**/callback)
- Fulfill the form with the following parameters:
- **Common URL**: `https://github.com/login/oauth/` This is the common part in the URLs of the two following parameters.
- **Authorization endpoint**: `authorize` This URL can be found [here](https://developer.github.com/v3/oauth/).
- **Token Acquisition Endpoint**: `access_token` This URL can be found [here](https://developer.github.com/v3/oauth/).
- **Profile edition URL**: `https://github.com/settings/profile` This is the URL where you are directed when you click on `Edit profile` in your GitHub dashboard.
- **Client identifier**: Your Client ID, collected just before.
- **Client secret**: Your Client Secret, collected just before.
- Then you will need to define the matching of the fields between the fab-manager and what the external SSO can provide.
Please note that the only mandatory field is `User.uid`.
To continue with our GitHub example, you will need to look at [this documentation page](https://developer.github.com/v3/users/#get-the-authenticated-user) to know witch field can be mapped and how, and [this one](https://developer.github.com/v3/) to know the root URL of the API.
- **Model**: `User`
- **Field**: `uid`
- **API endpoint URL**: `https://api.github.com/user` Here you can set a complete URL **OR** only an endpoint referring to the previously set **Common URL**.
- **API type**: `JSON` Only JSON API are currently supported
- **API fields**: `id` According to the GitHub API documentation, this is the name of the JSON field which uniquely identify the user.
Once you have completed and validated the mapping's line, an information button will be available.
A click on it will show you the type of data expected from the API and, in some cases, you'll be able to configure a transformation.
For example, the `Profile.gender` field require a booleanrake diagram:all attribute but your API may return strings like `man / woman`.
In this case, you'll be able to configure a transformation for `man` <-> `true` and `woman` <-> `false`.
Now, you are free to map more fields, like `Profile.github` to `html_url`, or `Profile.avatar` to `avatar_url`...
- Once you are done, your newly created authentication provider, will be marked as **Pending** in the authentication providers list.
To set it as the current active provider, you must open a terminal on the hosting server (and/or container) and run the following commands:
```bash
# replace GitHub with the name of the provider you just created
rake fablab:switch_auth_provider[GitHub]
```
- As the command just prompted you, you have to re-compile the assets (with eg, `rake tmp:clear` - this vary with the method you used to deploy your instance)
- Then restart the web-server or the container.
- Finally, to notify all existing users about the change (and send them their migration code/link), run:
```bash
rake fablab:notify_auth_changed
```

View File

@ -363,5 +363,6 @@ docker-compose pull fabmanager
docker-compose stop fabmanager
sudo rm -rf fabmanager/public/assets
docker-compose run --rm fabmanager bundle exec rake assets:precompile
docker-compose start fabmanager
docker-compose down
docker-compose up -d
```

View File

@ -16,7 +16,7 @@ DEFAULT_HOST=demo.fab-manager.com
DEFAULT_PROTOCOL=http
DELIVERY_METHOD=smtp
SMTP_ADDRESS=smtp.mailgun.org
SMTP_ADDRESS=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USER_NAME=
SMTP_PASSWORD=
@ -31,6 +31,8 @@ TWITTER_CONSUMER_SECRET=
TWITTER_ACCESS_TOKEN=
TWITTER_ACCESS_TOKEN_SECRET=
FACEBOOK_APP_ID=
RAILS_LOCALE=fr
MOMENT_LOCALE=fr
SUMMERNOTE_LOCALE=fr-FR
@ -44,10 +46,13 @@ TIME_ZONE=Paris
WEEK_STARTING_DAY=monday
D3_DATE_FORMAT=%d/%m/%y
UIB_DATE_FORMAT=dd/MM/yyyy
EXCEL_DATE_FORMAT=dd/mm/yyyy
OPENLAB_APP_SECRET=fSF9jZEWxjHyqjAzzg34jd92
OPENLAB_APP_ID=xLn9CmryyURNNHZiDRYVRXbv
OPENLAB_APP_SECRET=
OPENLAB_APP_ID=
OPENLAB_BASE_URI=https://openprojects.fab-manager.com
NAVINUM_API_LOGIN:
NAVINUM_API_PASSWORD:
LOG_LEVEL=debug

View File

@ -54,12 +54,62 @@ module OmniAuth
@parsed_info ||= Hash.new
unless @parsed_info.size > 0
OmniAuth::Strategies::SsoOauth2Provider.active_provider.providable.o_auth2_mappings.each do |mapping|
@parsed_info[(mapping.local_model+'.'+mapping.local_field).to_sym] = raw_info[mapping.api_endpoint.to_sym][mapping.api_field]
if mapping.transformation
case mapping.transformation['type']
## INTEGER
when 'integer'
mapping.transformation['mapping'].each do |m|
if m['from'] == raw_info[mapping.api_endpoint.to_sym][mapping.api_field]
@parsed_info[local_sym(mapping)] = m['to']
break
end
end
# if no transformation had set any value, set the raw value
unless @parsed_info[local_sym(mapping)]
@parsed_info[local_sym(mapping)] = raw_info[mapping.api_endpoint.to_sym][mapping.api_field]
end
## BOOLEAN
when 'boolean'
@parsed_info[local_sym(mapping)] = !(raw_info[mapping.api_endpoint.to_sym][mapping.api_field] == mapping.transformation['false_value'])
@parsed_info[local_sym(mapping)] = (raw_info[mapping.api_endpoint.to_sym][mapping.api_field] == mapping.transformation['true_value'])
## DATE
when 'date'
case mapping.transformation['format']
when 'iso8601'
@parsed_info[local_sym(mapping)] = DateTime.iso8601(raw_info[mapping.api_endpoint.to_sym][mapping.api_field])
when 'rfc2822'
@parsed_info[local_sym(mapping)] = DateTime.rfc2822(raw_info[mapping.api_endpoint.to_sym][mapping.api_field])
when 'rfc3339'
@parsed_info[local_sym(mapping)] = DateTime.rfc3339(raw_info[mapping.api_endpoint.to_sym][mapping.api_field])
when 'timestamp-s'
@parsed_info[local_sym(mapping)] = DateTime.strptime(raw_info[mapping.api_endpoint.to_sym][mapping.api_field],'%s')
when 'timestamp-ms'
@parsed_info[local_sym(mapping)] = DateTime.strptime(raw_info[mapping.api_endpoint.to_sym][mapping.api_field],'%Q')
else
@parsed_info[local_sym(mapping)] = DateTime.parse(raw_info[mapping.api_endpoint.to_sym][mapping.api_field])
end
## OTHER TRANSFORMATIONS (not supported)
else
@parsed_info[local_sym(mapping)] = raw_info[mapping.api_endpoint.to_sym][mapping.api_field]
end
## NO TRANSFORMATION
else
@parsed_info[local_sym(mapping)] = raw_info[mapping.api_endpoint.to_sym][mapping.api_field]
end
end
end
@parsed_info
end
private
def local_sym(mapping)
(mapping.local_model+'.'+mapping.local_field).to_sym
end
end
end
end

View File

@ -215,6 +215,8 @@ namespace :fablab do
desc 'notify users that the auth provider has changed'
task notify_auth_changed: :environment do
I18n.locale = I18n.default_locale
# notify every users if the provider is not local database provider
if AuthProvider.active.providable_type != DatabaseProvider.name
User.all.each do |user|

View File

@ -1,11 +1,13 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
event_id:
price_category_id:
amount: 1
id: 1
event_id: 1
price_category_id: 1
amount: 1500
two:
event_id:
price_category_id:
amount: 1
id: 2
event_id: 2
price_category_id: 1
amount: 1700

View File

@ -1,9 +1,11 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
youngs:
id: 1
name: "- de 25 ans"
conditions: "Tarif réservé aux jeunes de moins de 25 ans"
two:
unemployed:
id: 2
name: "chômeurs"
conditions: "Tarif préférentiel pour les demandeurs d'emploi pouvant justifier de leur situation."

View File

@ -1,11 +1 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
reservation_id:
event_price_category_id:
booked: 1
two:
reservation_id:
event_price_category_id:
booked: 1

View File

@ -113,4 +113,92 @@ class EventsTest < ActionDispatch::IntegrationTest
assert_equal 20, e.nb_total_places, 'Total number of places was not updated'
assert_equal 18, e.nb_free_places, 'Number of free places was not updated'
end
test 'create event with custom price and reserve it with success' do
price_category = PriceCategory.first
# First, we create a new event
post '/api/events',
{
event: {
title: 'Electronics initiation',
description: 'A workshop about electronics and the abilities to create robots.',
start_date: 1.week.from_now.utc + 2.days,
start_time: 1.week.from_now.utc.change({hour: 18}) + 2.days,
end_date: 1.week.from_now.utc + 2.days,
end_time: 1.week.from_now.utc.change({hour: 22}) + 2.days,
category_id: Category.last.id,
amount: 20,
nb_total_places: 10,
event_price_categories_attributes: [
{
price_category_id: price_category.id.to_s,
amount: 16.to_s
}
]
}
}.to_json,
default_headers
# Check response format & status
assert_equal 201, response.status, response.body
assert_equal Mime::JSON, response.content_type
# Check the event was created correctly
event = json_response(response.body)
e = Event.where(id: event[:id]).first
assert_not_nil e, 'Event was not created in database'
# Check the places numbers were set successfully
e = Event.where(id: event[:id]).first
assert_equal 10, e.nb_total_places, 'Total number of places was not updated'
assert_equal 10, e.nb_free_places, 'Number of free places was not updated'
# Now, let's make a reservation on this event
post '/api/reservations',
{
reservation: {
user_id: User.find_by_username('lseguin').id,
reservable_id: e.id,
reservable_type: 'Event',
nb_reserve_places: 4,
slots_attributes: [
{
start_at: e.availability.start_at,
end_at: e.availability.end_at,
availability_id: e.availability.id,
offered: false
}
],
tickets_attributes: [
{
event_price_category_id: e.event_price_categories.first.id,
booked: 4
}
]
}
}.to_json,
default_headers
# Check response format & status
assert_equal 201, response.status, response.body
assert_equal Mime::JSON, response.content_type
# Check the reservation match the required event
reservation = json_response(response.body)
r = Reservation.find(reservation[:id])
assert_equal e.id, r.reservable_id
assert_equal 'Event', r.reservable_type
# Check the remaining places were updated successfully
e = Event.where(id: event[:id]).first
assert_equal 2, e.nb_free_places, 'Number of free places was not updated'
# Check the resulting invoice generation and it has right price
assert_invoice_pdf r.invoice
assert_equal (4 * 20) + (4 * 16), r.invoice.total / 100.0
end
end

View File

@ -5,7 +5,7 @@ module Reservations
@user_with_subscription = User.with_role(:member).with_subscription.second
end
test "user without subscription reserves a machine with success" do
test 'user without subscription reserves a machine with success' do
login_as(@user_without_subscription, scope: :user)
machine = Machine.find(6)
@ -15,8 +15,9 @@ module Reservations
invoice_count = Invoice.count
invoice_items_count = InvoiceItem.count
users_credit_count = UsersCredit.count
subscriptions_count = Subscription.count
VCR.use_cassette("reservations_create_for_machine_without_subscription_success") do
VCR.use_cassette('reservations_create_for_machine_without_subscription_success') do
post reservations_path, { reservation: {
user_id: @user_without_subscription.id,
reservable_id: machine.id,
@ -37,6 +38,7 @@ module Reservations
assert_equal invoice_count + 1, Invoice.count
assert_equal invoice_items_count + 1, InvoiceItem.count
assert_equal users_credit_count, UsersCredit.count
assert_equal subscriptions_count, Subscription.count
# reservation assertions
reservation = Reservation.last
@ -65,7 +67,7 @@ module Reservations
assert_not_empty Notification.where(attached_object: reservation)
end
test "user without subscription reserves a machine with error" do
test 'user without subscription reserves a machine with error' do
login_as(@user_without_subscription, scope: :user)
machine = Machine.find(6)
@ -76,7 +78,7 @@ module Reservations
invoice_items_count = InvoiceItem.count
notifications_count = Notification.count
VCR.use_cassette("reservations_create_for_machine_without_subscription_error") do
VCR.use_cassette('reservations_create_for_machine_without_subscription_error') do
post reservations_path, { reservation: {
user_id: @user_without_subscription.id,
reservable_id: machine.id,
@ -99,7 +101,7 @@ module Reservations
assert_equal notifications_count, Notification.count
end
test "user without subscription reserves a training with success" do
test 'user without subscription reserves a training with success' do
login_as(@user_without_subscription, scope: :user)
training = Training.first
@ -109,7 +111,7 @@ module Reservations
invoice_count = Invoice.count
invoice_items_count = InvoiceItem.count
VCR.use_cassette("reservations_create_for_training_without_subscription_success") do
VCR.use_cassette('reservations_create_for_training_without_subscription_success') do
post reservations_path, { reservation: {
user_id: @user_without_subscription.id,
reservable_id: training.id,
@ -157,7 +159,7 @@ module Reservations
assert_not_empty Notification.where(attached_object: reservation)
end
test "user with subscription reserves a machine with success" do
test 'user with subscription reserves a machine with success' do
login_as(@user_with_subscription, scope: :user)
plan = @user_with_subscription.subscribed_plan
@ -169,7 +171,7 @@ module Reservations
invoice_items_count = InvoiceItem.count
users_credit_count = UsersCredit.count
VCR.use_cassette("reservations_create_for_machine_with_subscription_success") do
VCR.use_cassette('reservations_create_for_machine_with_subscription_success') do
post reservations_path, { reservation: {
user_id: @user_with_subscription.id,
reservable_id: machine.id,
@ -230,7 +232,7 @@ module Reservations
assert_not_empty Notification.where(attached_object: reservation)
end
test "user with subscription reserves the FIRST training with success" do
test 'user with subscription reserves the FIRST training with success' do
login_as(@user_with_subscription, scope: :user)
plan = @user_with_subscription.subscribed_plan
plan.update!(is_rolling: true)
@ -242,7 +244,7 @@ module Reservations
invoice_count = Invoice.count
invoice_items_count = InvoiceItem.count
VCR.use_cassette("reservations_create_for_training_with_subscription_success") do
VCR.use_cassette('reservations_create_for_training_with_subscription_success') do
post reservations_path, { reservation: {
user_id: @user_with_subscription.id,
reservable_id: training.id,
@ -293,7 +295,7 @@ module Reservations
assert_equal reservation.slots.first.start_at + plan.duration, @user_with_subscription.subscription.expired_at
end
test "user reserves a machine and pay by wallet with success" do
test 'user reserves a machine and pay by wallet with success' do
@vlonchamp = User.find_by(username: 'vlonchamp')
login_as(@vlonchamp, scope: :user)
@ -306,7 +308,7 @@ module Reservations
users_credit_count = UsersCredit.count
wallet_transactions_count = WalletTransaction.count
VCR.use_cassette("reservations_create_for_machine_and_pay_wallet_success") do
VCR.use_cassette('reservations_create_for_machine_and_pay_wallet_success') do
post reservations_path, { reservation: {
user_id: @vlonchamp.id,
reservable_id: machine.id,
@ -364,7 +366,7 @@ module Reservations
assert_equal transaction.amount, invoice.wallet_amount / 100.0
end
test "user reserves a training and plan by wallet with success" do
test 'user reserves a training and plan by wallet with success' do
@vlonchamp = User.find_by(username: 'vlonchamp')
login_as(@vlonchamp, scope: :user)
@ -377,7 +379,7 @@ module Reservations
invoice_items_count = InvoiceItem.count
wallet_transactions_count = WalletTransaction.count
VCR.use_cassette("reservations_create_for_training_and_plan_by_pay_wallet_success") do
VCR.use_cassette('reservations_create_for_training_and_plan_by_pay_wallet_success') do
post reservations_path, { reservation: {
user_id: @user_without_subscription.id,
reservable_id: training.id,
@ -430,5 +432,127 @@ module Reservations
assert_equal transaction.amount, 10
assert_equal transaction.amount, invoice.wallet_amount / 100.0
end
test 'user reserves a machine and a subscription using a coupon with success' do
login_as(@user_without_subscription, scope: :user)
machine = Machine.find(6)
plan = Plan.where(group_id: @user_without_subscription.group_id).first
availability = machine.availabilities.first
reservations_count = Reservation.count
invoice_count = Invoice.count
invoice_items_count = InvoiceItem.count
subscriptions_count = Subscription.count
users_credit_count = UsersCredit.count
VCR.use_cassette('reservations_machine_and_plan_using_coupon_success') do
post reservations_path, {
reservation: {
user_id: @user_without_subscription.id,
reservable_id: machine.id,
reservable_type: machine.class.name,
card_token: stripe_card_token,
slots_attributes: [
{ start_at: availability.start_at.to_s(:iso8601),
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
availability_id: availability.id
}
],
plan_id: plan.id
},
coupon_code: 'SUNNYFABLAB'
}.to_json, default_headers
end
# general assertions
assert_equal 201, response.status
assert_equal reservations_count + 1, Reservation.count
assert_equal invoice_count + 1, Invoice.count
assert_equal invoice_items_count + 2, InvoiceItem.count
assert_equal users_credit_count, UsersCredit.count
assert_equal subscriptions_count + 1, Subscription.count
# reservation assertions
reservation = Reservation.last
assert reservation.invoice
refute reservation.stp_invoice_id.blank?
assert_equal 2, reservation.invoice.invoice_items.count
# invoice assertions
invoice = reservation.invoice
refute invoice.stp_invoice_id.blank?
refute invoice.total.blank?
# invoice_items assertions
## reservation
reservation_item = invoice.invoice_items.where(subscription_id: nil).first
assert_not_nil reservation_item
assert reservation_item.stp_invoice_item_id
assert_equal reservation_item.amount, machine.prices.find_by(group_id: @user_without_subscription.group_id, plan_id: plan.id).amount
## subscription
subscription_item = invoice.invoice_items.where.not(subscription_id: nil).first
assert_not_nil subscription_item
subscription = Subscription.find(subscription_item.subscription_id)
assert subscription_item.stp_invoice_item_id
assert_equal subscription_item.amount, plan.amount
assert_equal subscription.plan_id, plan.id
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
assert_invoice_pdf invoice
VCR.use_cassette('reservations_machine_and_plan_using_coupon_retrieve_invoice_from_stripe') do
stp_invoice = Stripe::Invoice.retrieve(invoice.stp_invoice_id)
assert_equal stp_invoice.total, invoice.total
end
# notifications
assert_not_empty Notification.where(attached_object: reservation)
assert_not_empty Notification.where(attached_object: subscription)
end
test 'user reserves a training with an expired coupon with error' do
login_as(@user_without_subscription, scope: :user)
training = Training.find(1)
availability = training.availabilities.first
reservations_count = Reservation.count
invoice_count = Invoice.count
invoice_items_count = InvoiceItem.count
notifications_count = Notification.count
VCR.use_cassette('reservations_training_with_expired_coupon_error') do
post reservations_path, {
reservation: {
user_id: @user_without_subscription.id,
reservable_id: training.id,
reservable_type: training.class.name,
card_token: stripe_card_token,
slots_attributes: [
{ start_at: availability.start_at.to_s(:iso8601),
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
availability_id: availability.id
}
],
},
coupon_code: 'XMAS10'
}.to_json, default_headers
end
# general assertions
assert_equal 422, response.status
assert_equal reservations_count, Reservation.count
assert_equal invoice_count, Invoice.count
assert_equal invoice_items_count, InvoiceItem.count
assert_equal notifications_count, Notification.count
end
end
end

View File

@ -1,7 +1,9 @@
require 'test_helper'
class EventPriceCategoryTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
test "event price's category cannot be empty" do
epc = EventPriceCategory.new({price_category_id: 1, event_id: 3})
assert epc.invalid?
assert epc.errors[:amount].present?
end
end

View File

@ -1,7 +1,15 @@
require 'test_helper'
class PriceCategoryTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
test 'price category name must be unique' do
pc = PriceCategory.new({name: '- DE 25 ANS', conditions: 'Tarif préférentiel pour les jeunes'})
assert pc.invalid?
assert pc.errors[:name].present?
end
test 'associated price category cannot be destroyed' do
pc = PriceCategory.find(1)
assert_not pc.safe_destroy
assert_not_empty PriceCategory.where(id: 1)
end
end

View File

@ -1,7 +1,9 @@
require 'test_helper'
class TicketTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
test "ticket must have at least 1 seat" do
t = Ticket.new({event_price_category_id: 1, booked: -1})
assert t.invalid?
assert t.errors[:booked].present?
end
end

View File

@ -14,7 +14,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -106,7 +106,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -186,7 +186,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -266,7 +266,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -380,7 +380,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -494,7 +494,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -574,7 +574,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -708,7 +708,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -848,7 +848,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -926,7 +926,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -1004,7 +1004,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
@ -1082,7 +1082,7 @@ http_interactions:
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_mGokO9TGtrVxMOyK4yZiktBE
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:

View File

@ -0,0 +1,189 @@
---
http_interactions:
- request:
method: get
uri: https://api.stripe.com/v1/invoices/in_18rNSq2sOmf47Nz91hxlGSa7
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:25:04 GMT
Content-Type:
- application/json
Content-Length:
- '3362'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99l6aCLd0IC3Qn
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "in_18rNSq2sOmf47Nz91hxlGSa7",
"object": "invoice",
"amount_due": 3825,
"application_fee": null,
"attempt_count": 1,
"attempted": true,
"charge": "ch_18rNSq2sOmf47Nz9Z8EuuyI8",
"closed": true,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473321652,
"description": null,
"discount": null,
"ending_balance": 0,
"forgiven": false,
"lines": {
"object": "list",
"data": [
{
"id": "ii_18rNSp2sOmf47Nz9S0rJVP2a",
"object": "line_item",
"amount": -450,
"currency": "usd",
"description": "coupon SUNNYFABLAB",
"discountable": false,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321651,
"end": 1473321651
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
},
{
"id": "ii_18rNSm2sOmf47Nz9R11Svoer",
"object": "line_item",
"amount": -225,
"currency": "usd",
"description": "coupon SUNNYFABLAB",
"discountable": false,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321648,
"end": 1473321648
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
},
{
"id": "ii_18rNSm2sOmf47Nz9avgL9KyW",
"object": "line_item",
"amount": 1500,
"currency": "usd",
"description": "FORM1+ imprimante 3D September 04, 2016 14:00 - 03:00 PM",
"discountable": true,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321648,
"end": 1473321648
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
},
{
"id": "sub_99gqb47NmX9r79",
"object": "line_item",
"amount": 3000,
"currency": "usd",
"description": null,
"discountable": true,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321652,
"end": 1475913652
},
"plan": {
"id": "mensuel-standard-month-20160404171519",
"object": "plan",
"amount": 3000,
"created": 1459782921,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"name": "Mensuel - standard, association - month",
"statement_descriptor": null,
"trial_period_days": null
},
"proration": false,
"quantity": 1,
"subscription": null,
"type": "subscription"
}
],
"has_more": false,
"total_count": 4,
"url": "/v1/invoices/in_18rNSq2sOmf47Nz91hxlGSa7/lines"
},
"livemode": false,
"metadata": {},
"next_payment_attempt": null,
"paid": true,
"period_end": 1473321652,
"period_start": 1473321652,
"receipt_number": null,
"starting_balance": 0,
"statement_descriptor": null,
"subscription": "sub_99gqb47NmX9r79",
"subtotal": 3825,
"tax": null,
"tax_percent": null,
"total": 3825,
"webhooks_delivered_at": 1473321652
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:25:04 GMT
recorded_with: VCR 3.0.1

View File

@ -0,0 +1,1334 @@
---
http_interactions:
- request:
method: post
uri: https://api.stripe.com/v1/tokens
body:
encoding: UTF-8
string: card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '81'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:47 GMT
Content-Type:
- application/json
Content-Length:
- '779'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqPbGrfRTnyZ
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "tok_18rNSl2sOmf47Nz9cTGhyMRc",
"object": "token",
"card": {
"id": "card_18rNSk2sOmf47Nz9h1cf7obf",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"cvc_check": "unchecked",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2017,
"fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit",
"last4": "4242",
"metadata": {},
"name": null,
"tokenization_method": null
},
"client_ip": "90.52.44.103",
"created": 1473321647,
"livemode": false,
"type": "card",
"used": false
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:47 GMT
- request:
method: post
uri: https://api.stripe.com/v1/invoiceitems
body:
encoding: UTF-8
string: customer=cus_8Di1wjdVktv5kt&amount=1500&currency=usd&description=FORM1%2B+imprimante+3D+September+04%2C+2016+14%3A00+-+03%3A00+PM
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '129'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:48 GMT
Content-Type:
- application/json
Content-Length:
- '473'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqddasRVKxn2
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "ii_18rNSm2sOmf47Nz9avgL9KyW",
"object": "invoiceitem",
"amount": 1500,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473321648,
"description": "FORM1+ imprimante 3D September 04, 2016 14:00 - 03:00 PM",
"discountable": true,
"invoice": null,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321648,
"end": 1473321648
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:48 GMT
- request:
method: post
uri: https://api.stripe.com/v1/invoiceitems
body:
encoding: UTF-8
string: customer=cus_8Di1wjdVktv5kt&amount=-225&currency=usd&description=coupon+SUNNYFABLAB
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '83'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:48 GMT
Content-Type:
- application/json
Content-Length:
- '436'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gq27qOy8Dn3R
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "ii_18rNSm2sOmf47Nz9R11Svoer",
"object": "invoiceitem",
"amount": -225,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473321648,
"description": "coupon SUNNYFABLAB",
"discountable": false,
"invoice": null,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321648,
"end": 1473321648
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:49 GMT
- request:
method: get
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:49 GMT
Content-Type:
- application/json
Content-Length:
- '1408'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqbfntlVYpyJ
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "cus_8Di1wjdVktv5kt",
"object": "customer",
"account_balance": 0,
"created": 1459948888,
"currency": "usd",
"default_source": "card_17z7CT2sOmf47Nz9wtWkhGor",
"delinquent": false,
"description": "Jean Dupond",
"discount": null,
"email": "jean.dupond@gmail.com",
"livemode": false,
"metadata": {},
"shipping": null,
"sources": {
"object": "list",
"data": [
{
"id": "card_17z7CT2sOmf47Nz9wtWkhGor",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"customer": "cus_8Di1wjdVktv5kt",
"cvc_check": "pass",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2017,
"fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit",
"last4": "4242",
"metadata": {},
"name": null,
"tokenization_method": null
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/sources"
},
"subscriptions": {
"object": "list",
"data": [],
"has_more": false,
"total_count": 0,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions"
}
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:49 GMT
- request:
method: get
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:50 GMT
Content-Type:
- application/json
Content-Length:
- '1408'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqvJz00HL9sk
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "cus_8Di1wjdVktv5kt",
"object": "customer",
"account_balance": 0,
"created": 1459948888,
"currency": "usd",
"default_source": "card_17z7CT2sOmf47Nz9wtWkhGor",
"delinquent": false,
"description": "Jean Dupond",
"discount": null,
"email": "jean.dupond@gmail.com",
"livemode": false,
"metadata": {},
"shipping": null,
"sources": {
"object": "list",
"data": [
{
"id": "card_17z7CT2sOmf47Nz9wtWkhGor",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"customer": "cus_8Di1wjdVktv5kt",
"cvc_check": "pass",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2017,
"fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit",
"last4": "4242",
"metadata": {},
"name": null,
"tokenization_method": null
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/sources"
},
"subscriptions": {
"object": "list",
"data": [],
"has_more": false,
"total_count": 0,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions"
}
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:50 GMT
- request:
method: post
uri: https://api.stripe.com/v1/invoiceitems
body:
encoding: UTF-8
string: customer=cus_8Di1wjdVktv5kt&amount=-450&currency=usd&description=coupon+SUNNYFABLAB
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '83'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:51 GMT
Content-Type:
- application/json
Content-Length:
- '436'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gq9UCtuA1CdL
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "ii_18rNSp2sOmf47Nz9S0rJVP2a",
"object": "invoiceitem",
"amount": -450,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473321651,
"description": "coupon SUNNYFABLAB",
"discountable": false,
"invoice": null,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321651,
"end": 1473321651
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:51 GMT
- request:
method: post
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions
body:
encoding: UTF-8
string: plan=mensuel-standard-month-20160404171519&source=tok_18rNSl2sOmf47Nz9cTGhyMRc
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '78'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:52 GMT
Content-Type:
- application/json
Content-Length:
- '867'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gq6A5SZpD1qQ
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "sub_99gqb47NmX9r79",
"object": "subscription",
"application_fee_percent": null,
"cancel_at_period_end": false,
"canceled_at": null,
"created": 1473321652,
"current_period_end": 1475913652,
"current_period_start": 1473321652,
"customer": "cus_8Di1wjdVktv5kt",
"discount": null,
"ended_at": null,
"livemode": false,
"metadata": {},
"plan": {
"id": "mensuel-standard-month-20160404171519",
"object": "plan",
"amount": 3000,
"created": 1459782921,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"name": "Mensuel - standard, association - month",
"statement_descriptor": null,
"trial_period_days": null
},
"quantity": 1,
"start": 1473321652,
"status": "active",
"tax_percent": null,
"trial_end": null,
"trial_start": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:53 GMT
- request:
method: get
uri: https://api.stripe.com/v1/invoices?customer=cus_8Di1wjdVktv5kt&limit=1
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:53 GMT
Content-Type:
- application/json
Content-Length:
- '3963'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqm0fOzzj3EP
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"object": "list",
"data": [
{
"id": "in_18rNSq2sOmf47Nz91hxlGSa7",
"object": "invoice",
"amount_due": 3825,
"application_fee": null,
"attempt_count": 1,
"attempted": true,
"charge": "ch_18rNSq2sOmf47Nz9Z8EuuyI8",
"closed": true,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473321652,
"description": null,
"discount": null,
"ending_balance": 0,
"forgiven": false,
"lines": {
"object": "list",
"data": [
{
"id": "ii_18rNSp2sOmf47Nz9S0rJVP2a",
"object": "line_item",
"amount": -450,
"currency": "usd",
"description": "coupon SUNNYFABLAB",
"discountable": false,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321651,
"end": 1473321651
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
},
{
"id": "ii_18rNSm2sOmf47Nz9R11Svoer",
"object": "line_item",
"amount": -225,
"currency": "usd",
"description": "coupon SUNNYFABLAB",
"discountable": false,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321648,
"end": 1473321648
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
},
{
"id": "ii_18rNSm2sOmf47Nz9avgL9KyW",
"object": "line_item",
"amount": 1500,
"currency": "usd",
"description": "FORM1+ imprimante 3D September 04, 2016 14:00 - 03:00 PM",
"discountable": true,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321648,
"end": 1473321648
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
},
{
"id": "sub_99gqb47NmX9r79",
"object": "line_item",
"amount": 3000,
"currency": "usd",
"description": null,
"discountable": true,
"livemode": false,
"metadata": {},
"period": {
"start": 1473321652,
"end": 1475913652
},
"plan": {
"id": "mensuel-standard-month-20160404171519",
"object": "plan",
"amount": 3000,
"created": 1459782921,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"name": "Mensuel - standard, association - month",
"statement_descriptor": null,
"trial_period_days": null
},
"proration": false,
"quantity": 1,
"subscription": null,
"type": "subscription"
}
],
"has_more": false,
"total_count": 4,
"url": "/v1/invoices/in_18rNSq2sOmf47Nz91hxlGSa7/lines"
},
"livemode": false,
"metadata": {},
"next_payment_attempt": null,
"paid": true,
"period_end": 1473321652,
"period_start": 1473321652,
"receipt_number": null,
"starting_balance": 0,
"statement_descriptor": null,
"subscription": "sub_99gqb47NmX9r79",
"subtotal": 3825,
"tax": null,
"tax_percent": null,
"total": 3825,
"webhooks_delivered_at": 1473321652
}
],
"has_more": true,
"url": "/v1/invoices"
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:53 GMT
- request:
method: get
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:54 GMT
Content-Type:
- application/json
Content-Length:
- '2490'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqRCzmQJIDBa
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "cus_8Di1wjdVktv5kt",
"object": "customer",
"account_balance": 0,
"created": 1459948888,
"currency": "usd",
"default_source": "card_18rNSk2sOmf47Nz9h1cf7obf",
"delinquent": false,
"description": "Jean Dupond",
"discount": null,
"email": "jean.dupond@gmail.com",
"livemode": false,
"metadata": {},
"shipping": null,
"sources": {
"object": "list",
"data": [
{
"id": "card_18rNSk2sOmf47Nz9h1cf7obf",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"customer": "cus_8Di1wjdVktv5kt",
"cvc_check": "pass",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2017,
"fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit",
"last4": "4242",
"metadata": {},
"name": null,
"tokenization_method": null
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/sources"
},
"subscriptions": {
"object": "list",
"data": [
{
"id": "sub_99gqb47NmX9r79",
"object": "subscription",
"application_fee_percent": null,
"cancel_at_period_end": false,
"canceled_at": null,
"created": 1473321652,
"current_period_end": 1475913652,
"current_period_start": 1473321652,
"customer": "cus_8Di1wjdVktv5kt",
"discount": null,
"ended_at": null,
"livemode": false,
"metadata": {},
"plan": {
"id": "mensuel-standard-month-20160404171519",
"object": "plan",
"amount": 3000,
"created": 1459782921,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"name": "Mensuel - standard, association - month",
"statement_descriptor": null,
"trial_period_days": null
},
"quantity": 1,
"start": 1473321652,
"status": "active",
"tax_percent": null,
"trial_end": null,
"trial_start": null
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions"
}
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:54 GMT
- request:
method: get
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_99gqb47NmX9r79
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:55 GMT
Content-Type:
- application/json
Content-Length:
- '867'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqhmTVKcwbNF
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "sub_99gqb47NmX9r79",
"object": "subscription",
"application_fee_percent": null,
"cancel_at_period_end": false,
"canceled_at": null,
"created": 1473321652,
"current_period_end": 1475913652,
"current_period_start": 1473321652,
"customer": "cus_8Di1wjdVktv5kt",
"discount": null,
"ended_at": null,
"livemode": false,
"metadata": {},
"plan": {
"id": "mensuel-standard-month-20160404171519",
"object": "plan",
"amount": 3000,
"created": 1459782921,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"name": "Mensuel - standard, association - month",
"statement_descriptor": null,
"trial_period_days": null
},
"quantity": 1,
"start": 1473321652,
"status": "active",
"tax_percent": null,
"trial_end": null,
"trial_start": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:55 GMT
- request:
method: delete
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/subscriptions/sub_99gqb47NmX9r79?at_period_end=true
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:56 GMT
Content-Type:
- application/json
Content-Length:
- '872'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqPGBMCEM6Ec
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "sub_99gqb47NmX9r79",
"object": "subscription",
"application_fee_percent": null,
"cancel_at_period_end": true,
"canceled_at": 1473321656,
"created": 1473321652,
"current_period_end": 1475913652,
"current_period_start": 1473321652,
"customer": "cus_8Di1wjdVktv5kt",
"discount": null,
"ended_at": null,
"livemode": false,
"metadata": {},
"plan": {
"id": "mensuel-standard-month-20160404171519",
"object": "plan",
"amount": 3000,
"created": 1459782921,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"name": "Mensuel - standard, association - month",
"statement_descriptor": null,
"trial_period_days": null
},
"quantity": 1,
"start": 1473321652,
"status": "active",
"tax_percent": null,
"trial_end": null,
"trial_start": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:57 GMT
- request:
method: get
uri: https://api.stripe.com/v1/invoiceitems/ii_18rNSm2sOmf47Nz9avgL9KyW
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:58 GMT
Content-Type:
- application/json
Content-Length:
- '498'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqJIQqEHVCZ0
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "ii_18rNSm2sOmf47Nz9avgL9KyW",
"object": "invoiceitem",
"amount": 1500,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473321648,
"description": "FORM1+ imprimante 3D September 04, 2016 14:00 - 03:00 PM",
"discountable": true,
"invoice": "in_18rNSq2sOmf47Nz91hxlGSa7",
"livemode": false,
"metadata": {},
"period": {
"start": 1473321648,
"end": 1473321648
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:58 GMT
- request:
method: get
uri: https://api.stripe.com/v1/invoiceitems/ii_18rNSm2sOmf47Nz9avgL9KyW
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 08:00:58 GMT
Content-Type:
- application/json
Content-Length:
- '498'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99gqJk9T35fI7H
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "ii_18rNSm2sOmf47Nz9avgL9KyW",
"object": "invoiceitem",
"amount": 1500,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473321648,
"description": "FORM1+ imprimante 3D September 04, 2016 14:00 - 03:00 PM",
"discountable": true,
"invoice": "in_18rNSq2sOmf47Nz91hxlGSa7",
"livemode": false,
"metadata": {},
"period": {
"start": 1473321648,
"end": 1473321648
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 08:00:58 GMT
recorded_with: VCR 3.0.1

View File

@ -0,0 +1,997 @@
---
http_interactions:
- request:
method: post
uri: https://api.stripe.com/v1/tokens
body:
encoding: UTF-8
string: card[number]=4242424242424242&card[exp_month]=4&card[exp_year]=2017&card[cvc]=314
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '81'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:45:30 GMT
Content-Type:
- application/json
Content-Length:
- '779'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99lRiyf8VYL75c
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "tok_18rRuI2sOmf47Nz9nl5ZXXoF",
"object": "token",
"card": {
"id": "card_18rRuI2sOmf47Nz9TSeEZ96o",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"cvc_check": "unchecked",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2017,
"fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit",
"last4": "4242",
"metadata": {},
"name": null,
"tokenization_method": null
},
"client_ip": "90.52.44.103",
"created": 1473338730,
"livemode": false,
"type": "card",
"used": false
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:45:30 GMT
- request:
method: post
uri: https://api.stripe.com/v1/invoiceitems
body:
encoding: UTF-8
string: customer=cus_8Di1wjdVktv5kt&amount=5100&currency=usd&description=Formation+Imprimante+3D+September+05%2C+2016+08%3A00+-+09%3A00+AM
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '130'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:45:31 GMT
Content-Type:
- application/json
Content-Length:
- '476'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99lRUe4QZ7kRSv
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "ii_18rRuJ2sOmf47Nz9S7f6qfEz",
"object": "invoiceitem",
"amount": 5100,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473338731,
"description": "Formation Imprimante 3D September 05, 2016 08:00 - 09:00 AM",
"discountable": true,
"invoice": null,
"livemode": false,
"metadata": {},
"period": {
"start": 1473338731,
"end": 1473338731
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:45:31 GMT
- request:
method: post
uri: https://api.stripe.com/v1/invoiceitems
body:
encoding: UTF-8
string: customer=cus_8Di1wjdVktv5kt&amount=-510&currency=usd&description=coupon+XMAS10
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '78'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:45:32 GMT
Content-Type:
- application/json
Content-Length:
- '431'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99lR2huyf6IhVY
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "ii_18rRuK2sOmf47Nz9ye4DQ4PM",
"object": "invoiceitem",
"amount": -510,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473338732,
"description": "coupon XMAS10",
"discountable": false,
"invoice": null,
"livemode": false,
"metadata": {},
"period": {
"start": 1473338732,
"end": 1473338732
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:45:32 GMT
- request:
method: get
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:45:33 GMT
Content-Type:
- application/json
Content-Length:
- '2495'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99lRlUD2wtvAmA
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "cus_8Di1wjdVktv5kt",
"object": "customer",
"account_balance": 0,
"created": 1459948888,
"currency": "usd",
"default_source": "card_18rNSk2sOmf47Nz9h1cf7obf",
"delinquent": false,
"description": "Jean Dupond",
"discount": null,
"email": "jean.dupond@gmail.com",
"livemode": false,
"metadata": {},
"shipping": null,
"sources": {
"object": "list",
"data": [
{
"id": "card_18rNSk2sOmf47Nz9h1cf7obf",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"customer": "cus_8Di1wjdVktv5kt",
"cvc_check": "pass",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2017,
"fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit",
"last4": "4242",
"metadata": {},
"name": null,
"tokenization_method": null
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/sources"
},
"subscriptions": {
"object": "list",
"data": [
{
"id": "sub_99gqb47NmX9r79",
"object": "subscription",
"application_fee_percent": null,
"cancel_at_period_end": true,
"canceled_at": 1473321656,
"created": 1473321652,
"current_period_end": 1475913652,
"current_period_start": 1473321652,
"customer": "cus_8Di1wjdVktv5kt",
"discount": null,
"ended_at": null,
"livemode": false,
"metadata": {},
"plan": {
"id": "mensuel-standard-month-20160404171519",
"object": "plan",
"amount": 3000,
"created": 1459782921,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"name": "Mensuel - standard, association - month",
"statement_descriptor": null,
"trial_period_days": null
},
"quantity": 1,
"start": 1473321652,
"status": "active",
"tax_percent": null,
"trial_end": null,
"trial_start": null
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions"
}
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:45:33 GMT
- request:
method: post
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources
body:
encoding: UTF-8
string: card=tok_18rRuI2sOmf47Nz9nl5ZXXoF
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '33'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:45:34 GMT
Content-Type:
- application/json
Content-Length:
- '577'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99lReB7yNLWrc3
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "card_18rRuI2sOmf47Nz9TSeEZ96o",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"customer": "cus_8Di1wjdVktv5kt",
"cvc_check": "pass",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2017,
"fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit",
"last4": "4242",
"metadata": {},
"name": null,
"tokenization_method": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:45:34 GMT
- request:
method: post
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt
body:
encoding: UTF-8
string: default_source=card_18rRuI2sOmf47Nz9TSeEZ96o
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '44'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:45:35 GMT
Content-Type:
- application/json
Content-Length:
- '3223'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99lRU3qBXW4qEB
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "cus_8Di1wjdVktv5kt",
"object": "customer",
"account_balance": 0,
"created": 1459948888,
"currency": "usd",
"default_source": "card_18rRuI2sOmf47Nz9TSeEZ96o",
"delinquent": false,
"description": "Jean Dupond",
"discount": null,
"email": "jean.dupond@gmail.com",
"livemode": false,
"metadata": {},
"shipping": null,
"sources": {
"object": "list",
"data": [
{
"id": "card_18rRuI2sOmf47Nz9TSeEZ96o",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"customer": "cus_8Di1wjdVktv5kt",
"cvc_check": "pass",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2017,
"fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit",
"last4": "4242",
"metadata": {},
"name": null,
"tokenization_method": null
},
{
"id": "card_18rNSk2sOmf47Nz9h1cf7obf",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"customer": "cus_8Di1wjdVktv5kt",
"cvc_check": "pass",
"dynamic_last4": null,
"exp_month": 4,
"exp_year": 2017,
"fingerprint": "o52jybR7bnmNn6AT",
"funding": "credit",
"last4": "4242",
"metadata": {},
"name": null,
"tokenization_method": null
}
],
"has_more": false,
"total_count": 2,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/sources"
},
"subscriptions": {
"object": "list",
"data": [
{
"id": "sub_99gqb47NmX9r79",
"object": "subscription",
"application_fee_percent": null,
"cancel_at_period_end": true,
"canceled_at": 1473321656,
"created": 1473321652,
"current_period_end": 1475913652,
"current_period_start": 1473321652,
"customer": "cus_8Di1wjdVktv5kt",
"discount": null,
"ended_at": null,
"livemode": false,
"metadata": {},
"plan": {
"id": "mensuel-standard-month-20160404171519",
"object": "plan",
"amount": 3000,
"created": 1459782921,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"name": "Mensuel - standard, association - month",
"statement_descriptor": null,
"trial_period_days": null
},
"quantity": 1,
"start": 1473321652,
"status": "active",
"tax_percent": null,
"trial_end": null,
"trial_start": null
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/customers/cus_8Di1wjdVktv5kt/subscriptions"
}
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:45:35 GMT
- request:
method: post
uri: https://api.stripe.com/v1/invoices
body:
encoding: UTF-8
string: customer=cus_8Di1wjdVktv5kt
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '27'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:45:36 GMT
Content-Type:
- application/json
Content-Length:
- '1925'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99lRjTRT4OH5kv
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "in_18rRuO2sOmf47Nz9qbfxBA0D",
"object": "invoice",
"amount_due": 4590,
"application_fee": null,
"attempt_count": 0,
"attempted": false,
"charge": null,
"closed": false,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473338736,
"description": null,
"discount": null,
"ending_balance": null,
"forgiven": false,
"lines": {
"object": "list",
"data": [
{
"id": "ii_18rRuK2sOmf47Nz9ye4DQ4PM",
"object": "line_item",
"amount": -510,
"currency": "usd",
"description": "coupon XMAS10",
"discountable": false,
"livemode": false,
"metadata": {},
"period": {
"start": 1473338732,
"end": 1473338732
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
},
{
"id": "ii_18rRuJ2sOmf47Nz9S7f6qfEz",
"object": "line_item",
"amount": 5100,
"currency": "usd",
"description": "Formation Imprimante 3D September 05, 2016 08:00 - 09:00 AM",
"discountable": true,
"livemode": false,
"metadata": {},
"period": {
"start": 1473338731,
"end": 1473338731
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
}
],
"has_more": false,
"total_count": 2,
"url": "/v1/invoices/in_18rRuO2sOmf47Nz9qbfxBA0D/lines"
},
"livemode": false,
"metadata": {},
"next_payment_attempt": 1473342336,
"paid": false,
"period_end": 1473338736,
"period_start": 1473321652,
"receipt_number": null,
"starting_balance": 0,
"statement_descriptor": null,
"subscription": null,
"subtotal": 4590,
"tax": null,
"tax_percent": null,
"total": 4590,
"webhooks_delivered_at": null
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:45:36 GMT
- request:
method: post
uri: https://api.stripe.com/v1/invoices/in_18rRuO2sOmf47Nz9qbfxBA0D/pay
body:
encoding: ASCII-8BIT
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
Content-Length:
- '0'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:45:37 GMT
Content-Type:
- application/json
Content-Length:
- '1944'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99lRH31egNKaff
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"id": "in_18rRuO2sOmf47Nz9qbfxBA0D",
"object": "invoice",
"amount_due": 4590,
"application_fee": null,
"attempt_count": 1,
"attempted": true,
"charge": "ch_18rRuP2sOmf47Nz9V3NRITbR",
"closed": true,
"currency": "usd",
"customer": "cus_8Di1wjdVktv5kt",
"date": 1473338736,
"description": null,
"discount": null,
"ending_balance": 0,
"forgiven": false,
"lines": {
"object": "list",
"data": [
{
"id": "ii_18rRuK2sOmf47Nz9ye4DQ4PM",
"object": "line_item",
"amount": -510,
"currency": "usd",
"description": "coupon XMAS10",
"discountable": false,
"livemode": false,
"metadata": {},
"period": {
"start": 1473338732,
"end": 1473338732
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
},
{
"id": "ii_18rRuJ2sOmf47Nz9S7f6qfEz",
"object": "line_item",
"amount": 5100,
"currency": "usd",
"description": "Formation Imprimante 3D September 05, 2016 08:00 - 09:00 AM",
"discountable": true,
"livemode": false,
"metadata": {},
"period": {
"start": 1473338731,
"end": 1473338731
},
"plan": null,
"proration": false,
"quantity": null,
"subscription": null,
"type": "invoiceitem"
}
],
"has_more": false,
"total_count": 2,
"url": "/v1/invoices/in_18rRuO2sOmf47Nz9qbfxBA0D/lines"
},
"livemode": false,
"metadata": {},
"next_payment_attempt": null,
"paid": true,
"period_end": 1473338736,
"period_start": 1473321652,
"receipt_number": null,
"starting_balance": 0,
"statement_descriptor": null,
"subscription": null,
"subtotal": 4590,
"tax": null,
"tax_percent": null,
"total": 4590,
"webhooks_delivered_at": 1473338736
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:45:37 GMT
- request:
method: delete
uri: https://api.stripe.com/v1/customers/cus_8Di1wjdVktv5kt/sources/card_18rRuI2sOmf47Nz9TSeEZ96o
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Stripe/v1 RubyBindings/1.30.2
Authorization:
- Bearer sk_test_testfaketestfaketestfake
Content-Type:
- application/x-www-form-urlencoded
X-Stripe-Client-User-Agent:
- '{"bindings_version":"1.30.2","lang":"ruby","lang_version":"2.3.0 p0 (2015-12-25)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
version 4.4.0-36-generic (buildd@lcy01-01) (gcc version 5.4.0 20160609 (Ubuntu
5.4.0-6ubuntu1~16.04.2) ) #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016","hostname":"sylvain-sleede-pc"}'
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Thu, 08 Sep 2016 12:45:38 GMT
Content-Type:
- application/json
Content-Length:
- '63'
Connection:
- keep-alive
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, POST, HEAD, OPTIONS, DELETE
Access-Control-Allow-Origin:
- "*"
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Request-Id:
- req_99lRURlSYOVhs3
Stripe-Version:
- '2015-10-16'
Strict-Transport-Security:
- max-age=31556926; includeSubDomains
body:
encoding: UTF-8
string: |
{
"deleted": true,
"id": "card_18rRuI2sOmf47Nz9TSeEZ96o"
}
http_version:
recorded_at: Thu, 08 Sep 2016 12:45:38 GMT
recorded_with: VCR 3.0.1