Skip to content

[16.0][mig] customer_wallet_(account-portal-pos)#397

Open
legalsylvain wants to merge 111 commits intocoopiteasy:16.0from
grap:16.0-mig-pos_customer_wallet-SLG-2026
Open

[16.0][mig] customer_wallet_(account-portal-pos)#397
legalsylvain wants to merge 111 commits intocoopiteasy:16.0from
grap:16.0-mig-pos_customer_wallet-SLG-2026

Conversation

@legalsylvain
Copy link
Contributor

@legalsylvain legalsylvain commented Jan 29, 2026

Description

Fixes

  • remove useless dependency to website module.
  • set customer_wallet_pos autoinstallable, otherwise, wallet amount is wrong if point_of_sale is installed.
  • improve computation performance.

refactoring

  • rename modules. So, the modules are next to each other in the repository. Also the main module doesn't require "account" suffix.
    • account_customer_wallet -> customer_wallet
    • portal_customer_wallet -> customer_wallet_portal
    • pos_customer_wallet -> customer_wallet_pos
  • move transient model in wizard folder
  • renaming js file, to follow odoo convention
  • minimum_wallet_amount is now stored

New features

  • account.payment.register : add a banner on payment form, to mention that it is possible to use Wallet Journal.
  • res.partner : new tree view to see all customer wallet amounts.
  • res.partner : add the wallet amount in the top of partner form view
  • res.partner : have the possibility to see the detail of all the moves that justify the current wallet amount. + same in portal.
  • Add possibility to redistribute wallet amount from a partner to another. (or many other.)

Doc

  • full update of documentation. Adding screenshot.

Checklist before approval

  • Tests are present (or not needed).
  • Credits/copyright have been changed correctly.
  • Change log snippet is present.
  • (If a new module) Moving this to OCA has been considered.

@github-grap-bot
Copy link
Contributor

Hi @carmenbianca,
some modules you are maintaining are being modified, check this out!

@legalsylvain legalsylvain force-pushed the 16.0-mig-pos_customer_wallet-SLG-2026 branch 2 times, most recently from 27b3f7d to 92d3593 Compare January 29, 2026 09:59
@codecov-commenter
Copy link

codecov-commenter commented Jan 29, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 90.46610% with 45 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.54%. Comparing base (110387a) to head (37b4cc9).
⚠️ Report is 469 commits behind head on 16.0.

Files with missing lines Patch % Lines
customer_wallet_portal/controllers/main.py 41.66% 14 Missing ⚠️
customer_wallet_pos/models/pos_session.py 78.94% 10 Missing and 2 partials ⚠️
...let/wizards/customer_wallet_redistribute_wizard.py 82.22% 5 Missing and 3 partials ⚠️
customer_wallet/models/res_partner.py 91.42% 5 Missing and 1 partial ⚠️
customer_wallet/models/account_payment.py 33.33% 1 Missing and 1 partial ⚠️
...er_wallet/wizards/customer_wallet_detail_wizard.py 91.66% 1 Missing and 1 partial ⚠️
customer_wallet_pos/tests/common.py 97.61% 0 Missing and 1 partial ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@             Coverage Diff             @@
##             16.0     #397       +/-   ##
===========================================
- Coverage   94.17%   81.54%   -12.64%     
===========================================
  Files          34      205      +171     
  Lines         584     2649     +2065     
  Branches       56      261      +205     
===========================================
+ Hits          550     2160     +1610     
- Misses         27      446      +419     
- Partials        7       43       +36     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@legalsylvain legalsylvain force-pushed the 16.0-mig-pos_customer_wallet-SLG-2026 branch 10 times, most recently from c5985a0 to 78a85f3 Compare February 4, 2026 22:23
@legalsylvain
Copy link
Contributor Author

@legalsylvain legalsylvain marked this pull request as ready for review February 4, 2026 22:28
@legalsylvain legalsylvain force-pushed the 16.0-mig-pos_customer_wallet-SLG-2026 branch from a6bffd8 to 5299fbb Compare February 10, 2026 16:30
@huguesdk huguesdk changed the title [WIP][16.0][mig] customer_wallet_(account-portal-pos) (do not review) [WIP][16.0][mig] customer_wallet_(account-portal-pos) Mar 6, 2026
Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
….config

Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
…t payment method

Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
…stead of settings

Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
…ines

This does not yet live-update in the POS. The window needs to be
reloaded to see the updated balance.

Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
… balance

Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
Signed-off-by: Carmen Bianca BAKKER <carmen@coopiteasy.be>
…etc...) when displaying partners with wallet account
…he customer wallet balance

- Add a dedicated wizard and menu entry to see all the wallets.
- Refactor & Improve computation mechanism.
- Fix incorrect _customer_wallet_depends() if point_of_sale is installed
- Total refactor of the portal part. Display credit and debit + fix: display pos pending moves.
…he core customer_wallet module doesn't work, when point of sale is installed
@legalsylvain legalsylvain force-pushed the 16.0-mig-pos_customer_wallet-SLG-2026 branch from ea8653c to 37b4cc9 Compare March 6, 2026 09:03
@huguesdk huguesdk changed the title [WIP][16.0][mig] customer_wallet_(account-portal-pos) [16.0][mig] customer_wallet_(account-portal-pos) Mar 6, 2026
Copy link
Member

@huguesdk huguesdk left a comment

Choose a reason for hiding this comment

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

as requested, here is my in-progress review. i will continue reviewing it afterwards.

but first of all: great work, thanks! i tested it functionally, and it works like a charm.

Copy link
Member

Choose a reason for hiding this comment

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

please don’t modify this file directly: it will be updated automatically on merge.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't ! It's done automatically by pre-commit execution AFAIK.

Copy link
Member

Choose a reason for hiding this comment

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

pre-commit generates the modules’ README.rst and index.html files, but this one is generated by oca-gen-addons-table. i think the changes here are a result of search and replace, and they might cause merge conflicts.

@@ -8,19 +8,24 @@
"version": "16.0.1.0.1",
"category": "Accounting & Finance",
Copy link
Member

Choose a reason for hiding this comment

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

category names have another structure now.

Suggested change
"category": "Accounting & Finance",
"category": "Accounting/Accounting",

"views/product_template_views.xml",
"views/res_config_settings_views.xml",
"views/res_partner_views.xml",
"wizards/res_config_settings_views.xml",
Copy link
Member

Choose a reason for hiding this comment

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

this is indeed a TransientModel, but usually, it is still put in the views directory (and its model in models).

Copy link
Member

Choose a reason for hiding this comment

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

creating a demo account (and journals) directly like this in xml doesn’t work if a new database is initialized with this module directly: at the end of the init, the account and journals are deleted when the chart of account is created in the post_init_hook of the account module. the cooperator module works around this by initializing the data in another way (see this function that is called from several places (data.xml and account.chart.template._load()) (the demo data is also initialized explicitly from this xml file to support the rare case where demo data is loaded afterwards).

because of this, if a database is initialized with this module directly, the tests will fail. however, the tests on the ci run anyway because the database is first initialized with all the modules this module depends on and the tests are run in a second step, when installing this module (actually, all the modules of the repository).

note that it is not that important (as it is only demo data, and it was already the case in 12) and can be added in the roadmap.

Copy link
Member

Choose a reason for hiding this comment

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

the name of the module is still “Account Customer Wallet”, while the technical name has changed. should the name be adapted also?

self.assertEqual(self.partner.customer_wallet_balance, 100)
self.assertEqual(self.other_partner_1.customer_wallet_balance, 0)

self._redistribute(30.0, [(self.other_partner_1, 30)])
Copy link
Member

Choose a reason for hiding this comment

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

i tried to perform this operation from the web ui, and it doesn’t work. as soon as i click on “redistribute”, the amount field (which i set at 30) resets to 100 and the user error dialog pops up saying “The amount to be redistributed (100.0) is different from the sum of the amounts (30.0).”. it seems that the amount field gets recomputed. maybe instead of using a compute function, use an onchange on partner_id?

<field name="arch" type="xml">

<button name="action_view_partner_invoices" position="after">
<button
Copy link
Member

Choose a reason for hiding this comment

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

great addition!

Comment on lines +65 to +78
<button
type="object"
name="action_view_customer_wallet_details"
string="Details"
class="btn-secondary"
attrs="{'invisible': [('has_customer_wallet', '=', False)]}"
/>
<button
type="object"
name="action_view_customer_wallet_redistribute"
string="Redistribute"
class="btn-secondary"
attrs="{'invisible': [('customer_wallet_balance', '&lt;=', 0.0)]}"
/>
Copy link
Member

Choose a reason for hiding this comment

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

these buttons are a great addition! however, they take quite some space in the list and cannot be hidden. moreover, the redistribute action is only available from this list. adding it as a form action on the partner would be great.

<field name="context">{
'search_default_company_and_individual': 1,
'search_default_customer_wallet_balance_nonzero': 1,
'active_test': False,
Copy link
Member

Choose a reason for hiding this comment

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

why this line?

</record>

<record id="action_res_partner_wallet" model="ir.actions.act_window">
<field name="name">Customer Wallets</field>
Copy link
Member

Choose a reason for hiding this comment

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

this act_window is a nice addition too! the only strange thing about it is that it has a “new” button, which allows to create a partner. i think that’s confusing, as it should mean “new customer wallet” (even if that doesn’t make much sense). i think it’s better to prevent to create new records there.

Copy link
Member

@huguesdk huguesdk left a comment

Choose a reason for hiding this comment

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

again, great work, @legalsylvain! here is the rest of my remarks.

question: why were the modules renamed? the convention in odoo seems to be {application_name}_{feature_name} so the previous names made more sense i think, as customer_wallet is not an application.

also, please squash the rename commits, as there have been some wrongly renamed values corrected afterwards.

thanks a lot for this work!

Comment on lines +11 to +17
<div
class="alert alert-warning text-center"
attrs="{'invisible': ['|', ('is_customer_wallet_journal', '=', True), ('customer_wallet_balance', '&lt;=', '0')]}"
role="alert"
>
You can select the customer account journal for this customer.
</div>
Copy link
Member

Choose a reason for hiding this comment

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

great addition! the funny thing is that you can pay an invoice containing the customer wallet product with the amount that this invoice represents, resulting in a null operation, without actually having transferred any money.

detail = fields.Html(compute="_compute_detail_html", sanitize=False)

@api.depends("partner_id")
def _compute_detail_html(self):
Copy link
Member

Choose a reason for hiding this comment

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

as explained earlier, i think it is better to call a method on the partner to compute the details here, instead of using a computed field on the partner that will be computed over and over mostly uselessly.

Copy link
Member

Choose a reason for hiding this comment

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

typo in the filename: should be redistribute instead of reditribute (s missing)

type="object"
class="oe_highlight"
/>
or
Copy link
Member

Choose a reason for hiding this comment

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

this "or" should be removed: it is implied and it displays badly (vertical alignment is bad).

)

amount = fields.Monetary(
compute="_compute_amount",
Copy link
Member

Choose a reason for hiding this comment

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

should probably use an onchange (and maybe a default also?) instead of compute, as the amount is reset when clicking the “redistribute” button.

is_balance_above_minimum(client, wallet_amount) {
return (
client.customer_wallet_balance - wallet_amount <=
this.env.pos.config.minimum_wallet_amount - 0.00001
Copy link
Member

Choose a reason for hiding this comment

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

this seems hacky (hardcoding a delta value like this). isn’t there a cleaner way?

Comment on lines +139 to +144
for (var i = 0; i < this.payment_methods_from_config.length; i++) {
if (this.payment_methods_from_config[i].is_customer_wallet_method) {
return this.payment_methods_from_config[i];
}
}
return null;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
for (var i = 0; i < this.payment_methods_from_config.length; i++) {
if (this.payment_methods_from_config[i].is_customer_wallet_method) {
return this.payment_methods_from_config[i];
}
}
return null;
return this.payment_methods_from_config.find((c) => c.is_customer_wallet_method) || null;

Comment on lines +154 to +160
var wallet_products = [];
for (const value of Object.values(this.env.pos.db.product_by_id)) {
if (value.is_customer_wallet_product) {
wallet_products.push(value);
}
}
return wallet_products;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
var wallet_products = [];
for (const value of Object.values(this.env.pos.db.product_by_id)) {
if (value.is_customer_wallet_product) {
wallet_products.push(value);
}
}
return wallet_products;
return Object.values(this.env.pos.db.product_by_id).filter((p) => p.is_customer_wallet_product);

Comment on lines +171 to +181
var order = this.currentOrder;
var method = this.find_customer_wallet_payment_method();
var wallet_amount = 0;
var lines_qty = 0;
order.paymentlines.forEach((item) => {
if (item.payment_method === method) {
wallet_amount += item.amount;
lines_qty += 1;
}
});
return [wallet_amount, lines_qty];
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
var order = this.currentOrder;
var method = this.find_customer_wallet_payment_method();
var wallet_amount = 0;
var lines_qty = 0;
order.paymentlines.forEach((item) => {
if (item.payment_method === method) {
wallet_amount += item.amount;
lines_qty += 1;
}
});
return [wallet_amount, lines_qty];
const method = this.find_customer_wallet_payment_method();
const lines = this.currentOrder.paymentlines.filter((line) => line.payment_method === method);
const wallet_amount = lines.reduce((sum, line) => sum + line.amount, 0);
return [wallet_amount, lines.length];

Comment on lines +192 to +208
var order = this.currentOrder;
var wallet_product_ids = [];
var wallet_products = this.find_customer_wallet_products();
wallet_products.forEach(function (product) {
wallet_product_ids.push(product.id);
});
var wallet_amount = 0;
var lines_qty = 0;

order.orderlines.forEach((orderline) => {
if (wallet_product_ids.includes(orderline.product.id)) {
wallet_amount += orderline.get_price_without_tax();
lines_qty += 1;
}
});

return [wallet_amount, lines_qty];
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
var order = this.currentOrder;
var wallet_product_ids = [];
var wallet_products = this.find_customer_wallet_products();
wallet_products.forEach(function (product) {
wallet_product_ids.push(product.id);
});
var wallet_amount = 0;
var lines_qty = 0;
order.orderlines.forEach((orderline) => {
if (wallet_product_ids.includes(orderline.product.id)) {
wallet_amount += orderline.get_price_without_tax();
lines_qty += 1;
}
});
return [wallet_amount, lines_qty];
const wallet_products_ids = this.find_customer_wallet_products().map(p => p.id);
const lines = this.currentOrder.orderlines.filter((line) => wallet_product_ids.includes(orderline.product.id));
const wallet_amount = lines.reduce((sum, line) => sum + line.get_price_without_tax(), 0);
return [wallet_amount, lines.length];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants