The "Flexible" Need is a vestige of early versions of CiviCRM which we are discussing factoring out (see also
VOL-140). Without going down a rabbit hole of the merits or demerits of the current architecture, suffice it to say that there are substantial consequences if a project is created without a flexible need. To name a few:
- The "holding pen" of available volunteers in the Assign UI is directly related to the flexible need. If the need is missing the UI breaks.
- The public-facing volunteer opportunity search (or "shopping cart," as we sometimes call it) assumes that there is a need for every matching project. If this assumption isn't met, users will get no search results and a message "Expected one VolunteerNeed but found 25."
- Hours logged by coordinators for ad hoc volunteers are logged against the flexible need.
We have not been able to reliably reproduce the error condition via the interface, but we are getting reports of it in the wild. With the migration of many user interfaces to Angular (and the concomitant migration of many API requests to the client-side), it not difficult to imagine scenarios in which this could occur.
Presently the application provides only one GUI for creating projects. Because the project ID is required for the creation of the need, the client waits for the resolution of the call to api.VolunteerProject.create before initiating a call to api.VolunteerNeed.create. Should a user's Internet connection drop before the second call, the data will be in an inconsistent state.
It appears it is time to move the creation of the flexible need into the project creation logic. Previously we kept api.VolunteerProject.create pretty thin, but as the application has developed (and particularly as more has moved to the client side), more and more ancillary entities (e.g., UFJoins, VolunteerProjectContacts) are created by this API.
We resisted this before as it was argued that someone making direct API calls would know what they were doing and should have the flexibility to do whatever they please, but, practically, so many CiviVolunteer interfaces become unusable that it is difficult to imagine a real-world use case for this. Additionally, developers can trivially delete the flexible need if so desired with an additional call to api.VolunteerNeed.delete.
The application does assume that there will be exactly one flexible need per project. Not much experimentation has been done to find out what breaks when there is more than one, but we have seen the Assign UI break in development environments as a result of this. As a way to mitigate problems for any downstream code which may be attempting to create the flexible need after creating the project, we also propose to perform a check during need creation to prevent creation of a second flexible need for a given project.