I've occasionally suggested this, but never filed this feature request in an official location.

The address system in Ubercart 2.x stores addresses within orders and only within orders. uc_addresses extends this:

  • Customer can create one or more addresses. These are stored independently of any order.
  • The user can view, add, edit or delete these addresses.
  • There is one default address and it cannot be deleted.
  • The user can change which address is the default.
  • Every address can have an optional nickname.
  • During checkout, the default address can be used to automatically fill in the shipping and/or billing addresses.
  • The customer can select another address for billing or shipping by choosing the address by its nickname or by a default identifier used if there is no nickname.
  • New shipping and/or billing addresses can be automatically added to the customer's list.
  • Customers can be required to enter an address during registration.

The problem is that there is no way for uc_addresses to hook into the order address system so that it can provide addresses from its database. The two systems exist independently. Usually, it's the administrator who sees the inconsistencies, since uc_addresses doesn't operator on the order forms.

Either the features of uc_addresses should become part of Ubercart 3.0 or Ubercart 3.0 should provide the hooks necessary for the address system to be extended in a consistent fashion.

Another note: there is a module called Addresses that provides API-level support for addresses. It seems that Ubercart should leverage this module rather than spend time maintaining its own code support.

It's possible that some or all of this is already part of Ubercart 3.0, but I haven't seen anything except some references to a "UcAddresses" class.

CommentFileSizeAuthor
#5 Customer Addresses for Ubercart 3.pdf54.4 KBfreixas
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Andy_Lowe’s picture

Agreed. Currently Lyle/Mahitha are working to redesign how addresses are stored in Ubercart. In 1.x and 2.x, Ryan chose to store the addresses as a bunch of columns in the order table. This was a bad idea. For 3.x we are fixing this so that addresses are stored as fields referencing the order / user. Addresses as fields may limit the back end code we can use from uc_addresses, but we can still use most of the logic and ui from uc_addresses.

As for the Addresses module, we have not looked into it in detail, but the reviews here http://drupalmodules.com/module/addresses scared me a little. I agree with you in theory, but I'm not sure if the Addresses module is the right choice. Someone on the rules integration issue pointed out the Address Field module as well.

I suggest we take the ui / logic of the uc_addresses module and wrap it around supporting the Addresses or Address Field module and integrate it into Ubercart 3.x.

Freixas, do you have the time to push this forward? If you come up with a workable solution before 3.x goes into beta, It's certain to get in.
Cheers,
Andy

freixas’s picture

Sigh...the things that could be solved with some free time.

First, let me address the Addresses module (pun intended). Yeah, I saw the bad reviews, including one from April, 2010. But I also see that the usage stats count 3,116 installations. uc_addresses has 1,315. In the end, someone has to go study the module, see if it really adds any value and see if it works, possibly even help fix the problems.
Before using the Addresses module, I would expect that the Ubercart team would

  • Want to understand what it brings to the table
  • See if what it brings adds value to Ubercart
  • Ensure that Addresses won't simply add complexity and constrain Ubercart
  • Verify that the code is sound—possibly, even help fix any bugs that might block Ubercart from using it
  • Assess support for the module—you don't want Ubercart dependent on a module that is poorly maintained (ubercart has 22,929 reported installations)

If time is tight and resources aren't available, integrating with Addresses is not going to happen since even evaluating the package will take a lot of time.

Next, let's look at absorbing uc_addresses. You mention that "addresses as entities may limit the back end code we can use from uc_addresses". Actually, while I'm not exactly sure what you mean by entities, uc_addresses maintains a table of addresses and deals with addresses the same as the user table deals with users, so perhaps there is less of a problem than you might think. The uc_addresses table had to be compatible with the address fields used by orders, so that will further reduce any incompatibilities. The only extra is a nickname added to the address record and a separate table that identifies a default address (it associates one user with one address).

Next, you "suggest we take the ui / logic of the uc_addresses module and wrap it around supporting the Addresses or Address Field module and integrate it into Ubercart 3.x." This sounds as though you would like uc_addresses to pioneer the way into using the Addresses (or Address Field) module and, if successful, get folded into Ubercart 3.x. This seems like a problem because what I would like to see is all of Ubercart using the same address system. The problems with uc_addresses today arise from having two separate address systems and I don't see any point in perpetuating this. It would make more sense to have uc_addresses use whatever address system you've created for Ubercart 3.x.

What would this entail? uc_addresses associates addresses with users and Ubercart 3 associates it with users/orders. If uc_addresses is not a core module, then the integration would be less than ideal. If it were a core module, then we could allow addresses where the order_id is 0 to represent user-owned addresses. Otherwise, we're back to the user addresses and the order addresses not knowing anything about one another.

By "core" module, I mean that other core modules would know that uc_addresses exists and would understand how uc_addresses will operate on the addresses table. uc_addresses could actually be an optional module.

The other advantage of uc_addresses as a core module is that, when an order is saved, if uc_addresses is enabled and if the options to save the shipping and/or billing addresses as user addresses are enabled, the order system could save a user-associated address (order_id 0) along with the user/order associated address (why both? because the order could be deleted or the user address could be deleted). A user address is saved only if it doesn't already exist. The real trick is to make sure the address is saved only when the user is done modifying the order.

One enhancement that would be useful would be to add an option to let the customer decide if he/she wants to save an address. Right now, it's all or none. At the time I wrote the module (my first), I had no idea how to do this in the _alter_form function.

I don't think admin created/modified orders should add addresses to the customer's profile.

The checkout code could take the initiative to pre-fill the billing and/or shipping fields (again, if uc_addresses is enabled and the options to do that are enabled) from the core addresses table. This would take uc_addresses completely out of the business of messing with orders and checkout and just leave it to display and edit the addresses in the user's profile (and optionally during registration). uc_addresses would also maintain the default address and nickname.

Finally, any uc_addresses for Ubercart 3.x will need an upgrade path.

Do I have time to push this forward and to do this before Ubercart 3.x reaches beta? I am outside the loop on anything going on with either Drupal 7 or Ubercart 3 and I have no idea when 3.x might reach beta. uc_addresses is near the bottom of my priority list and I mostly maintain it because no one else has stepped up to the plate. I would hate to see it omitted from core Ubercart, though.

It would help if someone could tell me what changes are needed to convert a module to Drupal 7/Ubercart 3. Then I would need to know if the Ubercart team would consider making the code part of the core and would be willing to make the changes to the addresses table and to the checkout and order modules. That would leave me with just the profile editing to update and the upgrade path.

In uc_product_keys I use a design pattern where I read in all records using SELECT * and write out all records using drupal_write_record(). This allows other modules to extend the product keys database table so that extra fields can be added without requiring an extra table and an extra database fetch or JOIN. If you are using the same pattern in Ubercart 3, then some of the extra fields I mentioned could be optimized to exist only if uc_addresses is enabled.

Sorry about the long post, but I think we need to discuss this a bit before deciding what action to take.

Andy_Lowe’s picture

No need to apologize for the long post. It was a good read. I'll try to organize this response from high to low level without overlooking anything.

I apologize for not making it more clear. I'm 100% on board with making uc_addresses a core (or at least required) Ubercart module and the standard/default method for handling addresses in Ubercart 3.x including orders, shipping, product default shipping locations, and any other place I'm overlooking. If that is all we achieve, that is still a big step in the right direction.

However, while we are at it, I think we should look at how addresses are stored by uc_addresses. I think uc_addresses handles the logic and the ui for addresses well, but I think we may be able to improve on the way the addresses are stored which is what I was talking about when I said "entities". Unfortunately, what I meant to say was fields. I've edited #1 to correct my mistake. I apologize for confusing you. Fields are the Drupal 7 version of cck which can be linked to any Drupal 7 "entity" including users, nodes, and orders. This is why I look favorably on the Address Field module. I envision uc_addresses handling the user profile, configuration option, etc... but storing and retrieving addresses as fields as defined by the Address Fields module, or maybe as defined by the Addresses module. I created this issue #861126: Addresses in Drupal 7 in the addresses issue queue to get an idea of their plans for Drupal 7.

The time line for beta is not solid, but it is safe to say one month at the earliest and three at the latest.

The other advantage of uc_addresses as a core module is that, when an order is saved, if uc_addresses is enabled and if the options to save the shipping and/or billing addresses as user addresses are enabled, the order system could save a user-associated address (order_id 0) along with the user/order associated address (why both? because the order could be deleted or the user address could be deleted). A user address is saved only if it doesn't already exist. The real trick is to make sure the address is saved only when the user is done modifying the order.

Agreed. Maybe the solution to the trick is to only create the user default address on saving the order after confirmation.

One enhancement that would be useful would be to add an option to let the customer decide if he/she wants to save an address. Right now, it's all or none. At the time I wrote the module (my first), I had no idea how to do this in the _alter_form function.

I don't think admin created/modified orders should add addresses to the customer's profile.

I see the option to save as nice, but not critical. I think the admin create should add addresses. The user can always delete it if they don't want it for some reason. Even better would be a site wide configuration option (add or not).

The checkout code could take the initiative to pre-fill the billing and/or shipping fields (again, if uc_addresses is enabled and the options to do that are enabled) from the core addresses table. This would take uc_addresses completely out of the business of messing with orders and checkout and just leave it to display and edit the addresses in the user's profile (and optionally during registration). uc_addresses would also maintain the default address and nickname.

Finally, any uc_addresses for Ubercart 3.x will need an upgrade path.

Agreed.

The requirements for upgrading for Durpal 7 are listed here: http://drupal.org/node/224333. More importantly, the coder module will do much of the heavy lifting for you. Lyle wrote a set of rules for the coder module specific for Ubercart 3.x as well. You should be able to install Drupal 7, coder, Ubercart 3.x and the Drupal 6.x version of uc_addresses, go to the coder module pages, click a few buttons, and have a 90% (ymmv) complete port.

If you do the port and the upgrade path, we will start on our end with the checkout and other modules as you suggested. Hopefully we can meet in the middle :) That leaves the potential use of the addresses or address field module still undefined and unassigned, but I feel we're definitely making progress regardless

I'm sure I've left something out, but that's all I can come up with for now.
Thanks for writing a great module, and for helping to make Ubercart better.
Cheers,
Andy

freixas’s picture

Thanks, Andy. I'll gets started and see how easy or hard this will be.

On the topic of admin orders automatically adding a shipping and/or billing address to the user's profile, I can see the advantages and disadvantages. A few customers won't want anyone messing with their carefully prepared set of addresses. On the other hand, most customers may not care if a legitimate address is added to their list of addresses. They might wonder where the address came from, but as long as its associated with a legitimate order (one that they are aware of), they can probably figure it out. Let me think about this one.

As for fields and entities, let me get the code installed and see what's going on in the order system. Your comments may make more sense then. I'll post more info after I get the code.

freixas’s picture

Hi, I've attached a proposal for integrating uc_addresses into Ubercart 3 core (optional).

The proposal includes some changes to the current uc_addresses module, including renaming it to "Ubercart Address Book" and limiting it to just managing a customer address book and providing an API for other modules (such as uc_cart and uc_order) to use.

Andy, I installed D7 and UC3 and the order table looks as though it stores addresses as it always has. The decision to use the Addresses or Address Field modules is something I don't feel comfortable making and is one which should apply to all addresses used by UC3. Therefore, my proposal does not include anything new in that respect. Should the UC3 team decide to change how addresses are supported, then the Address Book module will need to change to match.

It does not make sense for me to check in the D7/UC3 version of uc_addresses (now uc_address_book) into the uc_addresses project. Could you provide me with the appropriate info so that I can add the new module to UC3?

MegaChriz’s picture

If you manage to introduce a total new address system for Ubercart 3.x, then please provide an easy way to add additional address fields. This may be via a GUI or via hooks. Currently in Ubercart 2, it's very hard to get this done. I'm trying, but at this moment I haven't found a full solution yet without hacking core.
See also http://drupal.org/node/337686

freixas’s picture

I would suggest you enter a separate issue for this (if there isn't one already). This issue is about adding a fully-integrated address book to Ubercart 3 (uc_addresses doesn't work on admin-created orders, for example, so it is not fully integrated).

Ubercart Address Book will (and should) use whatever address system is in Ubercart 3. The decision for how to define and store addresses should come from the core Ubercart team. One of the reasons for renaming uc_addresses is that it implies that it controls all Ubercart addresses. It doesn't.

longwave’s picture

Status: Active » Postponed (maintainer needs more info)

So, this didn't happen, and now we're at rc2 we're unlikely to rip out the entire address system and replace it. Is there anything we can still do on this front, or should this be postponed again until Ubercart 4? (at which point perhaps we should look at Addressfield module)

MegaChriz’s picture

Status: Postponed (maintainer needs more info) » Active

I have made a start with writing a Drupal 7 version of Ubercart Addresses. This module will (still) make use of the standard address fields that Ubercart uses. I'm not far enough to publish a development version as a lot of it is still "Drupal 6" code (e.g. it implements hooks of Ubercart 6.x-2.x that have been renamed in Ubercart 7.x-3.x). If I run into any issues I will let you know, but in big lines Ubercart Addresses 7.x-1.x will be a straight port of Ubercart Addresses 6.x-2.x, so I do not expect big problems. If you want to know more about how the address book technically will work, you can read the documentation or ask me.

So, probably this should be postponed again until Ubercart 4. The Address field module could be an option for address functionality the next major version of Ubercart, but I've not studied this module in detail yet. Does this module provide address book functionality?

I set the issue back to "active", but it may be set to "postponed" if you decide to look again to this when Ubercart 4 will be developed.

longwave’s picture

Title: Incorporate uc_addresses into Ubercart 3 or allow address system to be extended » Incorporate uc_addresses into Ubercart or allow address system to be extended
Status: Active » Postponed

As Ubercart Addresses is likely to be released separately for Ubercart 3, and we're nearing a release of 7.x-3.0, this isn't likely to happen until the next version of Ubercart.

j0rd’s picture

After some discussion in another thread about addresses in Ubercart, I'd like to show my support for Addressfield in a future version on Ubercart on D7. I've used it in Drupal Commerce and it works well enough.

Addressfield, while it needs some minor extensions to still provide the Address awesomeness which is currently found in Ubercart, wouldn't be hard to do. This would also help normalize the database a little bit more, as address information would be stored in it's own table, instead of all over the place in each node.

Additionally, addressfield is getting good integration geofield, which has integration with geocoding (address lookups to latlong) and OpenLayers (mapping functionality) all of which would open up some interesting possibilities.

There's also the Commerce Address book module which provides the Ubercart like dropdown for pre-entered address when checking out. In my opinion while this module provides a good start, it needs to be re-factored http://drupal.org/project/commerce_addressbook

muka’s picture

Hi,

I've recently had headaches in 3.x to handle correctly some addons field in addresses both for store owner and client side.
In my country (Italy) is require to have a VAT code exposed on the site and in invoices too.
Invoice to non-enterpise (Vat code owner) needs to have at least a tax code.
For check payment is good to expose IBAN (interbankary address number)
Probably many other ue country may had similar issues.

I've partially solved overriding a bunch of uc hook (https://github.com/muka/uc_address_items) but is nor DRY nor maintainable nor configurable. (with large override of panes for cart, order, checkout, store settings, payment settings and types)

What about use entity API for addresses to allow handling the address data for both seller/client ?
(The profile2 module is a good starting point)

Some goodies to think about it:
- It would use core Drupal API and hooks
- uc_address_format($arg, ..., $argN) is not as good as it could be; uc_address_format( $entity ) could contain all the required information eg. owner (uid), address type ( mail, bill, send present to ), view modes became a gui "formatter"
- The store settings could take all required data from a selected user user_id / address_id (this could then be used to build a "marketplace" with less efforts)
- entity API give for free tokens, fields, unified GUI, views goodies.
- view modes can be customized to be rendered on invoice, checkout review, seller information

Hope this help.
Luca

MegaChriz’s picture

@muka
You are in luck my friend, Ubercart Addresses 7.x-1.x (and 6.x-2.x) has an API for adding extra address fields in Ubercart. Because Ubercart Addresses 7.x-1.x is a port of 6.x-2.x, it makes less use of the Drupal 7 API as could be. Integration with field API, entity API, view modes is not (yet) implemented, but Ubercart Addresses has it's own way of formatting addresses: in Ubercart Addresses addresses are formatted by using tokens:

[uc_addresses:company]
[uc_addresses:first_name] [uc_addresses:last_name]
[uc_addresses:street1]
[uc_addresses:street2]
[uc_addresses:city], [uc_addresses:zone:zone_code] [uc_addresses:postal_code]
[uc_addresses:country:country_name_if]
TR’s picture

TR’s picture

TR’s picture

Version: 7.x-3.x-dev » 8.x-4.x-dev
Component: 3rd party integration » Code
Status: Postponed » Active

This is a priority for 8.x-4.x, but while the existing uc_addresses module provides the needed functionality, the code requires an extreme re-write for D8. It's probably easier at this point to start from scratch.

MegaChriz’s picture

Agreed. The 6.x-2.x and 7.x-1.x version of the Ubercart Addresses were written at a time before I learned about the Entity API. As I say in #13, it makes less use of the Drupal standard way of working with entities (no field API, no view modes). I wouldn't recommend to do a straight port of the module because of that. Nevertheless, we could still take ideas from it. I always liked the token based address formatting, to take an example.

An alternative could be to include something like the Addressfield module, although I have experienced that adding extra address fields with Views support for that module isn't easy: you can add extra fields via the API, but you have to take care for the saving yourself. I have found no easy way to add extra database columns to a field API field, which makes it harder to use the extra fields in Views. However, the D8 version of this module will be an entire other approach. From #2136263-7: D8 port:

Our D8 addressing plans are at https://drupalcommerce.org/blog/16864/commerce-2x-stories-addressing
The library itself is in good shape and Drupal integration is in progress.

This entirely new approach will power the 2.x branch, so I would say there is no need for a 1.x port.

TR’s picture

Addressfield is not an option for many reasons, and Ubercart D8 already supports most of the stuff talked about in that blog post. The key thing we need is to make addresses versioned, fieldable entities, with orders referencing those entities for billing and shipping, plus support so users can manage their own addresses. These entities should be used everywhere we now carry around address data, for example product ship-from addresses, stock location, store location, etc, not just for customer shipping and billing.

I don't see this as especially hard, it will just be complicated to disentangle all the old stuff that does addresses and replace it with the new entity, since there never was any functional abstraction for the old way to begin with. I think the way to start would be to create a small module within Ubercart (call it uc_address - we're sticking with the singular in Ubercart core ...) that just does addresses and exposes an address API as a service - once that is created and has tests we can replace the old code piece-by-piece throughout the Ubercart code base. This was the strategy I took when abstracting out the country/state/province handling code, which now resides in uc_country. We also might want to combine uc_country and uc_address at some point, but I see that as a secondary step.

But yes, the features of uc_addresses are good and I want to keep them, but the implementation doesn't seem usable because when it was developed in D6 it basically had to invent and entity-like system, and so it is loaded with a huge amount of code which now can be replaced by Drupal core equivalents. I did try a straight port of the D7 version to D8, but after working on it for a while and getting a good picture of what was going on, I realized it would be a lot quicker and easier to start from scratch and aim at the same feature set.