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

[16.0][OU-ADD] delivery: migration #4112

Closed
wants to merge 2 commits into from

Conversation

carmenbianca
Copy link
Member

@carmenbianca carmenbianca commented Aug 31, 2023

So this is a work-in-progress. I'm writing the challenges involved before having a go at tackling this problem. I need to clearly write the problem before I can start, and I figure I might as well write the thoughts publicly.

For delivery methods, zip_from and zip_to were changed to 'zip prefixes'.

The old method worked like this. If you wanted a delivery method to only apply to destinations in lovely Brussels, you would set zip_from to '1000' and zip_to to '1200'. All numbers between those two values cover all possible postal codes for the Brussels Capital Region. Each (entire) municipality has its own concrete number.

However, the world is scarcely always so simple. To take just one example, in Ireland, they use Eircode. So if you wanted to restrict a delivery method to Dublin, you would need to match all the following prefixes:

  • D01
  • D02
  • D03
  • D04
  • D05
  • D06
  • D6W (the notable outlier)
  • D07
  • D08
  • D09
  • D10
  • and so on until
  • D24

An example Eircode postal code looks like 'D04 1234', where 'D04' maps to Dublin 4 (a part of Dublin), and '1234' is a unique identifier for any address in that part of Dublin. In fact, a different apartment number in the same building may have a totally different unique identifier. The unique identifier can use any alphanumeric character (except 'O', and maybe some others, but it's not extremely clear to me, and it doesn't matter very much for this example).

In the case of Dublin, I'm not sure how the Odoo 15 system ever worked. zip_from = D01 0000, zip_to = D6W ZZZZ? Or D24 ZZZZ? Or D99 ZZZZ (which doesn't exist)? Does Odoo handle letter sorting like Python?

The new Odoo 16 system is relatively simple. Instead of defining a single range, you can define any number of 'prefixes'. For Brussels, this means that you can use ['1'] (no other postal code in Belgium uses >1200,<2000). For Dublin, you can use ['D'] (Dublin is the only city in Ireland whose postal code begins with D). However, if you wanted to, you could also define ['10', '11', '12'] for Brussels, and the big list of Dublin postal codes from the above list.

The new system has one more trick up its sleeve: you can use regexes!


Enough prelude. Let's solve this problem. We need to translate the old system to the new system in a way that accounts for all possible postal code systems. Or at least: postal code systems that are hierarchical when read from left to right (or sequentially), elsewise prefixes and ranges make no sense to begin with.

I just don't really know how. I happen to know that Brussels (zip_from = 1000, zip_to = 1200) maps to prefixes ['1'] or ['10', '11', '12'], but I couldn't confidently say that without my pre-existing knowledge. In an alternate universe, there may be another Belgian municipality outside of Brussels that uses postal code '1201'. So I guess you'd need to write a regex that maps to any alphanumeric value between '1000' and '1200' (incl)? That sounds doable, even if it's a minor exercise in masochism, but it gets even more complicated with esoteric systems like Eircode. And what if there exists some postal code system that uses non-Latin characters that aren't easily included in the regex?

I'll have another look at this later.

@legalsylvain
Copy link
Contributor

legalsylvain commented Aug 31, 2023

/ocabot migration delivery

Depends on :

@OCA-git-bot OCA-git-bot added this to the 16.0 milestone Aug 31, 2023
@carmenbianca carmenbianca changed the title [OU-ADD] delivery [16.0][OU-ADD] delivery Aug 31, 2023
@carmenbianca carmenbianca changed the title [16.0][OU-ADD] delivery [16.0][OU-ADD] delivery: migration Sep 1, 2023
@dreispt
Copy link
Member

dreispt commented Sep 4, 2023

Bianca, I'm not familiar with the Eire postal system, but I found before the problem of different zip code ranges.
I had to create different "duplicate" delivery codes for each straight range of zip code.

For example, you could have:

  • Free Delivery Brussels 1: from D01 0000 to D24 ZZZZ
  • Free Delivery Brussels 2: from D6W 0000 to D6W ZZZZ

In case it goes from D01 to D99, then no need for a second zone, as D6W is included in that range (just after D5Z ZZZZ and before D70 000).

@carmenbianca
Copy link
Member Author

Continuing work on this at OCA Days sprint

@pedrobaeza
Copy link
Member

Let me know if you want to discuss something.

@carmenbianca
Copy link
Member Author

Possible solutions:

  1. Abuse the ability to use regexes. Create a monstrous regex that covers the alphanumeric range from zip_from to zip_to. The problem is that this regex would be quite monstrous indeed. This link gives some examples on how to do this.

    Specifically, to cover the range 000..255, the regex is ^([01][0-9][0-9]|2[0-4][0-9]|25[0-5])$. You can imagine this becoming a lot harder for longer numbers, and a lot harder still if you also include alphabetic letters. And frankly, I don't know if there's an easy way to generate such a regex. Specialist software exists, so it's evidently possible, but I don't know how easy it is.

  2. Create a prefix entry for every possible value. For the range 1000-1200 in Brussels, that would mean creating 201 delivery.zip.prefix records: 1000, 1001, 1002, … 1199, 1200. This works, but is bad and stupid. The amount of prefixes generated balloons if we also create prefixes for alphabetic letters.

  3. Make a best-effort algorithm. A correct set of prefixes for the 1000-1200 Brussels range that doesn't make any assumptions about the real world is [10, 11, 1200]. But this gets tricky for, say, the Netherlands. The range '8000 AA → 9999 ZZ' covers the entire north of the country. You would expect [8, 9] as a set of prefixes here. But this can't be true, because '8000 11' and '9ZZZ ZZ' could exist (they don't, but we must make no assumptions, and they would've previously not been covered by the range). So you'd end up with something like: [8000 AA, 8000 AB, 8000 AC, …, 8000 B, …, 8000 Z, 81, 82, …, 90, 91, …, 98, … and now I'm not sure anymore].

    Not ideal. And honestly, probably not very trivial either.

I don't know how Odoo EE solves this problem. I'm inclined to say that we just log a warning with an explanation to the user that they should fix this manually. It's a rubbish solution, but the other ones aren't great either.

Do you have thoughts @pedrobaeza ?

@pedrobaeza
Copy link
Member

pedrobaeza commented Nov 7, 2023

Hi, Carmen, welcome to the wild OpenUpgrade, where hard decisions (or lots of work) have to be made!

OpenUpgrade should preserve at maximum the information of the previous version, so we shouldn't opt for the option on not doing anything.

I don't get why Odoo has gone to this ugly format. It's OK to admit regexes, but they shouldn't limit the possibilities to only that. Keep the intervals on this new model! But we are there at least for this version, so we have to tackle it.

I think the only viable option to go is the 1st, and replicate the tooling for creating the regexp for the interval. The second one will provoke a lot of noise.

Signed-off-by: Carmen Bianca BAKKER <[email protected]>
Signed-off-by: Carmen Bianca BAKKER <[email protected]>
@carmenbianca
Copy link
Member Author

I do not know why the CI is broken on some stock thing. It appears entirely unrelated, but the 16.0 branch is passing fine.

@pedrobaeza
Copy link
Member

That's because delivery depends on stock, and such module doesn't have still the scripts, and there's a breaking change that requires such scripts. That's why this PR gets the label "Blocked by dependency".

@carmenbianca
Copy link
Member Author

Ah. That's a little unfortunate. Thank you @pedrobaeza

prefixes = range_to_prefixes(method.zip_from, method.zip_to)
except Exception as error:
_logger.error(
f"Failed to convert the zip range '{method.zip_from} --"

Choose a reason for hiding this comment

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

hello, , If this code is performed from odoo 16.0 environment, make a AttributeError: 'delivery.carrier' object has no attribute 'zip_from', because zip_from is no longer in 16.0

Copy link
Member Author

Choose a reason for hiding this comment

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

ah, I may need to directly query the database for these values.

Choose a reason for hiding this comment

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

@carmenbianca any update on this?

Copy link
Contributor

@marielejeune marielejeune left a comment

Choose a reason for hiding this comment

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

Thanks for this huge reflexion and work!
One more comment. Btw, do you plan on fixing the script or do you need some help?
Thanks


@openupgrade.migrate()
def migrate(env, version):
delivery_methods = env["delivery.carrier"].search([])
Copy link
Contributor

Choose a reason for hiding this comment

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

One may restrict to delivery carriers having values in zip_from and / or zip_to.
(As @dansanti mentioned it, you should query this info in DB)

@pedrobaeza
Copy link
Member

Superseded and completed by #4370

Thanks Carmen from the excellent work done so far.

@pedrobaeza pedrobaeza closed this Apr 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants