openfoodfoundation / openfoodnetwork

Connect suppliers, distributors and consumers to trade local produce.
https://www.openfoodnetwork.org
GNU Affero General Public License v3.0
1.11k stars 720 forks source link

User balance functionality #297

Closed lin-d-hop closed 9 years ago

lin-d-hop commented 9 years ago

Integral to the UK food hub usage is the ability for the user and the reports to access their balance, as a function of money paid and order totals.

The /accounts page lists all orders for a user, so adding a balance to this page solves the user side.

I'd rather not store the balance in a DB table, but create it on the fly whenever needed.

This will feed into a number of the reporting issues under the UK label including #266 #267.

lin-d-hop commented 9 years ago

@RohanM @oeoeaio In terms of the best way to do this, does it make sense to add a function to users_controller_decorator.rb that returns a user balance? Does it make sense for the balance to be defined as sum of user's order.total minus payments with appropriate state?

Would be good just to know if I'm on the right track. Maybe I'm way off, in which case maybe we can chat next week Weds am/pm or when you are free?

Matt-Yorkley commented 9 years ago

We'll need to be able to add user credit as well though, sometimes for returns/refunds and sometimes when people pay to put credit into their account. How will that fit in to generating the balance on the fly from order totals? Customers will need to be able to make payments based on credit as well, right?

Matt-Yorkley commented 9 years ago

I know you can currently add "adjustments" to orders to essentially credit or debit a customer based on a specific order (to do refunds or partial payments for example), but can we add an option to insert a credit or debit payment as a sort of blank order with no products but labelled "debit" or "credit" and with a description? That would work well with generating balances on the fly from order totals and also for listing orders/payments for the user...

Also the balance will need to be per user but potentially associated with multiple enterprises, so balance will have to be displayed per enterprise for each user. If the orders were broken down into lists for each enterprise on the /account page you could display a balance for each one..

oeoeaio commented 9 years ago

This has been interesting reading, as it has highlighted for me the fact that there are really two different classes of "account balance" that have been discussed as though they are the same thing.

The first is this idea of a summary of the net position of the customers account, as Lynne says, is a function of the cost of the orders the customer has placed and the payments they have made against those orders.

The second is the quite closely related, but I think separate idea of having a reserve of funds stored in the system, which is built up by a combination of payments that the user makes (without reference to any order), and of refunds awarded by enterprises, and which may be depleted by paying for orders, or I suppose potentially other as yet undeveloped pay-per-use aspects of the system.

The first is clearly scoped to a particular enterprise, in that a deficit at one shop should not be apparent at another.

The second however could quite easily be global, so a customer's funds could be used to pay for orders at any shop in the system.

I think we should try to recognise these two ideas as distinct features that should probably be built separately. I feel like Lynne's proposal is aligning more with the first idea than the second?

If/when we do decide to tackle the second feature, I would tend to suggest that it be set up as an entirely separate concern to the placement of orders and associated payments, ie. that it have it's own set of models, views and controllers for accepting and making payments, checking balances, etc.

oeoeaio commented 9 years ago

My two cents:

My main concern with this proposal as it stands is that it may start to get a bit messy when payments are not automatically captured in the system. For example, when Cash/EFT payment methods are used to complete an order, it then becomes the responsibility of the enterprise owner to maintain the balance of the customer's account, by ensuring that they capture the payment manually when they receive it.

Not really sure of the best way around that...

Matt-Yorkley commented 9 years ago

Actually, looking at the adjustments functionality on orders, adding an "adjustment" (for say a partial payment of the order total) to an order modifies the order total itself, whereas the order total needs to be kept intact in terms of record keeping. So an adjustment to record a partial payment of £5 would make the order itself display as £5 less than it actually was as opposed to showing the total and recording that £5 has been payed...

*Edit: just realised you can do partial payments with the payments tab in an order by setting multiple payments. The remaining balance due for the order isn't displayed though.

Matt-Yorkley commented 9 years ago

@oeoeaio I think the credit/debit functionality I was talking about would still be scoped to individual enterprises. So for instance, if a food hub gave credit to a customer they wouldn't want them to be able to spend it at another hub. This might be as a refund of some kind, or at our hub people can add credit to their account by making a payment in advance that gets added on to their account balance which they can spend later.

It's still within the idea of a net balance between a customer and an enterprise, but with the addition of credits and debits that are not necessarily linked to specific orders. Could it be done using the payments table but using entries with order_id = nil?

lin-d-hop commented 9 years ago

Good points @oeoeaio pertaining to the two different kinds of balances.

So for StroudCo migration most important is an individual hub being able to track ins and outs per customer. This might not be relevant to all hubs (ie those that manage accounts fully outside OFN and take eftpos payments etc) but is functionality that StroudCo hubs need.

In the context of user balances, it would be a great thing to have for StroudCo but opens up a whole world of pain when confused customers want to know why their account is in the red despite having paid for all orders. It might be useful for a customer to be able to find out their account history for each hub they have purchased from, along with a balance. But that balance isn't a universal balance, and can't just be spent elsewhere.

Essentially OFN is not a food business itself, so probably should not be handling the keeping of debit/credit balances itself. This is something that hubs/producers might find necessary to a degree (ie @Matt-Yorkleys example of paying £18 for a £20 order or vice versa). In my mind the idea of global credit is really only useful in the context of vouchers, gift certificates and offers (ie sign up and get a voucher to spend at any producer).

oeoeaio commented 9 years ago

@Matt-Yorkley Hm, the idea of manually maintaining your balance at several different hubs (all of which may accept different payment methods) doesn't sound all that fun to me...

In relation to the scoping, I am just wondering about this: why does the fact that a user's balance is in credit (ie. was overcharged for something) necessarily entitle the enterprise to claim that credit for their store only?

That is what power companies used to do here (before smart meters): they sometimes didn't actually read your meter and instead charged you some guesstimate of your usage for the quarter which may have been far in excess of what was actually used. Once the bill was payed and it was discovered that the guesstimate was way off they would only offer a credit, rather than a refund. I was once in the situation where I was more than a hundred dollars in credit when I was about to move house, and just had to forfeit that credit because there was no way of claiming it back, all as a result of my power retailer not sending someone to actually check my meter.

I understand that this practice of businesses being allowed to "capture" the customer by issuing store credit is widespread and broadly accepted, but is it one that we want to facilitate/encourage?

At the same time, the more I think about it, the more I don't like the sound of a "centralised" account balance. Dang, we need a way of limiting both the power held by the owners of the OFN instance AND that of individual enterprises...

I am not necessarily advocating for this, just letting things fall out of my brain: What if we had both a centralised balance, and a per enterprise balance? So that it was up to the user who was responsible for holding onto their credit? Funds could be added to the OFN in a centralised and standardised way, and we could have a nice interface for distributing funds from the central balance outwards (one-way only) to individual enterprises, which would be cleaner than making separate payments into several different enterprises using different payment methods. When placing an order, the user would have the option of drawing down from either their central balance, or from their store credit. Users could set preferences about where their credit went in the event of a refund. Too messy/confusing?

oeoeaio commented 9 years ago

@lin-d-hop Can you explain how you envision the situation occurring where "their account is in the red despite having paid for all orders"? I didn't quite follow I'm sorry.

Point taken about OFN not being a food business, just wanting to explore all possibilities for making customer and enterprise user experience as pleasant as can be!

In terms of the two sets of features, I'd like to make it clear that I am seeing them as being completely distinct from one another. ie. it would be entirely possible for a customer to have a net position of say negative $30 at a particular hub, but simultaneously have an account balance (global or not is irrelevant) of say positive $100, which could be used to pay off their debt if need be. Am I making any sense? haha.

lin-d-hop commented 9 years ago

@oeoeaio "their account is in the red despite having paid for all orders" -> i was refering to your example: 'For example, when Cash/EFT payment methods are used to complete an order, it then becomes the responsibility of the enterprise owner to maintain the balance of the customer's account, by ensuring that they capture the payment manually when they receive it.'

Matt-Yorkley commented 9 years ago

@oeoeaio not sure what you mean by "the idea of manually maintaining your balance at several different hubs (all of which may accept different payment methods) doesn't sound all that fun to me". It would mostly just be the odd refund for an order that came short.

"why does the fact that a user's balance is in credit (ie. was overcharged for something) necessarily entitle the enterprise to claim that credit for their store only?"

Because they issued the credit..? This mostly came from the set up at our hub, where customers can pre-pay and add credit onto their account for the month so they don't have to keep doing bank transfers every week, I think it's functionality some customers want and currently use. It wouldn't make sense if they spent it elsewhere, as they'd be getting credit at another enterprises without having paid those enterprises for it...

Also I think we refund any credit if a customer asks, but they usually regularly buy from the same hub, so it's not generally an issue.

"it would be entirely possible for a customer to have a net position of say negative $30 at a particular hub, but simultaneously have an account balance (global or not is irrelevant) of say positive $100, which could be used to pay off their debt if need be."

If it was non-global, a customer couldn't use credit from one hub to pay another hub, because the debt represents actual money owed between two parties, which can't be repayed by credit from a third party. The idea of an OFN instance having a global account and moving credit around between customers and enterprises is making my brain melt... :)

Matt-Yorkley commented 9 years ago

@oeoeaio Hmm, I think you're right though, it can't be slotted in to the existing framework without a seperate table and controller etc. that records the user, the enterprise, the amount and a description/reason.

lin-d-hop commented 9 years ago

Now merged in #313 Closing :-)