# Free field scheduling starter — start here

Use the complete companion article for context, example results and troubleshooting. This is a copyable educational example, not a hosted product. Local tests simulate Google services; a real Google-account sandbox run is still required.

## Files

- `field-scheduler.gs`: paste the complete file into a spreadsheet-bound Apps Script project.
- `jobs.csv`: fictional job inputs and exact 15-column header.
- `crews.csv`: two crew rows; replace both Calendar ID placeholders.

## First build

1. In the dispatcher Google account, create two PRIVATE secondary calendars for test crews. Use no personal primary calendar and no real customer appointment calendar.
2. Align their time zones, spreadsheet settings, script project settings and CONFIG.timeZone (sample: Europe/London).
3. In a new restricted Sheet, open Extensions → Apps Script. Replace Code.gs with the entire supplied script and save.
4. Enable the Advanced Google Calendar API service v3 with identifier Calendar. No web deployment is needed. Review the permissions for your own project/account.
5. Run setupScheduler once. Reload the spreadsheet for the Field scheduler menu.
6. Import the CSVs into the named Jobs and Crews tabs, preserving headers and plain-text dates/times. Replace crew IDs. Update all sample job dates to a future weekday if needed.
7. Preview. With empty sample calendars, expect Crew A 09:00–10:00 and 10:15–11:00, Crew B 09:00–10:00, and TEST-004 in REVIEW. Calendar capacity includes an extra 15 minutes after each service.
8. Publish only after checking preview. Verify exactly three calendar events and matching output rows, then rerun to check no duplicates.
9. Perform all article sandbox tests, including crew mobile visibility. Share each crew calendar only with its intended test user and keep it read-only for that user. Reminder settings are per user; the script does not configure their phone.
10. Optional later: create ONE time-driven trigger for publishApprovedJobs every 15 minutes. Check Executions, REVIEW and READY rows. The script does not install a trigger automatically.

## Boundaries

- Monday–Friday, one time zone, 08:00–17:00, one crew with one skill and one zone per row.
- First-fit assignments in row order, 15-minute slots, fixed 15-minute after-service buffer. No travel calculation, SLA guarantee, fairness optimizer, automatic customer communication or offline worker app.
- Availability comes ONLY from the dedicated crew calendars. Enter breaks, meetings, leave and unavailable time there.
- At most 25 jobs/run, 500 data rows/tab, eight crew rows, four-minute soft attempt budget. These are starter safeguards, not Google's product limits. Provider quotas apply independently.
- All crews, including inactive rows, must remain accessible for recovery. Keep calendar IDs and JobIDs stable; never duplicate a calendar across crew rows or recycle an old JobID.
- One script project and one dispatcher publishing at a time. Script locking does not lock other calendar editors or systems. Calendar availability check plus insertion is not a database transaction.

## If anything goes wrong

Stop the time-driven trigger. Read the row's Error and inspect its actual event before retrying. Do not assume an error means the calendar write failed. An unchanged job can be retried with READY to recover an existing deterministic event ID; changed/moved/cancelled bookings need manual reconciliation. A REVIEW row stops that run; later READY jobs remain untouched.

Do not delete published rows/events as a blind reset. For a deliberate reschedule, reconcile/cancel the original event, retain its row as CANCELLED and create a new replacement JobID. Editing PUBLISHED inputs does not reschedule the event. Keep crew rows (Active=NO if needed), and do not point several copied spreadsheets at the same real calendars.

Private Google data, credentials and calendar IDs from real accounts do not belong in the public tutorial repository. No account, calendar event, email or subscription was created while preparing these files.
