company 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed1f293ece38ef16d7b40c90e465a8c95dd66e4f722af9d01cff87cb78a2e793
4
- data.tar.gz: b6c0d21d97439455d1cb50c751c3e8f8e4af13e406a0765d3b2f3f66c962c7c8
3
+ metadata.gz: 0b4dad8d6bba939008a26107865489bc6aeb9a055d8cb73e58ae7b92c012521a
4
+ data.tar.gz: e0b15dbe81ec83a130beaac19d666f2d182476f20d7890f918e79d44afa8c847
5
5
  SHA512:
6
- metadata.gz: e337b418dee3bd35743e33a601624f51d1c8d438add6ddf90f1c692f23cf62c46b311010f92f33c39d94e0e3942e040f3709d80e2e6a6be45e91d4134ecd6243
7
- data.tar.gz: 8d355dff05b2ddcb6447ab5f9eadd10e0129e51a2cfcc835a8d3801f2ea73bbec4fffed090fc2ed133ff888fb6da1a2e60cd547726afd33cc8999e7b42bf72da
6
+ metadata.gz: 8f20e43463498126a030dc4afb64c7ed1b12c7372329e15ba222acec3217005d919f2c054e2d0da1da797e961ef725f6bbc4580a9b765eb023dc2a555e650d62
7
+ data.tar.gz: 43dcfc1ecd909109e2169ba2ac419961a0cfce5a8b3bfe9c334a18569db501c9932adbb0152c427c293036721839826702a794d3064f7f3db32e65b793533bae
data/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
5
5
  For more information about changelogs, check [Keep a Changelog](http://keepachangelog.com) and
6
6
  [Vandamme](http://tech-angels.github.io/vandamme).
7
7
 
8
+ ## 2.1.0 - 2026-09-15
9
+
10
+ * [Feature] `Company::Collection#includes(*names)`, what to bring back beside each record. A
11
+ platform that charges for what a row carries answers it by asking for more; one that hands a
12
+ record over whole has nothing to ask for and answers the same list. Either way a caller names
13
+ what it reads without knowing which kind of platform it is talking to, which a caller sharing
14
+ one code path across two of them could not do before
15
+ * [Feature] `Company::Visit#location`, where the stop is. A schedule is read to know who is
16
+ where and when, so a visit says where without being asked what it was booked for, and a
17
+ caller no longer reaches through `visit.job` for an address -- which a stop booked against a
18
+ lead, or an hour blocked out against nothing, could never answer. `job` and `lead` say why a
19
+ visit exists and either may be absent; `location` may be too, for booked time that is nowhere
20
+
8
21
  ## 2.0.0 - 2026-09-15
9
22
 
10
23
  * [Breaking change] `Company::Selection` takes the rule to keep records by as a block rather
data/README.md CHANGED
@@ -79,12 +79,14 @@ visit.description # => 'Service appointment'
79
79
  visit.starts_at # => 2026-09-10 01:00:00 UTC
80
80
  visit.ends_at # => 2026-09-10 02:00:00 UTC
81
81
  visit.anytime? # => false
82
- visit.job # => job, or nil where the stop is a lead's
83
- visit.lead # => lead, or nil where the stop is a job's
82
+ visit.location # => #<Acme::Location>, or nil where it is nowhere
83
+ visit.job # => job, or nil where no job was booked for it
84
+ visit.lead # => lead, or nil where no lead was booked for it
84
85
  visit.technicians # => [#<Acme::Technician>, ...]
85
86
 
86
87
  visits.for_jobs # => only the stops of jobs
87
88
  visits.for_leads # => only the stops of leads
89
+ visits.includes(location: :customer) # => the same list, whatever the platform charges
88
90
 
89
91
  booked = account.visits.create name: 'Jane', surname: 'Qi', phone: '5555555666',
90
92
  email: 'jane@example.com', address: { street: '100 Acme Circle', zip: '98920' },
@@ -114,10 +116,14 @@ far as it goes or narrowed: to a window measured from now, to the technician the
114
116
  booked for, or to one kind of stop. The narrowings compose in any order, so one technician's
115
117
  week reads the same whichever is asked for first.
116
118
 
117
- A visit is any booked time, not only work that is already a job. A stop to look at something
118
- nobody has priced yet -- Jobber calls it an assessment, Housecall Pro an estimate -- is a visit
119
- that names a `lead` and no `job`, and it occupies the technician's day exactly as a job's stop
120
- does. `quote` stays the price, which is the other half of what Housecall Pro files as one
119
+ A visit is any booked time: somebody is somewhere for an hour. That is what a schedule is read
120
+ for -- who is where, and when -- so a visit says where it is without being asked what it was
121
+ booked for, and a caller never reaches through a job to find an address.
122
+
123
+ `job` and `lead` answer *why*, and either may be absent. A stop to look at something nobody has
124
+ priced yet -- Jobber calls it an assessment, Housecall Pro an estimate -- names a `lead` and no
125
+ `job`. An hour blocked out on a calendar names neither, and occupies the technician's day just
126
+ the same. `quote` stays the price, which is the other half of what Housecall Pro files as one
121
127
  record.
122
128
 
123
129
  ## Answering as a gem
@@ -143,8 +149,10 @@ end
143
149
 
144
150
  `Company::Business.node_keys` then answers `[:id, :name, :phone_number]`: exactly what to ask
145
151
  the platform for. A reader the gem leaves out raises `NotImplementedError` naming the gem; leads
146
- it leaves out refuse to file one, and so do the visits. `assigned_to`, `for_jobs` and
147
- `for_leads` a gem leaves out still answer: `Company::Selection` walks the list and lets through
152
+ it leaves out refuse to file one, and so do the visits. `includes` a gem leaves out answers the
153
+ same list: a platform that hands a record over whole has nothing to bring back beside it, so a
154
+ caller names what it reads without knowing which kind of platform it is talking to. `assigned_to`,
155
+ `for_jobs` and `for_leads` a gem leaves out still answer: `Company::Selection` walks the list and lets through
148
156
  what the rule keeps, so only a platform that can put the question to its server writes the
149
157
  method, and only to save the requests the walk would spend. The least a gem writes is under `test/acme`, and the test that
150
158
  runs every reader through it, `test/company/acme_test.rb`, reads as a tutorial.
@@ -20,6 +20,13 @@ module Company
20
20
  between within && now - within, now
21
21
  end
22
22
 
23
+ # What to bring back beside each record, for a platform that charges for the asking. One
24
+ # that answers a record whole has nothing to ask for and answers the same list, so a caller
25
+ # names what it reads without knowing which kind of platform it is talking to.
26
+ # @param names [Array<Symbol, Hash>] what to read beside each record, as the gem names them.
27
+ # @return [Collection] the same list, bringing those back where that costs anything.
28
+ def includes(*names) = self
29
+
23
30
  # A platform that can ask its server for one technician's work narrows the list there; one
24
31
  # that cannot walks the list and keeps what the technician turns out to be on.
25
32
  # @param technician [Technician] whoever the work is booked for.
@@ -1,6 +1,6 @@
1
1
  module Company
2
- # One stop of a job, or of a lead where the work is still being looked at: when somebody is
3
- # booked to be somewhere, and what they are booked for.
2
+ # Booked time: somebody is somewhere for an hour. Where it is, who is going and when are what
3
+ # a visit is for; the job or the lead it was booked against says why, and either may be absent.
4
4
  class Visit < Resource
5
5
  # What every visit reads, by the vocabulary's names.
6
6
  def self.attributes = %i[id description starts_at ends_at anytime]
@@ -17,10 +17,15 @@ module Company
17
17
  # @return [Boolean, nil] whether the visit may happen any time that day rather than at an hour.
18
18
  def anytime? = attribute :anytime
19
19
 
20
- # @return [Job, nil] job the stop belongs to, nil where the stop is a lead's.
20
+ # A stop says where it is without being asked what it was booked for, so a caller reading a
21
+ # schedule never has to reach through a job to find an address.
22
+ # @return [Location, nil] where the work happens, nil where the stop is booked nowhere.
23
+ def location = record Location, :location
24
+
25
+ # @return [Job, nil] job the stop belongs to, nil where no job was booked for it.
21
26
  def job = record Job, :job
22
27
 
23
- # @return [Lead, nil] lead the stop belongs to, nil where the stop is a job's.
28
+ # @return [Lead, nil] lead the stop belongs to, nil where no lead was booked for it.
24
29
  def lead = record Lead, :lead
25
30
 
26
31
  # @return [Array<Technician>] whoever the stop is booked for, where the platform names them.
@@ -1,5 +1,5 @@
1
1
  # The vocabulary two platform gems share: an account opens a business and the records it holds.
2
2
  module Company
3
3
  # The version of this gem, as RubyGems knows it.
4
- VERSION = '2.0.0'
4
+ VERSION = '2.1.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: company
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claudio Baccigalupo