jbr 5.0.0 → 7.0.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 +4 -4
- data/CHANGELOG.md +28 -0
- data/README.md +28 -5
- data/lib/jbr/booking.rb +1 -1
- data/lib/jbr/collections/visits.rb +3 -3
- data/lib/jbr/scheduled.rb +1 -1
- data/lib/jbr/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d0f69e98e247c3db048083001987272c2005e55ff55b4e4e40911aeb1057993f
|
|
4
|
+
data.tar.gz: 18e53a6747f4ca42cf9cd2cb872d0b083a4ec18aa4b933c2825522dc8ea78c5b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dfd01ee3d0f0a5665c1daaae6ec66c51a22746fbd61b34d9e849f7f856e4c042cdc1eb7ce74b8aad1f67f68a817addbe14d2f17d20d46a023dbbb20ca52f8670
|
|
7
|
+
data.tar.gz: a5b628621b35d3343f99136a8228c808bd5d7df3dfe481de0e43a60944aa0ed6de659dab7af643f51db5307f565683814c5bed3b37dca071272ee47a992bd0c8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [7.0.0] - 2026-09-17
|
|
4
|
+
|
|
5
|
+
- [Breaking change] The vocabulary is `company` 4.0: `of` takes the ID Jobber files a technician
|
|
6
|
+
under rather than the technician, so `account.visits.of(technician.id)` is what
|
|
7
|
+
`account.visits.of(technician)` was. It still lands in the one filter beside the window, and
|
|
8
|
+
it still needs no Users scope. The pin is `~> 4.0`.
|
|
9
|
+
|
|
10
|
+
- [Note] The ID is the whole of what `assignedTo` ever took, and asking for it plainly is what
|
|
11
|
+
stops a caller handing over a record of its own whose `id` is not the one Jobber knows.
|
|
12
|
+
|
|
13
|
+
## [6.0.0] - 2026-09-16
|
|
14
|
+
|
|
15
|
+
- [Breaking change] The vocabulary is `company` 3.0: `assigned_to` is `of`, so
|
|
16
|
+
`account.visits.of(technician)` is what `account.visits.assigned_to(technician)` was. Jobber
|
|
17
|
+
still narrows it in the one filter, and it still needs no Users scope. The pin is `~> 3.0`.
|
|
18
|
+
|
|
19
|
+
- [Note] `account.windows` -- the free time of a business -- raises `NotImplementedError` here,
|
|
20
|
+
and will until Jobber exposes the hours a business keeps. It does not today: the schema was
|
|
21
|
+
enumerated looking, and there is no `BusinessHours`, `WorkingHours`, `Shift` or `Weekday` type
|
|
22
|
+
of any kind, while `OnlineBookingConfiguration` is four fields and none of them is an hour.
|
|
23
|
+
|
|
24
|
+
- [Note] Every setting around those hours is there, on `requestSettings`:
|
|
25
|
+
`intervalDurationMinutes` is the grain, `earliestAvailabilityMinutes` the notice,
|
|
26
|
+
`bufferDurationMinutes` the padding either side of a job, `efficientSchedulingType` and
|
|
27
|
+
`maxDriveTimeMinutes` whether travel counts. A caller can work free time out from those and
|
|
28
|
+
the visits. Read them off the form that books, not the one marked default, whose
|
|
29
|
+
`bookingType` may be `NONE`.
|
|
30
|
+
|
|
3
31
|
## [5.0.0] - 2026-09-15
|
|
4
32
|
|
|
5
33
|
- [Feature] A scope the app was never granted no longer raises. Jobber answers `An object of
|
data/README.md
CHANGED
|
@@ -115,7 +115,7 @@ failing. What each reader here needs:
|
|
|
115
115
|
| --- | --- |
|
|
116
116
|
| `account.jobs`, `job.lines` | Jobs |
|
|
117
117
|
| `job.location`, `location.customer`, `visit.job` | Jobs and Clients |
|
|
118
|
-
| `account.visits`, `
|
|
118
|
+
| `account.visits`, `of` | Scheduled Items |
|
|
119
119
|
| `account.technicians`, `visit.technicians`, `includes(:technicians)` | Users |
|
|
120
120
|
| `account.quotes` | Quotes |
|
|
121
121
|
| `account.invoices` | Invoices |
|
|
@@ -125,7 +125,7 @@ Jobber files a visit under **Scheduled Items**, which is one object covering vis
|
|
|
125
125
|
assessments, tasks and calendar events -- so there is no scope to add for the kinds of booked
|
|
126
126
|
time this gem does not read yet.
|
|
127
127
|
|
|
128
|
-
`
|
|
128
|
+
`of` is the one worth knowing: narrowing to a technician needs no Users, because
|
|
129
129
|
Jobber does the narrowing and no user is ever selected. Reading *who* is on a visit is what
|
|
130
130
|
needs it.
|
|
131
131
|
|
|
@@ -325,17 +325,40 @@ One technician's week is the visits in it narrowed to them:
|
|
|
325
325
|
|
|
326
326
|
```ruby
|
|
327
327
|
monday = Date.today.beginning_of_week.in_time_zone
|
|
328
|
-
account.visits.between(monday, monday + 1.week).
|
|
328
|
+
account.visits.between(monday, monday + 1.week).of(technician.id).each do |visit|
|
|
329
329
|
visit.starts_at, visit.ends_at, visit.job.id
|
|
330
330
|
end
|
|
331
331
|
```
|
|
332
332
|
|
|
333
|
-
Jobber narrows a list of visits by who is on it, so `
|
|
333
|
+
Jobber narrows a list of visits by who is on it, so `of` puts the technician into the
|
|
334
334
|
same filter as the window: nobody else's visits are answered, paged or paid for, and the crew
|
|
335
335
|
is not read at all unless `includes(:technicians)` asks. The two narrowings land in the one
|
|
336
336
|
filter, so a caller may ask for the week and the technician in either order.
|
|
337
337
|
|
|
338
|
-
`
|
|
338
|
+
`of` therefore needs no Users scope. Reading *who* is on a visit does.
|
|
339
|
+
|
|
340
|
+
## What Jobber cannot say
|
|
341
|
+
|
|
342
|
+
`account.windows` -- the free time of a business, which the vocabulary names -- raises
|
|
343
|
+
`NotImplementedError` here, and will go on doing so until Jobber exposes the hours a business
|
|
344
|
+
keeps.
|
|
345
|
+
|
|
346
|
+
It does not today. The whole schema was enumerated looking for it: there is no `BusinessHours`,
|
|
347
|
+
`WorkingHours`, `OperatingHours`, `Shift`, `Weekday` or `DayOfWeek` type of any kind, and
|
|
348
|
+
`OnlineBookingConfiguration` is four fields -- whether bookings are on, the URL, the embed
|
|
349
|
+
script, the id. Jobber's own booking page must know the hours; the API does not say them.
|
|
350
|
+
|
|
351
|
+
What it does say is every setting around them, on `requestSettings`:
|
|
352
|
+
`intervalDurationMinutes` is the grain an offer is cut to, `earliestAvailabilityMinutes` the
|
|
353
|
+
notice the business needs, `bufferDurationMinutes` the padding left either side of a job, and
|
|
354
|
+
`efficientSchedulingType` with `maxDriveTimeMinutes` whether travel is counted as well. Read
|
|
355
|
+
those beside the visits and a caller can work free time out for itself -- which is what the
|
|
356
|
+
missing reader would have done. Take the settings from the form that books, not the one marked
|
|
357
|
+
default: the default form may be a request form, whose `bookingType` is `NONE`.
|
|
358
|
+
|
|
359
|
+
Raising is deliberate rather than answering with none. An empty week and a fully booked one are
|
|
360
|
+
the same shape, so a caller reading none as none would quietly stop offering the business
|
|
361
|
+
altogether, with nothing in a log and no page looking wrong.
|
|
339
362
|
|
|
340
363
|
A visit is still not all Jobber schedules. A task, an event and the two kinds of reminder sit
|
|
341
364
|
on the same calendar and are read past unread, because Jobber's filter takes one kind and not
|
data/lib/jbr/booking.rb
CHANGED
|
@@ -40,7 +40,7 @@ module Jbr
|
|
|
40
40
|
|
|
41
41
|
def schedule(starts_at, ends_at, technicians)
|
|
42
42
|
{ startAt: moment(starts_at), endAt: (moment(ends_at) if ends_at),
|
|
43
|
-
teamMemberIdsToAssign: technicians.map(&:id) }.compact
|
|
43
|
+
teamMemberIdsToAssign: technicians.map(&:id), }.compact
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def moment(at)
|
|
@@ -15,16 +15,16 @@ module Jbr
|
|
|
15
15
|
def between(from, to)
|
|
16
16
|
now = Time.now
|
|
17
17
|
narrowed occursWithin: { startAt: (from || now - HORIZON).iso8601,
|
|
18
|
-
endAt: (to || now + HORIZON).iso8601 },
|
|
18
|
+
endAt: (to || now + HORIZON).iso8601, },
|
|
19
19
|
includeUnassigned: true, includeUnscheduled: false
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
# Jobber narrows a schedule by who is on it, so the technician joins the window in the one
|
|
23
23
|
# filter and nobody else's work is answered, paged or paid for.
|
|
24
|
-
# @param
|
|
24
|
+
# @param id [String] ID Jobber files whoever the work is booked for under.
|
|
25
25
|
# @return [Visits] the same list, narrowed to what they are booked for.
|
|
26
26
|
# @note Needs no Users scope: Jobber narrows, and no user is selected to do it.
|
|
27
|
-
def
|
|
27
|
+
def of(id) = narrowed(assignedTo: [ id ])
|
|
28
28
|
|
|
29
29
|
# @return [Visits] the same list, narrowed to the stops of jobs, by Jobber rather than here.
|
|
30
30
|
def for_jobs = narrowed(scheduleItemType: 'VISIT')
|
data/lib/jbr/scheduled.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Jbr
|
|
|
13
13
|
|
|
14
14
|
def fields
|
|
15
15
|
[ SHARED, kind('Visit', 'clientConfirmed job { id }'),
|
|
16
|
-
kind('Assessment', 'clientConfirmed request { id }') ].join ' '
|
|
16
|
+
kind('Assessment', 'clientConfirmed request { id }'), ].join ' '
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def kind(name, own) = "... on #{name} { #{[ own, located ].compact_blank.join ' '} }"
|
data/lib/jbr/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jbr
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 7.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Claudio Baccigalupo
|
|
@@ -29,14 +29,14 @@ dependencies:
|
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
32
|
+
version: '4.0'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
39
|
+
version: '4.0'
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: minitest
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|