zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

commit a0754eb65b5860ccf4f6f2fb7a0111f14afa8314
parent 3f9de49643ea0150e847c452894140bb3fd12dd0
Author: srfsh <dev@srf.sh>
Date:   Mon, 20 Jun 2022 15:32:51 +0300

docs: improve

Diffstat:
Ddocs/HACKING.md | 46----------------------------------------------
Adocs/configuration-guide.md | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adocs/dependency-management.md | 40++++++++++++++++++++++++++++++++++++++++
Ddocs/deps-licences | 38--------------------------------------
Ddocs/runtime-conf | 28----------------------------
Adocs/software-licences.md | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddocs/style-guide | 4----
Adocs/style-guide.md | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Adocs/vf-intro-gql-iface.md | 2009+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmix.exs | 33++++++++++++++++++++++++++++++---
10 files changed, 2266 insertions(+), 119 deletions(-)

diff --git a/docs/HACKING.md b/docs/HACKING.md @@ -1,46 +0,0 @@ -# Running a local instance - -Simple instructions to run a local instance using postgres DB inside Docker and local elixir 1.12 - - -Setup the DB -``` -docker run -d -v /var/lib/postgres/data -p 5432:5432 --name db -e POSTGRES_PASSWORD=zenflows postgres:12-alpine -``` - -Install elixir -``` -apt-get install -y erlang erlang-dev erlang-os-mon erlang-parsetools erlang-tools -``` - -Build Zenflows -``` -mix deps.get -mix compile -``` - -Setup the DB for tests -``` -echo << EOF > conf/test.local.exs -import Config - -config :zenflows, Zenflows.DB.Repo, - username: "postgres", - password: "zenflows" -EOF - -./mann -t db.create -./mann -t db.migrate -``` - -Run all tests -``` -mix test -``` - -Clean the build -``` -rm -rf ./deps -rm -rf ./_build -``` - diff --git a/docs/configuration-guide.md b/docs/configuration-guide.md @@ -0,0 +1,70 @@ +# Configuration Guide + +Zenflows is configured through basic POSIX-compliant shell scripts. When you +run `mann env.setup`, it'll copy the example template, `conf/.example-env.sh`, +to `conf/env.sh`. You can edit that file according to your needs. The +available options are mentioned below. + + +## All available options + +The options here might seem a bit much, but it is to allow flexibility. Please +also see the [Required Options](#required-options). + +* `DB_HOST`: The hostname or IP address of the database host. The default is + `localhost`. +* `DB_PORT`: The port number of the database host. The default is `5432`. It + must be an integer between `0` and `65535`, inclusive. +* `DB_NAME`: The database name of the database host. The default is `zenflows` + if run in production mode; `zenflows_dev` in development mode; `zenflows_test` + in testing mode. +* `DB_USER`: The name of the user/role of the database host. +* `DB_PASS`: The passphrane of the user/role of the database host. +* `DB_SOCK`: The Unix socket path of the database daemon. +* `DB_URI`: The URI connection string. The syntax is + `scheme://user:pass@host:port/dbname?key0=val0&key1=val1&keyN=valN`, where: + 1. `scheme` is any valid scheme, such as `db`, `a`, `foo` or even `http`; + 2. `user` is the name of the user/role of teh database host. + 3. `pass` is the passphrane of the user/role of the database host. + 4. `host` is the hostname or IP address of the database host. + 5. `port` is the port number of the database host. + 6. `key0=val0`, `key1=val1`, and `keyN=valN` query strings are additional, + adapter-related options, such as `ssl=true` and `timeout=10000`. The list + of additional options can be viewed at the [PostgreSQL Adapter docs]( + https://hexdocs.pm/ecto_sql/Ecto.Adapters.Postgres.html#module-connection-options). + + This option should be used if extended configuration is desired (using the + options mention in the link above). + +* `ROOM_HOST`: The hostname or IP address of the Restroom instance. +* `ROOM_PORT`: The port number of the Restroom instance. It must be an integer + between `0` and `65535`, inclusive. +* `ROOM_SALT`: A 64-octect long, lowercase-base16-encoded string used for the + salt of the passphrase hashing function. Can be generated with `openssl rand + -hex 64`. It is automatically generated when you run `mann env.setup` + + +## Required Options + +Some of the options on how to connect to the database and the Restroom intance +are required, along with `ROOM_SALT` that is used for passhprase hashing. + +For the Restroom instance, you need the `ROOM_HOST` and `ROOM_PORT` options. + +About the database, there are only 2 things you need to setup: how to connect to +the database host, and what credentials to use. + +To specify what credentials to use, you must set `DB_USER` and `DB_PASS` +variables accordingly. + +To specify how to connect to the database host, you have 3 options: + +* Setting only `DB_HOST` and `DB_PORT`. This is the most masic one, and what + most people will use. You don't even need to set up any of these, as these + have the default values of `localhost` and `5432`. +* Setting only `DB_SOCK`. This is to allow people to use Unix sockets. +* Setting only `DB_URI`. This is to allow people to provide additional options. + It is basically setting `DB_HOST` and `DB_PORT` in the same variable, plus + additional options (that is, you can't use Unix sockets with this option). +These options are mutually-exclusive and the order of precedence is `DB_URI` > +`DB_SOCK` > `DB_HOST` and `DB_PORT`. diff --git a/docs/dependency-management.md b/docs/dependency-management.md @@ -0,0 +1,40 @@ +# Dependency Management + +The dependencies are put in version control in Zenflows. But elixir/mix doesn't +like this approach because it puts generated files (such as erlex, absinthe) in +the dependencies' directory, which makes it hard to track/differentiate source +files and generated files. + +For that reason, the actual dependencies (the real source code) are stored and +tracked in the `.deps/` directory instead of the `deps/` directory. Then, the +`.deps/` directory is copied over to `deps/` directory when we want to use the +dependencies in the project. Similarly, `deps/` is copied over to `.deps/` +whenever we update or add a dependency (of course, `deps/` is cleaned first, in +order to avoid generated files). + +But this approach needs some care when you want to update or add a dependency: +you must first clean the `deps/` directory with `mann dep.clean`, then copy +`.deps/` over to `deps/` with `mann dep.setup`, then use whatever mix command +you want to add or update a dependency (to update, use `mann mix deps.update +mydep`), then copy `deps/` over back to `.deps/`. + +Let's give some examples. Suppose you want to update `absinthe`. You do: + +1. `mann dep.clean` +2. `mann dep.setup` +3. `mann mix deps.update absinthe` +4. `mann dep.copy` +5. `git add .deps/` +6. `git commit -m 'dep: update absinthe to x.y.z'` + +Now let's suppose you want to add a new dependency, `absinthe`, to your project. +You do: + +1. `mann dep.clean` +2. `mann dep.setup` +3. edit `mix.exs` to add the dependency +4. `mann dep.copy` +5. `git add .deps/` +6. `git commit -m 'dep: add absinthe x.y.z'` + +Similar process happens with dependency removal, but I think it is clear now. diff --git a/docs/deps-licences b/docs/deps-licences @@ -1,38 +0,0 @@ -# elixir and erlang/otp -elixir * Apache-2.0 -erlang/otp * Apache-2.0 - -# library deps (name, version, license, "dev" if used in development) -absinthe 1.6.6 Expat -absinthe_plug 1.5.8 Expat -bunt 0.2.0 Expat dev -connection 1.1.0 Apache-2.0 -cowboy 2.9.0 ISC -cowboy_telemetry 0.4.0 Apache-2.0 -cowlib 2.11.0 ISC -credo 1.6.1 Expat dev -db_connection 2.4.1 Apache-2.0 -decimal 2.0.0 Apache-2.0 -dialyxir 1.1.0 Apache-2.0 dev -ecto 3.7.1 Apache-2.0 -ecto_sql 3.7.1 Apache-2.0 -erlex 0.2.6 Apache-2.0 dev -exsync 0.2.4 BSD-3 dev -file_system 0.2.10 WTFPL dev -jason 1.3.0 Apache-2.0 -mime 2.0.2 Apache-2.0 -nimble_parsec 1.2.0 Apache-2.0 -plug 1.12.1 Apache-2.0 -plug_cowboy 2.5.2 Apache-2.0 -plug_crypto 1.2.2 Apache-2.0 -postgrex 0.15.13 Apache-2.0 -ranch 1.8.0 ISC -telemetry 1.0.0 Apache-2.0 - - -# db -postgres * psql - -# vf -valueflows-gql * Apache-2.0 -valueflows-docs * CC BY-SA diff --git a/docs/runtime-conf b/docs/runtime-conf @@ -1,28 +0,0 @@ -When running in production, the following environment variables can be -passed to Zenflows (all number ranges are inclusive): - - * DB_HOST: The hostname to connect to for the database. The default - is `localhost'. - * DB_PORT: The port number of the database. The default is 5432. - It must be an integer between 0 and 65535. - * DB_NAME: The name of the database in PostgreSQL. The default is - `zenflows'. - * DB_USER: The username of the PostgreSQL user/role to connect as. - It is required if DB_SOCK is not provided. - * DB_PASS: The passphrase of the PostgreSQL user/role to connect as. - It is required if DB_SOCK is not provided. - * DB_SOCK: The path to the Unix socket of PostgreSQL. It takes - presence over DB_HOST, DB_PORT, DB_USER, and DB_PASS. - - * PASS_ITER: Iteration count for the hashing. The default is - 160000. It must be an integer between 1024 and 1073741823. - * PASS_KLEN: The length in octets for the derived key. The default is - 64. It must be an integer between 1 and 4294967295. - * PASS_SLEN: The length in octets for the randomly-generated salt. - The default is 16. It must be an integer between 16 and 255. - -You can put these in a file, for example, called `env' and do: - - env $(cat env) zenflows start - -to start the application easily with your configuration. diff --git a/docs/software-licences.md b/docs/software-licences.md @@ -0,0 +1,66 @@ +# Software Licenses + +The list of software licenses used by Zenflows. You can view the license +details of Zenflows in [the license file](docs/LICENSE). + + +## Elixir and Erlang/OTP distribution + +| Name | License | +|------------|-----------------------| +| elixir | [Apache-2.0][apache2] | +| erlang/otp | [Apache-2.0][apache2] | + + +## Library Dependencies + +| Name | License | Only in Development? | +|------------------|-----------------------|----------------------| +| absinthe | [Expat][expat] | | +| absinthe_plug | [Expat][expat] | | +| bunt | [Expat][expat] | Yes | +| connection | [Apache-2.0][apache2] | | +| cowboy | [ISC][isc] | | +| cowboy_telemetry | [Apache-2.0][apache2] | | +| cowlib | [ISC][isc] | | +| credo | [Expat][expat] | Yes | +| db_connection | [Apache-2.0][apache2] | | +| decimal | [Apache-2.0][apache2] | | +| dialyxir | [Apache-2.0][apache2] | Yes | +| ecto | [Apache-2.0][apache2] | | +| ecto_sql | [Apache-2.0][apache2] | | +| erlex | [Apache-2.0][apache2] | | +| exsync | [BSD-3][bsd3] | Yes | +| file_system | [WTFPL][wtfpl] | Yes | +| jason | [Apache-2.0][apache2] | | +| mime | [Apache-2.0][apache2] | | +| nimble_parsec | [Apache-2.0][apache2] | | +| plug | [Apache-2.0][apache2] | | +| plug_cowboy | [Apache-2.0][apache2] | | +| plug_crypto | [Apache-2.0][apache2] | | +| postgrex | [Apache-2.0][apache2] | | +| ranch | [ISC][isc] | | +| telemetry | [Apache-2.0][apache2] | | + + +## Database + +| Name | License | +|----------|----------------------------| +| postgres | [postgresql license][psql] | + + +## Valueflows + +| Name | License | +|----------------|-----------------------| +|valueflows-docs | [CC BY-SA][ccbysa] | +|valueflows-gql | [Apache-2.0][apache2] | + +[apache2]: https://www.gnu.org/licenses/license-list.en.html#apache2 +[expat]: https://www.gnu.org/licenses/license-list.en.html#Expat +[isc]: https://www.gnu.org/licenses/license-list.en.html#ModifiedBSD +[bsd3]: https://www.gnu.org/licenses/license-list.en.html#ModifiedBSD +[wtfpl]: https://www.gnu.org/licenses/license-list.en.html#WTFPL +[psql]: https://www.postgresql.org/about/licence/ +[ccbysa]: https://www.gnu.org/licenses/license-list.en.html#ccbysa diff --git a/docs/style-guide b/docs/style-guide @@ -1,4 +0,0 @@ -* Use tabs for indentation, spaces for aligment. -* Don't indent the top-level code in modules. -* Use trailing commas in multi-line lists, maps, functions, etc. where - possible. diff --git a/docs/style-guide.md b/docs/style-guide.md @@ -0,0 +1,51 @@ +# Style Guide + +Having a style guide is great for having consistency. + + +## Elixir + +For Elixir (`.ex`) or Elixir script files (`.exs`), follow these guide lines: + +* Keep line lengths at about 80 lines, not a hard rule. +* Use Unix line endings and make sure you have a <newline> character at the end + of the file (any decent editor will already do that). +* Use tabs for indentation, spaces for aligment. +* Don't indent the top-level code in modules and avoid nesting modules. +* Use trailing commas in multi-line lists, maps, functions, etc. wherever + possible. +* Prefer exclicit `do ... end` syntax over `, do: ...` syntax. + + +## Markdown + +For Markdown files (`.md`), follow these guide lines: + +* Keep lines lengths at most 80 lines (unless it is in a code block, then it is + not a hard rule). +* Capitalize first letters of all the titles (except for words like and, or, of, + etc.) +* Separate all titles from each other with two blank lines. +* Separate a title from the immediate paragraph by a blank line. +* Separate a list from the before and after paragraph by a blank line. +* Separate a code block (not inline) from the before and after paragraph by a + blank line. +* Aling the lines breaked from a list line like this: + + ``` + * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + + 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex + + 2. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex + + * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + ``` diff --git a/docs/vf-intro-gql-iface.md b/docs/vf-intro-gql-iface.md @@ -0,0 +1,2009 @@ +# VF Intro + +This document tries to explain how to use Zenflows's implementaton of the +Valueflows vocabulary. Please read about Valueflows documentation a bit to grasp +some concepts such as *Processes*, *EconomicEvents*, *EconomicResources*, and +*ResourceSpecifications* in order for this document to be more effective. + + +## Ownership and Quanty Types of Resources + +There are two quantity types in Zenflows: + +* `accountingQuantity` +* `onhandQuantity` + +Their meaning is defined by how they are used by the events. For example: + +* `produce` and `raise` events increase both quantities +* `consume` and `lower` events decrease both quantities +* `accept` events decrease `onhandQuantity` +* `modify` events increase `onhandQuantity` +* `transferAllRights` events decrease `accountingQuantity` of one resource, and + increase `accountingQuantity` of the other resource + +The ownership types specify who is the owner of the given quantity type. Those +types are: + +* `primaryAccountable`: the owner of the quantity `accountingQuantity` +* `custodian`: the current owner who has custody over the resource, amounted by + `onhandQuantity` + + +## ResourceSpecification and ProcessSpecification + +In order to tell what a resource is, we use *ResourceSpecifications*. If two +resources conform to the same ResourceSpecification, they would be of the same +type. Each resource has a field named `conformsTo` that points to a +ResourceSpecification. The field gets set by `resourceConformsTo` of `produce` +and `raise` events. + +But sometimes ResourceSpecification is not enough to differentiate between other +resources. Sometimes you need to, for example, differentiate between "clean", +"used", "dirty", "donated" gown resources. You use ProcessSpecifications to +differentiate between those. Each resource has a field named `stage` that could +point to a ProcessSpecification. The field gets set by `modify` events. + + +## Event Side-Effects and Enforcements + +In Zenflows, each event has its own requirements, enforcements, and possible +side-effects. Even though the GraphQL types allow some fields optionally, +depending on the action, the back-end enforces some fields required by the +events. + + +### Common Requirements and Enforcements + +Each event requires an Action. If no Action is provided, the back-end can't +know which fields to enforce and which side-effects to create. The supported +Actions are: + +* `produce` +* `consume` +* `use` +* `work` +* `cite` +* `deliverService` (alias: `deliver-service`) +* `pickup` +* `dropoff` +* `accept` +* `modify` +* `pack` +* `unpack` +* `transferCustody` (alias: `transfer-custody`) +* `transferAllRights` (alias: `transfer-all-rights`) +* `transfer` +* `move` +* `raise` +* `lower` + +Each event requires a `provider` and a `receiver`. If any of them is not +provided, the back-end will default to the currently logged-in agent. This +might be changed in the future, however (the front-ends can default to currently +logged-in agent by themselves). Also, at the moment, `provider` must be the +same agent as the logged-in agent. + +Each event requires you to provide some sort of time-related data. These are +provided by the fields `hasPointInTime`, `hasBeginning`, and `hasEnd`. The +back-end allows only these mutually-exclusive combinations, and if none of these +combinations are met, you'll not be able to create your event: + +* Only `hasPointInTime` +* Only `hasBeginning` +* Only `hasEnd` +* Both `hasBeginning` and `hasEnd` + +Currently, there's no check regarding the date-time fields. For example, +the back-end do not check if `hasBeginning` is older than `hasEnd`. + +The fields that take a reference (ID) to a record (such as +`resourceInventoriedAs`, `resourceConformsTo`, `atLocation`, and `toLocation`) +checks if the provided record exists. You can't create an event with invalid +references. + +The quantity fields take only positive amounts at the moment. + + +### Produce Events + +`produce` events are used for creating stuff. This does not only mean something +like harvesting crops, making a wood toy; it can also mean separating a resource +that have quantities of five pieces into five individual pieces (in that case, +you'd `consume` the resource that have five pieces, and `produce` five individual +pieces). + +Generally used with `consume`, `work`, `use`, and `cite` events together to +create a meaningful scenario. + +There are two things a `produce` event can do: + +* creating a new resource +* increasing quantities of an existing resource + +The back-end differentiates them by whether the event has +`resourceInventoriedAs` field or not. If it has, it'll try to increase the +quantities of the resource `resourceInventoriedAs`. + +Whether it creates a new resource or just increases the quantities of an existing +resource, the events will require `outputOf`, `resourceConformsTo`, and +`resourceQuantity` to be provided, and that the `provider` and `receiver` are +the same agents. + +If it creates a new resource, it'll try to get the fields `name`, `note`, +`trackingIdentifier`, `currentLocation`, and `stage` from +`newInventoriedResource` and put them into the newly-created resource. + +If it increases the quantities of an existing resource, it'll just do it, but +these requirements must be met first: + +* The `provider` and `receiver` must be the same agent as the + `primaryAccountable` and `custodian` of the resource `resourceInventoriedAs`. +* The `resourceQuantity.hasUnit` of the event must be the same as + `accountingQuantity.hasUnit` and `onhandQuantity.hasUnit` of the resource + `resourceInventoriedAs`. +* The `resourceConformsTo` must be same as `conformsTo` of the resource + `resourceInventoriedAs` +* The `resourceInventoriedAs` can't be a container or packed resource. + + +### Raise Events + +`raise` events are pretty much require and have the same side-effects as +`produce` events, but they can't have `outputOf` (or `inputOf`). + +The semantic meaning of `raise`, hower is different than `produce`. + + +### Consume Events + +`consume` events are used for... consuming stuff. This does not only mean +something like consuming seeds to plant crops; it can also mean separating a +resource that have quantities of five pieces into five individual pieces (in +that case, you'd `consume` the resource that have five pieces, and `produce` five +individual pieces). + +Generally used with `produce`, `work`, `use`, and `cite` events together to +create a meaningful scenario. + +The events require `inputOf`, `resourceInventoriedAs`, and `resourceQuantity` +to be provided, and that the `provider` and `receiver` are the same agents. + +It'll decrease the quantities of the resource `resourceInventoriedAs`, but these +requirements must be met: + +* The `provider` and `receiver` must be the same agent as the + `primaryAccountable` and `custodian` of the resource `resourceInventoriedAs`. +* The `resourceQuantity.hasUnit` of the event must be the same as + `accountingQuantity.hasUnit` and `onhandQuantity.hasUnit` of the resource + `resourceInventoriedAs`. +* The `resourceInventoriedAs` can't be a container or packed resource. + + +### Lower Events + +`lower` events are pretty much require and have the same side-effects as +`consume` events, but they can't have `inputOf` (or `outputOf`). + +The semantic meaning of `lower`, hower is different than `consume`. + + +### Use Events + +`use` events are used for... using stuff. The stuff you use are either an +actual resource or its specification. + +Generally used with `produce`, `consume`, `work`, and `cite` events together to +create a meaningful scenario. + +The events require `inputOf`, `effortQuantity`, and either +`resourceInventoriedAs` or `resourceConformsTo` (they're mutally-exclusive). +Optionally, you can also provide `resourceQuantity`. + +If you choose to have `resourceInventoriedAs`, these requirements must be met: + +* The `resourceQuantity.hasUnit` of the event must be the same as + `accountingQuantity.hasUnit` and `onhandQuantity.hasUnit` of the resource + `resourceInventoriedAs` +* The `resourceInventoriedAs` can't be a container or packed resource. + + +### Work Events + +`work` events are used for indicating labor power used in a process. This can +be the "repairing" in a car repairing scenario, "kneading" in a making a pie +scenario. + +Generally used with `produce`, `consume`, `use`, and `cite` events together to +create a meaningful scenario. + +The events require `inputOf`, `effortQuantity`, and `resourceConformsTo`. + + +### Cite Events + +`cite` events are used for indicating the usage of instructions, blueprints and +the like. They are used resourced but not consumed (that is, decreasing +quantities). + +Generally used with `produce`, `consume`, `use`, and `work` events together to +create a meaningful scenario. + +The events require `inputOf`, and `resourceQuantity`, and `resourceConformsTo` +or `resourceInventoriedAs` (they're mutually-exclusive). + +If you choose to have `resourceInventoriedAs`, these requirements must be met: + +* The `resourceQuantity.hasUnit` of the event must be the same as + `accountingQuantity.hasUnit` and `onhandQuantity.hasUnit` of the resource +* The `resourceInventoriedAs` can't be a container or packed resource. + + +### DeliverService Events + +`deliverService` events are used for indicating delivered services, such as +transportation of apples, painting the walls of the house. + +The events require `inputOf` and/or `outputOf`, and +`resourceConformsTo`. If both of `inputOf` and `outputOf` are provided, they +must refer to different Processes. + + +### Pickup and Dropoff Events + +`pickup` and `dropoff` events are used in pairs to transport resources from one +location to another. + +`pickup` and `dropoff` events are paired through the resource +`resourceInventoriedAs`. If they both refer to the same resource, they are +paired. That's the definition of "pair" here. + +The `pickup` events require `inputOf`, `resourceQuantity`, and +`resourceInventoriedAs`, and that the `provider` and `receiver` are the same +agents. + +The `pickup` events also require that: + +* The `provider` is the same agent as the `custodian` of the resource + `resourceInventoriedAs` +* The `resourceInventoriedAs` can't be a packed resource +* The `resourceQuantity.hasUnit` of the event must be the same as + `onhandQuantity.hasUnit` of the resource `resourceInventoriedAs` +* The `onhandQuantity.hasNumericalValue` of the resource is positive +* The `resourceQuantity.hasNumericalValue` of the event must be the same as + `onhandQuantity.hasNumericalValue` of the resource `resourceInventoriedAs` +* There is no other `pickup` event that refers to the same resource + `resourceInventoriedAs` in the same process + +The `dropoff` events requires `outputOf`, `resourceQuantity`, and +`resourceInventoriedAs`, and that the `provider` and `receiver` are the same +agents. + +The `dropoff` events also requires that: + +* There is exactly one `pickup` event referring to the same resource + `resourceInventoriedAs` in the same process. Due to this, most of the + `pickup` events requrimenst apply here out of the box +* The `provider` is the same agent as the `provider` of the paired event +* There is no other `dropoff` events that refer to the same resource + `resourceInventoriedAs` in the same process +* The `resourceQuantity.hasUnit` of the event must be the same as + the paired `pickup` event's `resourceQuantity.hasUnit` + +If `toLocation` is provided, `dropoff` events will set the `currentLocation` of +the resource `resourceInventoriedAs`. If the resource `resourceInventoriedAs` +is a container, it'll also set the `currentLocation` of all the contained +resources. + +I'm thinking to add another validation logic here: until the resource +`resourceInventoriedAs` is `dropoff`'ed, any other event that are not in the +same process won't be able to affect it (as in `consume`, `cite`, `use`, +`transfer`, and so on). + + +### Accept and Modify Events + +`accept` and `modify` events are used in pairs and have the follow +functionalities: + +* set a resource's `stage` field +* specify the container resource used for `pack` and `unpack` + +`accept` and `modify` events are paired through the resource +`resourceInventoriedAs`. If they both refer to the same resource, they are +paired. That's the definition of "pair" here. + +The `accept` events require `inputOf`, `resourceQuantity`, and +`resourceInventoriedAs`, and that the `provider` and `receiver` are the same +agents. + +The `accept` events also require that: + +* The `provider` is the same agent as the `custodian` of the resource + `resourceInventoriedAs` +* The `resourceInventoriedAs` can't be a packed resource. +* There is no other `accept` event that refers to the same resource + `resourceInventoriedAs` in the same process +* The `resourceQuantity.hasUnit` of the event must be the same as + `onhandQuantity.hasUnit` of the resource `resourceInventoriedAs` +* There is no `pack` or `unpack` events in the same process +* If the resource `resourceInventoriedAs` is a contanier, the + `onhandQuantity.hasNumericalValue` of the resource is positive +* If the resource `resourceInventoriedAs` is a container, the + `resourceQuantity.hasNumericalValue` of the event must be the same as + `onhandQuantity.hasNumericalValue` of the resource + +If these requirements above are met, the `onhandQuantity.hasNumericalValue` of +the resource `resourceInventoriedAs` will be decreased by +`resourceQuantity.hasNumericalValue` of the event. + +The `modify` events require `outputOf`, `resourceQuantity`, and +`resourceInventoriedAs`, and that the `provider` and `receiver` are the same +agents. + +The `modify` events also require that: + +* There is exactly one `accept` event referring to the same resource + `resourceInventoriedAs` in the same process. Due to this, most of the + `accept` events requrimenst apply here out of the box +* The `provider` is the same agent as the `provider` of the paired event +* The `resourceQuantity.hasUnit` of the event must be the same as + the paired `accept` event's `resourceQuantity.hasUnit` +* There is no other `modify` events that refer to the same resource + `resourceInventoriedAs` in the same process +* The `resourceQuantity.hasNumericalValue` of the event must be the same as + the paired `accept` event's `resourceQuantity.hasNumericalValue` + +If these requirements above are met, the `onhandQuantity.hasNumericalValue` of +the resource `resourceInventoriedAs` will be increased by +`resourceQuantity.hasNumericalValue` of the event, and the resource's `stage` +will be set to the same ProcessesSpecification of the current Process (`basedOn` +field of the Process). Note that this also includes the `null` value. + + +### Pack and Unpack Events + +`pack` and `unpack` events are *not* used in pairs, even though it kinda sounds +like that. `pack` events put a resource into a container resource, `unpack` +events take them out. + +The `pack` events require `inputOf`, and `resourceInventoriedAs`, and that the +`provider` and `receiver` are the same agents. + +The `pack` events also require that: + +* There's exactly one `accept` event in the same process. It requires it + beforehand so that the back-end can see what container is used with this +* The `provider` is the same agent as the `custodian` of the resource + `resourceInventoriedAs` +* The `resourceInventoriedAs` can't be an already-packed resource +* There is no `unpack` events in the same process + +If these requirements above are met, the `containedIn` of the resource +`resourceInventoriedAs` will be set to `resourceInventoriedAs` of the accept +event in the process. + +The `unpack` events require `outputOf`, and `resourceInventoriedAs`, and that the +`provider` and `receiver` are the same agents. + +The `unpack` events also require that: + +* There's exactly one `accept` event in the same process. It requires it + beforehand so that the back-end can see what container is used with this +* The `provider` is the same agent as the `custodian` of the resource + `resourceInventoriedAs` +* The resource `resourceInventoriedAs` is actually in the container provided by + the `accept` event +* There is no `pack` events in the same process + +If these requirements above are met, the `containedIn` of the resource +`resourceInventoriedAs` will be set to `null`. + + +### TransferCustody Events + +`transferCustody` events transfer the custody ownership, that is, `custodian` +and thus, it only affects `onhandQuantity`. + +There are two things a `transferCustody` event can do: + +* when only `resourceInventoriedAs` is provided, it'll create a new resource on + the other end +* when both `resourceInventoriedAs` and `toResourceInventoriedAs` are provided, + it'll increase the `onhandQuantity` of `toResourceInventoriedAs` while + decreasing `resourceInventoriedAs`'s + +In any case, they require `resourceInventoriedAs`, `resourceQuantity` and, +optionally if you want to "transfer into" another resource, +`toResourceInventoriedAs`. + +If only `resourceInventoriedAs` is provided, you need to fulfill these +requirements: + +* The `provider` is the same agent as the `custodian` of the resource + `resourceInventoriedAs` +* The `resourceInventoriedAs` can't be a packed resource +* The `resourceQuantity.hasUnit` of the event must be the same as + `onhandQuantity.hasUnit` of the resource `resourceInventoriedAs` +* If the resource `resourceInventoriedAs` is a container, the + `onhandQuantity.hasNumericalValue` of the resource must be postitive +* If the resource `resourceInventoriedAs` is a container, + `resourceQuantity.hasNumericalValue` of the event must be the same as + `onhandQuantity.hasNumericalValue` of the resource + +If these requirements above are met, it'll create a new resource that will: + +* have `onhandQuantity.hasUnit` and `onhandQuantity.hasNumericalValue` set from + `resourceQuantity` of the event +* have `accountingQuantity.hasNumericalValue` set to `0` and + `accountingQuantity.hasUnit` set to `resourceQuantity.hasUnit` of the event +* have `currentLocation` set to `toLocation` of the event, if it is available +* have all the other fields copied from the resource `resourceInventoriedAs`, + except for `name`, `note`, `trackingIdentifier` if they are provided by + `newInventoriedResource` when creating the event + +It'll also decrease the `onhandQuantity.hasNumericalValue` of the resourece +`resourceInventoriedAs` by `resourceQuantity.hasNumericalValue` of the event. +And if the resource `resourceInventoriedAs` was a container, the packed resources' +`containedIn` will be set to the newly created resource and `custodian` set to +`receiver` of the event. + +If both `resourceInventoriedAs` and `toResourceInventoriedAs` are provided, you +need to fulfill these requirements: + +* The `provider` is the same agent as the `custodian` of the resource + `resourceInventoriedAs` +* The `resourceInventoriedAs` and `toResourceInventoriedAs` can't be a packed + resource +* The `resourceQuantity.hasUnit` of the event must be the same as + `onhandQuantity.hasUnit` of the resource `resourceInventoriedAs` and + `toResourceInventoriedAs` +* The `resourceInventoriedAs.conformsTo` and + `toResourceInventoriedAs.conformsTo` must bethe same +* If the resource `resourceInventoriedAs` is a container, the + `onhandQuantity.hasNumericalValue` of the resource must be postitive +* If the resource `resourceInventoriedAs` is a container, + `resourceQuantity.hasNumericalValue` of the event must be the same as + `onhandQuantity.hasNumericalValue` of the resource + +If these requirements above are met, it'll increase the +`onhandQuantity.hasNumericalValue` of the resource `toResourceInventoriedAs` +while decreasing `onhandQuantity.hasNumericalValue` of `resourceInventoriedAs` +by `resourceQuantity.hasNumericalValue` of the event. And if the resource +`resourceInventoriedAs` was a container, the packed resources' `containedIn` +will be set to `toResourceInventoriedAs` and `custodian` set to `receiver` of +the event. + + +### TransferAllRights Events + +`transferAllRight` events transfer the accounting ownership, that is, +`primaryAccountable` and thus, it only affects `accountingQuantity`. + +There are two things a `transferAllRight` event can do: + +* when only `resourceInventoriedAs` is provided, it'll create a new resource on + the other end +* when both `resourceInventoriedAs` and `toResourceInventoriedAs` are provided, + it'll increase the `accountingQuantity` of `toResourceInventoriedAs` while + decreasing `resourceInventoriedAs`'s + +In any case, they require `resourceInventoriedAs`, `resourceQuantity` and, +optionally if you want to "transfer into" another resource, +`toResourceInventoriedAs`. + +If only `resourceInventoriedAs` is provided, you need to fulfill these +requirements: + +* The `provider` is the same agent as the `primaryAccountable` of the resource + `resourceInventoriedAs` +* The `resourceInventoriedAs` can't be a packed resource +* The `resourceQuantity.hasUnit` of the event must be the same as + `accountingQuantity.hasUnit` of the resource `resourceInventoriedAs` +* If the resource `resourceInventoriedAs` is a container, the + `accountingQuantity.hasNumericalValue` of the resource must be postitive +* If the resource `resourceInventoriedAs` is a container, + `resourceQuantity.hasNumericalValue` of the event must be the same as + `accountingQuantity.hasNumericalValue` of the resource + +If these requirements above are met, it'll create a new resource that will: + +* have `accountingQuantity.hasUnit` and `accountingQuantity.hasNumericalValue` + set from `resourceQuantity` of the event +* have `onhandQuantity.hasNumericalValue` set to `0` and + `onhandQuantity.hasUnit` set to `resourceQuantity.hasUnit` of the event +* have all the other fields copied from the resource `resourceInventoriedAs`, + except for `name`, `note`, `trackingIdentifier` if they are provided by + `newInventoriedResource` when creating the event + +It'll also decrease the `accountingQuantity.hasNumericalValue` of the resourece +`resourceInventoriedAs` by `resourceQuantity.hasNumericalValue` of the event. +And if the resource `resourceInventoriedAs` was a container, the packed resources' +`containedIn` will be set to the newly created resource and `primaryAccountable` +set to `receiver` of the event. + +If both `resourceInventoriedAs` and `toResourceInventoriedAs` are provided, you +need to fulfill these requirements: + +* The `provider` is the same agent as the `primaryAccountable` of the resource + `resourceInventoriedAs` +* The `resourceInventoriedAs` and `toResourceInventoriedAs` can't be a packed + resource +* The `resourceQuantity.hasUnit` of the event must be the same as + `accountingQuantity.hasUnit` of the resource `resourceInventoriedAs` and + `toResourceInventoriedAs` +* The `resourceInventoriedAs.conformsTo` and + `toResourceInventoriedAs.conformsTo` must bethe same +* If the resource `resourceInventoriedAs` is a container, the + `accountingQuantity.hasNumericalValue` of the resource must be postitive +* If the resource `resourceInventoriedAs` is a container, + `resourceQuantity.hasNumericalValue` of the event must be the same as + `accountingQuantity.hasNumericalValue` of the resource + +If these requirements above are met, it'll increase the +`accountingQuantity.hasNumericalValue` of the resource `toResourceInventoriedAs` +while decreasing `accountingQuantity.hasNumericalValue` of +`resourceInventoriedAs` by `resourceQuantity.hasNumericalValue` of the event. +And if the resource `resourceInventoriedAs` was a container, the packed +resources' `containedIn` will be set to `toResourceInventoriedAs` and +`primaryAccountable` set to `receiver` of the event. + + +### Transfer Events + +`transfer` events transfer the both types of ownership, that is, +`primaryAccountable` and `custodian` and thus, it affects both +`accountingQuantity` and `onhandQuantity`. + +There are two things a `transfer` event can do: + +* when only `resourceInventoriedAs` is provided, it'll create a new resource on + the other end +* when both `resourceInventoriedAs` and `toResourceInventoriedAs` are provided, + it'll increase the `accountingQuantity` and `onhandQuantity` of + `toResourceInventoriedAs` while decreasing `resourceInventoriedAs`'s + +In any case, they require `resourceInventoriedAs`, `resourceQuantity` and, +optionally if you want to "transfer into" another resource, +`toResourceInventoriedAs`. + +If only `resourceInventoriedAs` is provided, you need to fulfill these +requirements: + +* The `provider` is the same agent as the `primaryAccountable` and `custodian` + of the resource `resourceInventoriedAs` +* The `resourceInventoriedAs` can't be a packed resource +* The `resourceQuantity.hasUnit` of the event must be the same as + `accountingQuantity` and `onhandQuantity.hasUnit` of the resource + `resourceInventoriedAs` +* If the resource `resourceInventoriedAs` is a container, the + `accountingQuantity.hasNumericalValue` and `onhandQuantity.hasNumericalValue` + of the resource must be postitive +* If the resource `resourceInventoriedAs` is a container, + `resourceQuantity.hasNumericalValue` of the event must be the same as + `accountingQuantity.hasNumericalValue` and `onhandQuantity.hasNumericalValue` + of the resource + +If these requirements above are met, it'll create a new resource that will: + +* have `accountingQuantity.hasUnit`, `accountingQuantity.hasNumericalValue`, + `onhandQuantity.hasUnit`, and `onhandQuantity.hasNumericalValue` set from + `resourceQuantity` of the event +* have all the other fields copied from the resource `resourceInventoriedAs`, + except for `name`, `note`, `trackingIdentifier` if they are provided by + `newInventoriedResource` when creating the event + +It'll also decrease the `accountingQuantity.hasNumericalValue` and +`onhandQuantity.hasNumericalValue` of the resourece `resourceInventoriedAs` by +`resourceQuantity.hasNumericalValue` of the event. +And if the resource `resourceInventoriedAs` was a container, the packed resources' +`containedIn` will be set to the newly created resource, and `primaryAccountable` +and `custodian` set to `receiver` of the event. + +If both `resourceInventoriedAs` and `toResourceInventoriedAs` are provided, you +need to fulfill these requirements: + +* The `provider` is the same agent as the `primaryAccountable` and `custodian` + of the resource `resourceInventoriedAs` +* The `resourceInventoriedAs` and `toResourceInventoriedAs` can't be a packed + resource +* The `resourceQuantity.hasUnit` of the event must be the same as + `accountingQuantity` and `onhandQuantity.hasUnit` of the resource + `resourceInventoriedAs` and `toResourceInventoriedAs` +* The `resourceInventoriedAs.conformsTo` and + `toResourceInventoriedAs.conformsTo` must bethe same +* If the resource `resourceInventoriedAs` is a container, the + `accountingQuantity.hasNumericalValue` and `onhandQuantity.hasNumericalValue` + of the resource must be postitive +* If the resource `resourceInventoriedAs` is a container, + `resourceQuantity.hasNumericalValue` of the event must be the same as + `accountingQuantity.hasNumericalValue` and `onhandQuantity.hasNumericalValue` + of the resource + +If these requirements above are met, it'll increase the +`accountingQuantity.hasNumericalValue` and `onhandQuantity.hasNumericalValue` of +the resource `toResourceInventoriedAs` while decreasing +`accountingQuantity.hasNumericalValue` and `onhandQuantity.hasNumericalValue` of +`resourceInventoriedAs` by `resourceQuantity.hasNumericalValue` of the event. +And if the resource `resourceInventoriedAs` was a container, the packed +resources' `containedIn` will be set to `toResourceInventoriedAs`, and +`primaryAccountable` and `custodian` set to `receiver` of the event. + + +### Move Events + +`move` events are used for internal dividing and such. When companed to +`transfer`, it is similar to what `produce` is to `raise` and what `consume` is +to `lower` + +The only differenece between `move` and `transfer` in the back-end is that +`move` requires both the `provider` and `receiver` be the same person. + + +## Examples + + +### Produce Examples +Harvesting apples from a tree farm. + +Give: +``` +mutation { + createEconomicEvent( + event: { + action: "produce" + provider: "01FWN12XX7TJX1AFF5KA4WPNN9" # bob + receiver: "01FWN12XX7TJX1AFF5KA4WPNN9" # bob + outputOf: "01FWN136SPDMKWWF23SWQZRM5F" # harvesting apples process + resourceConformsTo: "01FWN136Y4ZZ7K9F314HQ7MKRG" # apple + resourceQuantity: { + hasNumericalValue: 50 + hasUnit: "01FWN136S5VPCCR3B3TGYDYEY9" # kilogram + } + atLocation: "01FWN136ZAPQ5ENBF3FZ79935D" # bob's farm + hasPointInTime: "2022-01-02T03:04:05Z" + } + newInventoriedResource: { + name: "bob's apples" + note: "bob's delish apples" + trackingIdentifier: "lot 123" + currentLocation: "01FWN136ZAPQ5ENBF3FZ79935D" # bob's farm + stage: "01FWN136X183DM43CTWXESNWAB" # fresh + } + ) { + economicEvent { + id + action {id} + provider {id} + receiver {id} + outputOf {id} + resourceConformsTo {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + atLocation {id} + hasPointInTime + } + economicResource { # this is the newly-created resource + id + name + note + trackingIdentifier + stage {id} + currentLocation {id} + conformsTo {id} + primaryAccountable {id} + custodian {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWN16MMRPWEWCWHGNNH9TCTK", + "action": {"id": "produce"}, + "provider": {"id": "01FWN12XX7TJX1AFF5KA4WPNN9"}, # bob + "receiver": {"id": "01FWN12XX7TJX1AFF5KA4WPNN9"}, # bob + "outputOf": {"id": "01FWN136SPDMKWWF23SWQZRM5F"}, # harvesting apples process + "resourceConformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "resourceQuantity": { + "hasNumericalValue": 50, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "atLocation": {"id": "01FWN136ZAPQ5ENBF3FZ79935D"}, # bob's farm + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + }, + "economicResource": { + "id": "01FWN16MMVVVWEWTMC6Z5PMCM0", + "name": "bob's apples", + "note": "bob's delish apples", + "trackingIdentifier": "lot 123", + "stage": {"id": "01FWN136X183DM43CTWXESNWAB"}, # fresh + "currentLocation": {"id": "01FWN136ZAPQ5ENBF3FZ79935D"}, # bob's farm + "conformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "primaryAccountable": {"id": "01FWN12XX7TJX1AFF5KA4WPNN9"}, # bob + "custodian": {"id": "01FWN12XX7TJX1AFF5KA4WPNN9"}, # bob + "accountingQuantity": { + "hasNumericalValue": 50, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "onhandQuantity": { + "hasNumericalValue": 50, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + } + } + } + } +} +``` + +Harvesting apples, but using the existing apple resource (created above). + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "produce" + provider: "01FWN12XX7TJX1AFF5KA4WPNN9" # bob + receiver: "01FWN12XX7TJX1AFF5KA4WPNN9" # bob + outputOf: "01FWN136SPDMKWWF23SWQZRM5F" # harvesting apples process + resourceConformsTo: "01FWN136Y4ZZ7K9F314HQ7MKRG" # apple + resourceQuantity: { + hasNumericalValue: 15 + hasUnit: "01FWN136S5VPCCR3B3TGYDYEY9" # kilogram + } + resourceInventoriedAs: "01FWN16MMVVVWEWTMC6Z5PMCM0" # resource "bob's apples" + atLocation: "01FWN136ZAPQ5ENBF3FZ79935D" # bob's farm + hasPointInTime: "2022-01-02T03:04:05Z" + }) { + economicEvent { + id + action {id} + provider {id} + receiver {id} + outputOf {id} + resourceConformsTo {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + resourceInventoriedAs { # this is the already-existing resource "bob's apples" + id + name + note + trackingIdentifier + stage {id} + currentLocation {id} + conformsTo {id} + primaryAccountable {id} + custodian {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + } + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWN2Z7XNACJBT2K4TR9EM40W", + "action": {"id": "produce"}, + "provider": {"id": "01FWN12XX7TJX1AFF5KA4WPNN9"}, # bob + "receiver": {"id": "01FWN12XX7TJX1AFF5KA4WPNN9"}, # bob + "outputOf": {"id": "01FWN136SPDMKWWF23SWQZRM5F"}, # harvesting apples process + "resourceConformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "resourceQuantity": { + "hasNumericalValue": 15, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "atLocation": {"id": "01FWN136ZAPQ5ENBF3FZ79935D"}, # bob's farm + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + }, + "economicResource": { + "id": "01FWN16MMVVVWEWTMC6Z5PMCM0", + "name": "bob's apples", + "note": "bob's delish apples", + "trackingIdentifier": "lot 123", + "stage": {"id": "01FWN136X183DM43CTWXESNWAB"}, # fresh + "currentLocation": {"id": "01FWN136ZAPQ5ENBF3FZ79935D"}, # bob's farm + "conformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "primaryAccountable": {"id": "01FWN12XX7TJX1AFF5KA4WPNN9"}, # bob + "custodian": {"id": "01FWN12XX7TJX1AFF5KA4WPNN9"}, # bob + "accountingQuantity": { + "hasNumericalValue": 65, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "onhandQuantity": { + "hasNumericalValue": 65, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + } + } + } + } +} +``` + + +### Raise Examples +Suppose a person joined to the instance at a later time. But they already have +some resources they want to import. You can use `raise` events for that. + +Give: +``` +mutation { + createEconomicEvent( + event: { + action: "raise" + provider: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + resourceConformsTo: "01FWN136Y4ZZ7K9F314HQ7MKRG" # apple + resourceQuantity: { + hasNumericalValue: 30 + hasUnit: "01FWN136S5VPCCR3B3TGYDYEY9" # kilogram + } + atLocation: "01FWN3VH3H8T4KHN8XC7FJ32V3" # alice's kitchen + hasPointInTime: "2022-01-02T03:04:05Z" + } + newInventoriedResource: { + name: "alice's apples" + note: "alice's delish apples" + trackingIdentifier: "lot 123" + currentLocation: "01FWN3VH3H8T4KHN8XC7FJ32V3" # alice's kitchen + stage: "01FWN136X183DM43CTWXESNWAB" # fresh + } + ) { + economicEvent { + id + action {id} + provider {id} + receiver {id} + resourceConformsTo {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + atLocation {id} + hasPointInTime + } + economicResource { # this is the newly-created resource + id + name + note + trackingIdentifier + stage {id} + currentLocation {id} + conformsTo {id} + primaryAccountable {id} + custodian {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWN3YAT32CGRFJG827XWTSWY", + "action": {"id": "raise"}, + "provider": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "resourceConformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "resourceQuantity": { + "hasNumericalValue": 30, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "atLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + }, + "economicResource": { + "id": "01FWN3ZY2Z8ZJ071YXJ315KC2W", + "name": "alice's apples", + "note": "alice's delish apples", + "trackingIdentifier": "lot 123", + "stage": {"id": "01FWN136X183DM43CTWXESNWAB"}, # fresh + "currentLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "conformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "primaryAccountable": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "custodian": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "accountingQuantity": { + "hasNumericalValue": 30, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "onhandQuantity": { + "hasNumericalValue": 30, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + } + } + } + } +} +``` + +Found more apples? Add them to the stack! + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "raise" + provider: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + resourceConformsTo: "01FWN136Y4ZZ7K9F314HQ7MKRG" # apple + resourceQuantity: { + hasNumericalValue: 15 + hasUnit: "01FWN136S5VPCCR3B3TGYDYEY9" # kilogram + } + resourceInventoriedAs: "01FWN3ZY2Z8ZJ071YXJ315KC2W" # resource "alice's apples" + atLocation: "01FWN3VH3H8T4KHN8XC7FJ32V3" # alice's kitchen + hasPointInTime: "2022-01-02T03:04:05Z" + }) { + economicEvent { + id + action {id} + provider {id} + receiver {id} + resourceConformsTo {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + resourceInventoriedAs { # this is the already-existing resource "bob's apples" + id + name + note + trackingIdentifier + stage {id} + currentLocation {id} + conformsTo {id} + primaryAccountable {id} + custodian {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + } + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWN3ZY2Z8ZJ071YXJ315KC2W", + "action": {"id": "raise"}, + "provider": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "resourceConformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "resourceQuantity": { + "hasNumericalValue": 15, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "resourceInventoriedAs": { + "id": "01FWN3ZY2Z8ZJ071YXJ315KC2W", + "name": "alice's apples", + "note": "alice's delish apples", + "trackingIdentifier": "lot 123", + "stage": {"id": "01FWN136X183DM43CTWXESNWAB"}, # fresh + "currentLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "conformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "primaryAccountable": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "custodian": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "accountingQuantity": { + "hasNumericalValue": 45, + "hasUnit": {"id": "01FW15136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "onhandQuantity": { + "hasNumericalValue": 45, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + } + }, + "atLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + } + } + } +} +``` + + +### Consume Examples + +Consume apples for making apple juice. + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "consume" + provider: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + inputOf: "01FWN5SVCHH662KD10E73M221J" # process "making apple juice" + resourceInventoriedAs: "01FWN3ZY2Z8ZJ071YXJ315KC2W" # resource "alice's apples" 45kg + resourceQuantity: { + hasNumericalValue: 20 + hasUnit: "01FWN136S5VPCCR3B3TGYDYEY9" # kilogram + } + atLocation: "01FWN3VH3H8T4KHN8XC7FJ32V3" # alice's kitchen + hasPointInTime: "2022-01-02T03:04:05Z" + }) { + economicEvent { + id + action {id} + provider {id} + receiver {id} + inputOf {id} + resourceInventoriedAs { + id + name + note + trackingIdentifier + stage {id} + currentLocation {id} + conformsTo {id} + primaryAccountable {id} + custodian {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + } + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWN6ABS0RCKEVC636N8TY58D", + "action": {"id": "consume"}, + "provider": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "inputOf": {"id": "01FWN5SVCHH662KD10E73M221J"}, # process "making apple juice" + "resourceConformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "resourceQuantity": { + "hasNumericalValue": 20, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "resourceInventoriedAs": { + "id": "01FWN3ZY2Z8ZJ071YXJ315KC2W", + "name": "alice's apples", + "note": "alice's delish apples", + "trackingIdentifier": "lot 123", + "stage": {"id": "01FWN136X183DM43CTWXESNWAB"}, # fresh + "currentLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "conformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "primaryAccountable": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "custodian": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "accountingQuantity": { + "hasNumericalValue": 25, # = 45 - 15 + "hasUnit": {"id": "01FW15136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "onhandQuantity": { + "hasNumericalValue": 25, # = 45 - 15 + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + } + }, + "atLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + } + } + } +} +``` + +### Lower Examples + +Oh, did you import 5kg of apples accidentally? We can `lower` it! + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "lower" + provider: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + resourceInventoriedAs: "01FWN3ZY2Z8ZJ071YXJ315KC2W" # resource "alice's apples" 20kg + resourceQuantity: { + hasNumericalValue: 5 + hasUnit: "01FWN136S5VPCCR3B3TGYDYEY9" # kilogram + } + atLocation: "01FWN3VH3H8T4KHN8XC7FJ32V3" # alice's kitchen + hasPointInTime: "2022-01-02T03:04:05Z" + }) { + economicEvent { + id + action {id} + provider {id} + receiver {id} + resourceInventoriedAs { + id + name + note + trackingIdentifier + stage {id} + currentLocation {id} + conformsTo {id} + primaryAccountable {id} + custodian {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + } + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWN6ABS0RCKEVC636N8TY58D", + "action": {"id": "lower"}, + "provider": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "resourceConformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "resourceQuantity": { + "hasNumericalValue": 5, + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "resourceInventoriedAs": { + "id": "01FWN3ZY2Z8ZJ071YXJ315KC2W", + "name": "alice's apples", + "note": "alice's delish apples", + "trackingIdentifier": "lot 123", + "stage": {"id": "01FWN136X183DM43CTWXESNWAB"}, # fresh + "currentLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "conformsTo": {"id": "01FWN136Y4ZZ7K9F314HQ7MKRG"}, # apple + "primaryAccountable": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "custodian": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "accountingQuantity": { + "hasNumericalValue": 15, # = 20 - 5 + "hasUnit": {"id": "01FW15136S5VPCCR3B3TGYDYEY9"} # kilogram + }, + "onhandQuantity": { + "hasNumericalValue": 15, # = 20 - 5 + "hasUnit": {"id": "01FWN136S5VPCCR3B3TGYDYEY9"} # kilogram + } + }, + "atLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + } + } + } +} +``` + + +### Use Examples + +Suppose you want to make some apple juice out of... apples. You would `consume` +some apple resources and `produce` some apple juice resources, but this story +doesn't sound quite right. If you want to record how you did get the juice, you +could use a `use` event, specifying that you used a juicer. + +The below example demonstates that we used a juicer machine for 2 hours. + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "use" + provider: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + inputOf: "01FWN9E7MD5JKJE52EMP5MHYT3" # process "making apple juice" + resourceInventoriedAs: "01FWN9A23V1Y1XRJPZ5CG2BDYW" # the juicer + resourceQuantity: { + hasNumericalValue: 1 + hasUnit: "01FWN9828J8M6NB95C0GV0Z324" # one/each/pcs + } + effortQuantity: { + hasNumericalValue: 2 + hasUnit: "01FWN96JV5KG2N91Q3FSZRZZQ3" # hour + } + atLocation: "01FWN3VH3H8T4KHN8XC7FJ32V3" # alice's kitchen + hasPointInTime: "2022-01-02T03:04:05Z" + }) { + economicEvent { + id + action {id} + provider {id} + receiver {id} + inputOf {id} + resourceInventoriedAs { + id + name + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + } + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + effortQuantity { + hasNumericalValue + hasUnit {id} + } + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWN9W5Y9JY6ZFTZ6518SF6PP", + "action": {"id": "use"}, + "provider": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "inputOf": {"id": "01FWN9E7MD5JKJE52EMP5MHYT3"}, # process "making apple juice" + "resourceInventoriedAs": { + "id": "01FWN9A23V1Y1XRJPZ5CG2BDYW", + "name": "the juicer machine", + "accountingQuantity": { + "hasNumericalValue": 1, + "hasUnit": {"id": "01FWN9828J8M6NB95C0GV0Z324"} # one/each/pcs + }, + "onhandQuantity": { + "hasNumericalValue": 1, + "hasUnit": {"id": "01FWN9828J8M6NB95C0GV0Z324"} # one/each/pcs + } + }, + "resourceQuantity": { + "hasNumericalValue": 1, + "hasUnit": {"id": "01FWN9828J8M6NB95C0GV0Z324"} # one/each/pcs + }, + "effortQuantity": { + "hasNumericalValue": 2, + "hasUnit": {"id": "01FWN96JV5KG2N91Q3FSZRZZQ3"} # hour + }, + "atLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + } + } + } +} +``` + +You can also choose to not use `resourceQuantity` or `resourceInventoriedAs` at +all. But if you choose to not use `resourceInventoriedAs`, you must provide a +ResourceSpecification in the field `resourceConformsTo`. + +This would mean that we used a machine for 2 hours, but we didn't want to use an +actual resource for it and didn't want to provide how many of them we used. +This is a valid usage of `use` events. + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "use" + provider: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + inputOf: "01FWN9E7MD5JKJE52EMP5MHYT3" # process "making apple juice" + resourceConformsTo: "01FWNA5WDM5FPJYPQ3BTGMFTQ5" # resource spec "juicer machine" + effortQuantity: { + hasNumericalValue: 2 + hasUnit: "01FWN96JV5KG2N91Q3FSZRZZQ3" # hour + } + atLocation: "01FWN3VH3H8T4KHN8XC7FJ32V3" # alice's kitchen + hasPointInTime: "2022-01-02T03:04:05Z" + }) { + economicEvent { + id + action {id} + provider {id} + receiver {id} + inputOf {id} + resourceConformsTo {id} + effortQuantity { + hasNumericalValue + hasUnit {id} + } + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWNA7DETHVJ2C97AQWK55Y8B", + "action": {"id": "use"}, + "provider": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "inputOf": {"id": "01FWN9E7MD5JKJE52EMP5MHYT3"}, # process "making apple juice" + "resourceConformsTo": {"id": "01FWN9A23V1Y1XRJPZ5CG2BDYW"}, + "effortQuantity": { + "hasNumericalValue": 2, + "hasUnit": {"id": "01FWN96JV5KG2N91Q3FSZRZZQ3"} # hour + }, + "atLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + } + } + } +} +``` + + +### Work Examples + +`works` events are used when you want to specify what kind of work you put in a +process. Suppose you are making some apple pies, and you are kneading the dough +for the crust; you'd put "kneading the dough" as a work event to the proccess. + +There's a small catch, though: as the term "resource", thus its "specification", +is broad in the Valueflows vocabulary, you are required to provide what kind of +work you do to the field `resourceConformsTo`, that is, there's no such field +as `effortConformsTo` and a type as `EffortSpecification`. Such work would be +"kneading" in a "making apple pies" scenario. + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "work" + provider: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + inputOf: "01FWTXNRFVYPR98WQGPVB69DW8" # process "making apple pies" + resourceConformsTo: "01FWTWNTZEWYKAT0S45809QMFN" # resource spec "kneading" + effortQuantity: { + hasNumericalValue: 2 + hasUnit: "01FWN96JV5KG2N91Q3FSZRZZQ3" # hour + } + atLocation: "01FWN3VH3H8T4KHN8XC7FJ32V3" # alice's kitchen + hasPointInTime: "2022-01-02T03:04:05Z + }) { + economicEvent { + id + provider {id} + receiver {id} + inputOf {id} + resourceInventoriedAs {id} + effortQuantity { + hasNumericalValue + hasUnit {id} + } + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWTXN8ZY01XXNG9QK47PEKNH", + "action": {"id": "work"}, + "provider": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "inputOf": {"id": "01FWTXNRFVYPR98WQGPVB69DW8"}, # process "making apple pies" + "resourceConformsTo": {"id": "01FWTWNTZEWYKAT0S45809QMFN"}, # resource spec "kneading" + "effortQuantity": { + "hasNumericalValue": 2, + "hasUnit": {"id": "01FWN96JV5KG2N91Q3FSZRZZQ3"}, # hour + }, + "atLocation": {"id": "01FWN3VH3H8T4KHN8XC7FJ32V3"}, # alice's kitchen + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + } + } + } +} +``` + + +### Cite Examples + +Suppose you are some sort of instruction paper, design files, blueprints (all +can be digital as well) to produce something. You record the history of that +with `cite` events. They cosume the cited resource. They're there because they +help us to create a more meaningful history. + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "cite" + provider: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + inputOf: "01FWPA0H6YB1NDP2X1HNCXFQN9" # process "creating flags" + resourceInventoriedAs: "01FWPA7HXMA25AGA3VXXR0540K" # resource "flag design" + resourceQuantity: { + hasNumericalValue: 1 + hasUnit: "01FWN9828J8M6NB95C0GV0Z324" # one/each/pcs + } + atLocation: "01FWPAG1YVBXXPTQNSCFG48RTY" # alice's workshop + hasPointInTime: "2022-01-02T03:04:05Z + }) { + economicEvent { + id + provider {id} + receiver {id} + inputOf {id} + resourceInventoriedAs {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWPAE4JC2P039G4B93D0AS4Q", + "action": {"id": "cite"}, + "provider": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "inputOf": {"id": "01FWPA0H6YB1NDP2X1HNCXFQN9"}, # process "creating flags" + "resourceInventoriedAs": {"id": "01FWPA7HXMA25AGA3VXXR0540K"}, # resource "flag design" + "resourceQuantity": { + "hasNumericalValue": 1, + "hasUnit": {"id": "01FWN9828J8M6NB95C0GV0Z324"}, # one/each/pcs + }, + "atLocation": {"id": "01FWPAG1YVBXXPTQNSCFG48RTY"}, # alice's workshop + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + } + } + } +} +``` + +With `cite` events, you may wish to just use a ResourceSpecification instead of +an Economicresource. But, you must provide the quantity nonetheless. + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "cite" + provider: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice + inputOf: "01FWPA0H6YB1NDP2X1HNCXFQN9" # process "creating flags" + resourceConformsTo: "01FWPAN3ST2FE431DSBQTCMBN9" # resource spec "flag design" + resourceQuantity: { + hasNumericalValue: 1 + hasUnit: "01FWN9828J8M6NB95C0GV0Z324" # one/each/pcs + } + atLocation: "01FWPAG1YVBXXPTQNSCFG48RTY" # alice's workshop + hasPointInTime: "2022-01-02T03:04:05Z + }) { + economicEvent { + id + provider {id} + receiver {id} + inputOf {id} + resourceConformsTo {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWPAE4JC2P039G4B93D0AS4Q", + "action": {"id": "cite"}, + "provider": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice + "inputOf": {"id": "01FWPA0H6YB1NDP2X1HNCXFQN9"}, # process "creating flags" + "resourceConformsTo": {"id": "01FWPAN3ST2FE431DSBQTCMBN9"} # resource spec "flag design" + "resourceQuantity": { + "hasNumericalValue": 1, + "hasUnit": {"id": "01FWN9828J8M6NB95C0GV0Z324"}, # one/each/pcs + }, + "atLocation": {"id": "01FWPAG1YVBXXPTQNSCFG48RTY"}, # alice's workshop + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + } + } + } +} +``` + + +### DeliverService Examples + +When you want to indicate the services used in a process, you use +`deliverService` events. + +Painting a house, transporting a pizza, and dry-cleaning clothes are examples of +services. + +Similar to `work` events, `resourceConformsTo` refer to the type of service. + +Give: +``` +mutation { + createEconomicEvent(event: { + action: "deliverService" + provider: "01FWN12XX7TJX1AFF5KA4WPNN9" # bob the painter + receiver: "01FWN3QA3Q2G0JNYHBCCBEN76H" # alice the house owner + outputOf: "01FWV0BXSCMRWHRCFCQ82JM2S3" # process "painting alice's house" + resourceConformsTo: "01FWV0G7X0H03BQKPV0W8Q32EA" # resource spec "painting" + atLocation: "01FWV0REX2G4VHRRBH5QSWD7N8" # alice's house + hasPointInTime: "2022-01-02T03:04:05Z" + }) { + economicEvent { + id + provider {id} + receiver {id} + outputOf {id} + resourceConformsTo {id} + atLocation {id} + hasPointInTime + } + } +} +``` + +Get: +``` +{ + "data": { + "createEconomicEvent": { + "economicEvent": { + "id: "01FWV0N1FE320H75Q8RYVAFTR4", + "action": {"id": "deliverService"}, + "provider": {"id": "01FWN12XX7TJX1AFF5KA4WPNN9"}, # bob the painter + "receiver": {"id": "01FWN3QA3Q2G0JNYHBCCBEN76H"}, # alice the house owner + "outputOf": {"id": "01FWPA0H6YB1NDP2X1HNCXFQN9"}, # process "painting alice's house" + "resourceConformsTo": {"id": "01FWV0G7X0H03BQKPV0W8Q32EA"} # resource spec "painting" + "atLocation": {"id": "01FWV0REX2G4VHRRBH5QSWD7N8"}, # alice's workshop + "hasPointInTime": "2022-01-02T03:04:05.000000Z" + } + } + } +} +``` + +# GraphQL Documents + + +## Economic Events + +All the events require `action`, `provider`, `receiver` fields along with one of these datetime combinations (no particular validation regarding the datetime fields is performed, such as wether `hasBeginning` is actually older or equal to than `hasEnd`): + +* only `hasPointInTime` +* only `hasBeginning` +* only `hasEnd` +* both `hasBeginning` and `hasEnd` + +The rest of the sections will asume you are aware of this information. + + +### Produce Events + +Produce events require `outputOf`, `resourceConformsTo`, `resourceQuantity`, +and `newInventoriedResource.name`. You can provide the soon-to-be-created +resource's `name`, `note`, `trackingIdentifier` through +`newInventoriedResource`. Here is an example document that uses variables: + +``` +mutation ( + $outputOf: ID! + $provider: ID! + $receiver: ID! + $resourceConformsTo: ID! + $resourceQuantity: IMeasure! + $newInventoriedResource: EconomicResourceCreateParams! + $hasPointInTime: DateTime + $hasBeginning: DateTime + $hasEnd: DateTime +) { + createEconomicEvent( + event: { + action: "produce" + outputOf: $outputOf + provider: $provider + receiver: $receiver + resourceConformsTo: $resourceConformsTo + resourceQuantity: $resourceQuantity + hasPointInTime: $hasPointInTime + hasBeginning: $hasBeginning + hasEnd: $hasEnd + } + newInventoriedResource: $newInventoriedResource + ) { + economicEvent { + id + action {id} + outputOf {id} + provider {id} + receiver {id} + resourceConformsTo {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + resourceInventoriedAs { + id + name + note + primaryAccountable {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + conformsTo {id} + } + hasPointInTime + hasEnd + hasBeginning + } + } +} +``` + +and the example variables: + +``` +{ + "outputOf": "01G2Q2AT2PHQD56N9RFX3A240J", + "provider": "01FZFE8E43ANRY360J1E98PJ0Z", + "receiver": "01FZFE8E43ANRY360J1E98PJ0Z", + "resourceConformsTo": "01FTB03K54ZF38FHEKGVHTWGY8", + "resourceQuantity": { + "hasNumericalValue": 10.0, + "hasUnit": "01FTB06BQ64MSS7XSB3QMSW83R" + }, + "newInventoriedResource": { + "name": "some name", + "note": "some note" + }, + "hasEnd": "2022-01-02T03:04:05Z" +} +``` + + +### Consume Events + +Consume events require `inputOf`, `resourceInventoriedAs`, and +`resourceQuantity` fields. Here is an example document that uses variables: + +``` +mutation ( + $inputOf: ID! + $provider: ID! + $receiver: ID! + $resourceInventoriedAs: ID! + $resourceQuantity: IMeasure! + $hasPointInTime: DateTime + $hasBeginning: DateTime + $hasEnd: DateTime +) { + createEconomicEvent(event: { + action: "consume" + inputOf: $inputOf + provider: $provider + receiver: $receiver + resourceInventoriedAs: $resourceInventoriedAs + resourceQuantity: $resourceQuantity + hasPointInTime: $hasPointInTime + hasBeginning: $hasBeginning + hasEnd: $hasEnd + }) { + economicEvent { + id + action {id} + inputOf {id} + provider {id} + receiver {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + resourceInventoriedAs { + id + name + note + primaryAccountable {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + conformsTo {id} + } + hasPointInTime + hasEnd + hasBeginning + } + } +} +``` + +and the example variables: + +``` +{ + "inputOf": "01G2Q2AT2PHQD56N9RFX3A240J", + "provider": "01FZFE8E43ANRY360J1E98PJ0Z", + "receiver": "01FZFE8E43ANRY360J1E98PJ0Z", + "resourceInventoriedAs": "01FTB03K54ZF38FHEKGVHTWGY8", + "resourceQuantity": { + "hasNumericalValue": 10.0, + "hasUnit": "01FTB06BQ64MSS7XSB3QMSW83R" + }, + "hasPointInTime": "2022-01-02T03:04:05Z" +} +``` + + +### Raise Events + +Raise events are almost identical to produce events, execept for their semantic +meaning, and the fact that they don't require `outputOf` to be provided (that's +related to the semantic meaning). Here is an example document that uses +variables: + +``` +mutation ( + $provider: ID! + $receiver: ID! + $resourceConformsTo: ID! + $resourceQuantity: IMeasure! + $newInventoriedResource: EconomicResourceCreateParams! + $hasPointInTime: DateTime + $hasBeginning: DateTime + $hasEnd: DateTime +) { + createEconomicEvent( + event: { + action: "raise" + provider: $provider + receiver: $receiver + resourceConformsTo: $resourceConformsTo + resourceQuantity: $resourceQuantity + hasPointInTime: $hasPointInTime + hasBeginning: $hasBeginning + hasEnd: $hasEnd + } + newInventoriedResource: $newInventoriedResource + ) { + economicEvent { + id + action {id} + provider {id} + receiver {id} + resourceConformsTo {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + resourceInventoriedAs { + id + name + note + primaryAccountable {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + conformsTo {id} + } + hasPointInTime + hasEnd + hasBeginning + } + } +} +``` + +and the example variables: + +``` +{ + "provider": "01FZFE8E43ANRY360J1E98PJ0Z", + "receiver": "01FZFE8E43ANRY360J1E98PJ0Z", + "resourceConformsTo": "01FTB03K54ZF38FHEKGVHTWGY8", + "resourceQuantity": { + "hasNumericalValue": 10.0, + "hasUnit": "01FTB06BQ64MSS7XSB3QMSW83R" + }, + "newInventoriedResource": { + "name": "some name", + "note": "some note" + }, + "hasBeginning": "2022-01-02T03:04:05Z" +} +``` + + +### Lower Events + +Raise events are almost identical to consume events, execept for their semantic +meaning, and the fact that they don't require `inputOf` to be provided (that's +related to the semantic meaning). Here is an example document that uses +variables: + +``` +mutation ( + $provider: ID! + $receiver: ID! + $resourceInventoriedAs: ID! + $resourceQuantity: IMeasure! + $hasPointInTime: DateTime + $hasBeginning: DateTime + $hasEnd: DateTime +) { + createEconomicEvent(event: { + action: "lower" + provider: $provider + receiver: $receiver + resourceInventoriedAs: $resourceInventoriedAs + resourceQuantity: $resourceQuantity + hasPointInTime: $hasPointInTime + hasBeginning: $hasBeginning + hasEnd: $hasEnd + }) { + economicEvent { + id + action {id} + inputOf {id} + provider {id} + receiver {id} + resourceQuantity { + hasNumericalValue + hasUnit {id} + } + resourceInventoriedAs { + id + name + note + primaryAccountable {id} + accountingQuantity { + hasNumericalValue + hasUnit {id} + } + onhandQuantity { + hasNumericalValue + hasUnit {id} + } + conformsTo {id} + } + hasPointInTime + hasEnd + hasBeginning + } + } +} +``` + +and the example variables: + +``` +{ + "provider": "01FZFE8E43ANRY360J1E98PJ0Z", + "receiver": "01FZFE8E43ANRY360J1E98PJ0Z", + "resourceInventoriedAs": "01FTB03K54ZF38FHEKGVHTWGY8", + "resourceQuantity": { + "hasNumericalValue": 10.0, + "hasUnit": "01FTB06BQ64MSS7XSB3QMSW83R" + }, + "hasBeginning": "2022-01-02T03:04:05Z", + "hasEnd": "2022-01-02T03:04:05Z" +} +``` diff --git a/mix.exs b/mix.exs @@ -7,7 +7,7 @@ def project() do version: "0.1.0", elixir: "~> 1.11", # erlang/otp 22-24 start_permanent: Mix.env() == :prod, - config_path: "conf/common.exs", + config_path: "conf/buildtime.exs", deps: deps(), releases: [ zenflows: [ @@ -19,12 +19,18 @@ def project() do elixirc_paths: elixirc_paths(Mix.env()), test_pattern: "*.test.exs", warn_test_pattern: "*{.test.ex,_test.ex,_test.exs}", + + # doc + name: "Zenflows", + source_url: "https://github.com/dyne/zenflows.git", + hompage_url: "https://github.com/dyne/zenflows", + docs: docs(), ] end def application() do [ - extra_applications: [:logger], + extra_applications: [:logger, :inets, :ssl], mod: {Zenflows.Application, []}, ] end @@ -42,7 +48,7 @@ defp deps() do {:plug_cowboy, "~> 2.5"}, # graphql - {:absinthe, "~> 1.6"}, + {:absinthe, "~> 1.7"}, {:absinthe_plug, "~> 1.5"}, {:jason, "~> 1.3"}, @@ -52,9 +58,30 @@ defp deps() do # static analysis {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, {:dialyxir, "~> 1.0", only: [:dev], runtime: false}, + + # doc + {:ex_doc, "~> 0.28", only: :dev, runtime: false}, ] end +defp docs() do +[ + main: "readme", + source_ref: "master", + extra_section: "DOCS", + extras: [ + "README.md", + "docs/configuration-guide.md", + "docs/vf-intro-gql-iface.md", + "docs/software-licences.md", + "docs/dependency-management.md", + "docs/style-guide.md", + "LICENSE", + ], + output: ".docs" +] +end + defp elixirc_paths(:test), do: ["src/", "test/help/"] defp elixirc_paths(_), do: ["src/"] end