Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions migration/db/migrations/202312281122100_add_client_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
-- +micrate Up
-- SQL in section 'Up' is executed when this migration is applied

CREATE TABLE IF NOT EXISTS "clients"(
id TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
billing_address TEXT,
billing_contact TEXT,
is_management BOOLEAN NOT NULL DEFAULT FALSE,
config JSONB NULL,
parent_id TEXT,
created_at TIMESTAMPTZ NOT NULL,
updated_at TIMESTAMPTZ NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_clients_name ON clients(name);
CREATE INDEX IF NOT EXISTS idx_clients_description ON clients(description);
CREATE INDEX IF NOT EXISTS idx_clients_config ON clients USING GIN (config jsonb_path_ops);

ALTER TABLE ONLY "clients"
ADD CONSTRAINT clients_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES "clients"(id) ON DELETE CASCADE;

ALTER TABLE "authority" ADD COLUMN IF NOT EXISTS client_id TEXT;
ALTER TABLE "authority"
ADD CONSTRAINT fk_authority_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE CASCADE;

ALTER TABLE "sys" ADD COLUMN IF NOT EXISTS client_id TEXT;
ALTER TABLE "sys"
ADD CONSTRAINT fk_sys_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE CASCADE;

ALTER TABLE "mod" ADD COLUMN IF NOT EXISTS client_id TEXT;
ALTER TABLE "mod"
ADD CONSTRAINT fk_mod_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE CASCADE;

ALTER TABLE "zone" ADD COLUMN IF NOT EXISTS client_id TEXT;
ALTER TABLE "zone"
ADD CONSTRAINT fk_zone_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE CASCADE;

-- +micrate Down
-- SQL section 'Down' is executed when this migration is rolled back
ALTER TABLE "authority"
DROP CONSTRAINT IF EXISTS fk_authority_client;
ALTER TABLE "authority" DROP COLUMN IF EXISTS client_id;

ALTER TABLE "sys"
DROP CONSTRAINT IF EXISTS fk_sys_client;
ALTER TABLE "sys" DROP COLUMN IF EXISTS client_id;

ALTER TABLE "mod"
DROP CONSTRAINT IF EXISTS fk_mod_client;
ALTER TABLE "mod" DROP COLUMN IF EXISTS client_id;

ALTER TABLE "zone"
DROP CONSTRAINT IF EXISTS fk_zone_client;
ALTER TABLE "zone" DROP COLUMN IF EXISTS client_id;

DROP TABLE IF EXISTS "clients"
3 changes: 2 additions & 1 deletion spec/asset_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,14 @@ module PlaceOS::Model
asset_id = asset.id.as(String)
booking = Generator.booking(tenant.id, asset_id, event_start, event_end)
booking.save!

booking.asset_ids.size.should eq(1)
booking.asset_ids.first.should eq(booking.asset_id)

booking.asset_id = asset2.id.as(String)
booking.save!

booking.asset_ids.size.should eq(1)
booking.asset_ids.size.should eq(2)
booking.asset_id.should eq(asset2.id)
end

Expand Down
31 changes: 31 additions & 0 deletions spec/client_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require "./helper"

module PlaceOS::Model
Spec.before_each do
Client.clear
end

describe Client do
test_round_trip(Client)

it "saves a Client" do
client = Generator.client.save!

client.should_not be_nil
client.persisted?.should be_true
Client.find!(client.id).id.should eq client.id
end

it "allow sub-clients" do
parent = Generator.client.save!
child = Generator.client(parent).save!
child.parent_id.should eq parent.id
client = Client.find!(parent.id)
client.id.should eq parent.id
client.children.should_not be_nil
client.children.size.should eq(1)
client.children.try &.first.id.should eq child.id
puts client.to_pretty_json
end
end
end
79 changes: 79 additions & 0 deletions spec/generator.cr
Original file line number Diff line number Diff line change
Expand Up @@ -603,5 +603,84 @@ module PlaceOS::Model
sent: sent,
)
end

def self.client(parent : Client? = nil)
Client.new(name: Faker::Company.name, description: Faker::Lorem.sentence,
billing_address: Faker::Address.street_address, billing_contact: Faker::Name.name,
is_management: !parent.nil?, parent_id: parent.try &.id)
end

def self.survey(
title : String = Faker::Hacker.abbreviation,
description : String = Faker::Hacker.say_something_smart,
trigger : Survey::TriggerType = Survey::TriggerType::NONE,
zone_id : String = "",
building_id = "",
pages : Array(Survey::Page) = [self.page]
)
Survey.new(
title: title,
description: description,
trigger: trigger,
zone_id: zone_id,
building_id: building_id,
pages: pages,
)
end

def self.page(
title : String = Faker::Hacker.adjective,
description : String = Faker::Hacker.say_something_smart,
question_order : Array(Int64) = [] of Int64
)
Survey::Page.new(
title: title,
description: description,
question_order: question_order,
)
end

def self.question(
title : String = Faker::Hacker.noun,
description : String = Faker::Hacker.say_something_smart,
type : String = "text",
options : JSON::Any = JSON::Any.new({} of String => JSON::Any),
required : Bool = false,
choices : JSON::Any = JSON::Any.new({} of String => JSON::Any),
max_rating : Int32? = nil,
tags : Array(String) = [] of String,
deleted_at : Int64? = nil
)
Survey::Question.new(
title: title,
description: description,
type: type,
options: options,
required: required,
choices: choices,
max_rating: max_rating,
tags: tags,
deleted_at: deleted_at,
)
end

def self.invitation(
survey_id : Int64? = nil,
email : String = Faker::Internet.email,
sent : Bool? = nil
)
id = survey_id || self.survey.save!.id
Survey::Invitation.new(
survey_id: id,
email: email,
sent: sent,
)
end

def self.client(parent : Client? = nil)
Client.new(name: Faker::Company.name, description: Faker::Lorem.sentence,
billing_address: Faker::Address.street_address, billing_contact: Faker::Name.name,
is_management: !parent.nil?, parent_id: parent.try &.id)
end
end
end
1 change: 1 addition & 0 deletions src/placeos-models/authority.cr
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module PlaceOS::Model

# Associations
###############################################################################################
belongs_to Client, foreign_key: "client_id", association_name: "client"

{% for relation, _idx in [
{LdapAuthentication, "ldap_authentications"},
Expand Down
55 changes: 55 additions & 0 deletions src/placeos-models/client.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require "./base/model"

module PlaceOS::Model
class Client < ModelBase
include PlaceOS::Model::Timestamps
table :clients

attribute name : String
attribute description : String? = nil
attribute billing_address : String? = nil
attribute billing_contact : String? = nil
attribute is_management : Bool = false
attribute config : JSON::Any? = nil

belongs_to Client, foreign_key: "parent_id", association_name: "parent"

has_many(
child_class: Client,
foreign_key: "parent_id",
collection_name: :children,
serialize: true
)

has_many(
child_class: Authority,
foreign_key: "client_id",
collection_name: :authorities
)

has_many(
child_class: ControlSystem,
foreign_key: "client_id",
collection_name: :systems
)

has_many(
child_class: Module,
foreign_key: "client_id",
collection_name: :modules
)

has_many(
child_class: Zone,
foreign_key: "client_id",
collection_name: :zones
)

validates :name, presence: true

def to_json(json : ::JSON::Builder)
__children_rel if @id
super
end
end
end
2 changes: 2 additions & 0 deletions src/placeos-models/control_system.cr
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ module PlaceOS::Model
foreign_key: "control_system_id"
)

belongs_to Client, foreign_key: "client_id", association_name: "client"

# Validation
###############################################################################################

Expand Down
2 changes: 2 additions & 0 deletions src/placeos-models/module.cr
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ module PlaceOS::Model
dependent: :destroy
)

belongs_to Client, foreign_key: "client_id", association_name: "client"

# Validation
###############################################################################################

Expand Down
2 changes: 2 additions & 0 deletions src/placeos-models/zone.cr
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ module PlaceOS::Model
dependent: :destroy
)

belongs_to Client, foreign_key: "client_id", association_name: "client"

def root_zone_id : String
raise "zone model not persisted and has no parent" unless persisted? || self.parent_id.presence
return self.id.as(String) unless self.parent_id.presence
Expand Down