Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DFC API] Import known units when creating new products #11377

Merged
merged 14 commits into from
Sep 7, 2023

Conversation

mkllnk
Copy link
Member

@mkllnk mkllnk commented Aug 10, 2023

ℹ️ This is a funded feature. Please use the Clockify project with the following name when working on this, including review and test: #9170 OFN DFC Products

What? Why?

Whenever the DFC Prototype is updated, it's an opportunity to verify our implementation and update the specs.

  • Using DFC Connector for SuppliedProduct updates.
  • Updating name and unit as well.

Then adding support for most DFC units.

What should we test?

  • Specs only.

Release notes

Changelog Category: Technical changes

The title of the pull request will be included in the release notes.

Dependencies

Documentation updates

@mkllnk mkllnk self-assigned this Aug 10, 2023
mkllnk added 10 commits August 28, 2023 17:13
I observed new data from the DFC Prototype. It now uses the DFC 1.8
ontology with the hasQuantity object.

It now also uses PUT requests for updates because PATCH is not as well
supported. Rails doesn't care though.

I couldn't observe a request for the CatalogItem yet because the
Prototype failed to send it.
Re-uses existing code and takes knowledge out of the controller.
I also updated the comments.
@mkllnk mkllnk force-pushed the dfc-update-request branch from 5b3232b to 8114430 Compare August 28, 2023 07:13
@mkllnk mkllnk changed the title Update DFC SuppliedProduct with latest version 1.8 request [DFC API] Import known units when creating new products Aug 28, 2023
@mkllnk mkllnk added the feature toggled These pull requests' changes are invisible by default and are grouped in release notes label Aug 28, 2023
@mkllnk mkllnk marked this pull request as ready for review August 28, 2023 07:28
Copy link
Member

@dacook dacook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, I just noticed that the Tonne line needs fixing, and have a query about how the unit names are set.

builder.apply(quantity, product)

expect(product.variant_unit).to eq "volume"
expect(product.variant_unit_name).to eq "liter"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realise this is testing existing code, but I noticed the US spelling and was curious to see where this comes from.

I have to admit I always find it rather confusing how all the variant unit bits fit together, but I think I've narrowed it down to find that variant_unit_name is normally set with the values here: https://github.com/openfoodfoundation/openfoodnetwork/blob/master/app/services/weights_and_measures.rb#L35

IE it looks like a litre should be an (unambiguous?) "L"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you found the source of truth! I should have looked for that. You are right about the unit naming.

@@ -78,6 +77,8 @@ def self.apply(quantity, product)
["weight", "gram", 1]
when quantity_unit.KILOGRAM
["weight", "kg", 1_000]
when quantity_unit.TONNE
["weight", "kg", 1_000_000]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be "T" (as in WeightsAndMeasures)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you are right.

And I'm just realising another issue. I chose the most accurate values for imperial measures, thinking that it can always be rounded later, but WeightsAndMeasures uses rounded values as lookup keys. Well, I guess, we can add the rounding to that class to help it recognise these measures.

@mkllnk mkllnk requested a review from dacook August 30, 2023 23:29
We still have the scale stored in two places but in our current system
that's part of a unit's "id".

If the DFC adds that value to its standard then we can use it for lookup
and don't need to repeat it.

* datafoodconsortium/taxonomies#7
@mkllnk mkllnk force-pushed the dfc-update-request branch from ff64c8c to 50f7177 Compare August 30, 2023 23:48
Copy link
Member

@dacook dacook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, and on raising the specific issues with DFC too. It's interesting to learn more about the measurements of the world!

I just have a couple of suggestions...

Comment on lines +32 to 35
28.349523125 => { 'name' => 'oz', 'system' => 'imperial' },
28.35 => { 'name' => 'oz', 'system' => 'imperial' },
453.59237 => { 'name' => 'lb', 'system' => 'imperial' },
453.6 => { 'name' => 'lb', 'system' => 'imperial' },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, so I guess this means we recognise both a) the more specific unit scale imported from DFC, and b) the less specific unit from the OFN admin interface or product importer.
It might be helpful to have a code comment to explain why there's two:

Suggested change
28.349523125 => { 'name' => 'oz', 'system' => 'imperial' },
28.35 => { 'name' => 'oz', 'system' => 'imperial' },
453.59237 => { 'name' => 'lb', 'system' => 'imperial' },
453.6 => { 'name' => 'lb', 'system' => 'imperial' },
28.349523125 => { 'name' => 'oz', 'system' => 'imperial' }, # More specific value imported from DFC
28.35 => { 'name' => 'oz', 'system' => 'imperial' },
453.59237 => { 'name' => 'lb', 'system' => 'imperial' }, # More specific value imported from DFC
453.6 => { 'name' => 'lb', 'system' => 'imperial' },

1000.0 => { 'name' => 'kL', 'system' => 'metric' }
1000.0 => { 'name' => 'kL', 'system' => 'metric' },

0.25 => { 'name' => 'cu', 'system' => 'imperial' },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you have pointed out, this is actually a metric cup, so should we not label it as such?

Suggested change
0.25 => { 'name' => 'cu', 'system' => 'imperial' },
0.25 => { 'name' => 'cu', 'system' => 'metric' },

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is tough. It's an imperial measure made to fit into the metric system. It's not included in the metric system which only uses multipliers of 10. But it's not an old imperial unit either. It's mainly used in Australia, Canada and New Zealand. It probably sits somewhere in between and belongs to neither, the imperial system or the metric system.

Although derived from the metric system, it is not an SI unit.[7]

https://en.wikipedia.org/wiki/Cup_(unit)

What do you think?

The other question is: does it matter? Now I came across the UnitPrice service which seems to assume that a variant's unit_value is always expressed in grams, litres, pounds or items. I actually find that class super confusing and I'm not sure it's covering all the cases or why we have to convert this way. When a product is created, the user chooses the unit and that should be enough, shouldn't it?

According to that logic, it does look safer to assign the metric system to a cup so that it doesn't assume it to be a weight. It looks like there's some bigger picture clean-up to do.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm interesting. It's still commonly labelled "metric cup" which I would consider close enough.

But does it matter? No, in fact I would suggest we don't bother supporting this unit at all. We've clearly come this far without it.
Until it's clarified, or as you suggest we avoid scaling it and just treat it as a label, we probably shouldn't implement it.

Another thought: if "cup" is just a label that doesn't have a standard meaning, then why don't we import it as an items label? Could this work?

    when quantity_unit.CUP
      # Interpreted as a label, because this is not an internationally measurable unit.
      # https://github.com/datafoodconsortium/taxonomies/issues/8
      ["items", "cup", 1]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But does it matter? No, in fact I would suggest we don't bother supporting this unit at all.

Of course, thank you for thinking outside the cup and identifying this issue clearly as storm in a cup.

I also like your suggestion of importing the label. But there are a lot more DFC measures with a label we just import as generic "items". I would like to change that logic in general to use a label for all "items".

mkllnk added 2 commits August 31, 2023 16:11
The DFC doesn't actually specify which cup it means. I don't expect
anyone providing "cup" as unit to measure their produce and expect it to
calculate as a regular volume. It can just be seen as items.
@mkllnk mkllnk requested a review from dacook August 31, 2023 06:31
Copy link
Member

@dacook dacook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, even better! 💯

Copy link
Member

@dacook dacook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, there's a spec to fix :(

     NoMethodError:
       undefined method `semanticId' for "dfc-m:Gram":String
     
             label = unit.semanticId.split("#").last || "items"
                         ^^^^^^^^^^^
     # ./engines/dfc_provider/app/services/quantitative_value_builder.rb:113:in `map_unit'

@mkllnk mkllnk requested a review from dacook August 31, 2023 07:25
@mkllnk mkllnk added api changes These pull requests change the API and can break integrations and removed feature toggled These pull requests' changes are invisible by default and are grouped in release notes labels Sep 7, 2023
@drummer83
Copy link
Contributor

Hi @mkllnk,
by

What should we test?

  • Specs only.

do you mean there is no manual testing needed?
Or is there anything Filipe should do about the spec files?

@mkllnk
Copy link
Member Author

mkllnk commented Sep 7, 2023

@drummer83

What should we test?

This doesn't need testing. There's actually no other DFC software to test this with. So I'll merge this straight away.

@mkllnk mkllnk merged commit 1991970 into openfoodfoundation:master Sep 7, 2023
@mkllnk mkllnk deleted the dfc-update-request branch September 7, 2023 23:05
@RachL
Copy link
Contributor

RachL commented Sep 8, 2023

@mkllnk actually we can test with demo.socleo.org on the other end. I will play with it a bit next week :)

Also I think we should have soon both UK and FR staging connected with the prototype if I understood correctly ping @RaggedStaff @lin-d-hop

@mkllnk
Copy link
Member Author

mkllnk commented Sep 11, 2023

@RachL

Also I think we should have soon both UK and FR staging connected with the prototype

Yes, that's deployed. We could actually try to transfer products form one platform to another. I haven't tested that yet. Would be interesting what you find.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api changes These pull requests change the API and can break integrations feedback-needed
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

[DFC API] Import known units when creating new products
5 participants