The "shop as a read-only catalog" behaviour lived inside website_sale_aplicoop, so every site that wanted the eskaera flow also lost the standard cart. It now ships as its own installable addon, with the redirect target configurable instead of hardcoded to /eskaera. - website_sale_disable_cart: hides the cart UI (12 header styles + the product card quick-add) and overrides the standard cart endpoints. Redirect URL is configurable in Website settings (default /shop); only site-internal paths are accepted, so a misconfigured value cannot turn the shop into an open redirect nor loop back into a disabled route. - Fixes carried over from the original code: /shop/cart/quantity is the Odoo 18 path (it was /shop/cart_quantity, which never matched), the boxed, sidebar and sales two/three/four headers were not covered (the cart link stayed visible on them), and the routes now override the standard methods instead of registering duplicate ones. - website_sale_aplicoop 18.0.1.12.0: drops the view file and the four redirect routes; installing it no longer touches the standard shop. Upgrade order matters: update website_sale_aplicoop first, then install website_sale_disable_cart in a second Odoo run — both use the same XPaths and obsolete records are only cleaned up at the end of a run. Tests: 8/8 in website_sale_disable_cart, aplicoop unaffected (its 2 failures predate this change). Verified live on a DB clone: /shop/cart returns 303 to the configured URL and no cart markup remains on /shop. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.9 KiB
4.9 KiB
Kidekoop — Odoo 18.0 Custom Addons
Odoo 18.0 (OCB community) addons repo. Code in English, UI in Basque/Spanish.
Combines OCB (ocb/), inherited OCA addons, and our own custom addons.
⚠️ Critical rules (non-negotiable)
- DO NOT modify the OCB core (
ocb/) nor these original OCA addons (reference/inheritance only):product_main_seller,account_invoice_triple_discount,product_get_price_helper,product_price_category,purchase_triple_discount,base_bank_from_iban,l10n_es_partner. All changes go in our own custom addons. - Do NOT use
_()in field definitions (triggers import-time warnings). Only in methods/executable code. - Business logic ALWAYS on
product.product(variants), never onproduct.template(userelatedthere). Avoids issues with pricelists and reports that operate at the variant level. - No logic in QWeb: prepare all data in the Python controller; templates only do simple attribute access.
- No business logic in JavaScript: UI/events only.
- Translations: edit
.pofiles withpolib(append).msgmergecorrupts the files — do not use it.
Stack
Odoo 18.0 · Python 3.10+ · PostgreSQL · Docker Compose · XML/QWeb/JS.
Formatting: black (line 88) + isort (black profile) + flake8 + pylint-odoo. Pre-commit active.
Commands
docker-compose up -d # env (8070=web, 8073=longpolling)
docker-compose run odoo odoo -d odoo --test-enable --stop-after-init -u <addon> # tests (run, NOT exec: avoids cache)
docker-compose exec odoo odoo -d odoo -u <addon> --stop-after-init # update addon
docker-compose logs -f odoo # logs
docker-compose exec db psql -U odoo -d odoo # postgres
make lint | make format | make check-format | make flake8 | make pylint-required
pre-commit run --all-files
Odoo conventions
- Models
snake.case· classesPascalCase· filessnake_case.py· XML IDsmodule.name. - Manifest always
__manifest__.py, version18.0.X.Y.Z,dependsalphabetically ordered. - Views: 4 spaces, explicit
positionin XPath, groups viamodule.xml_id,sequencefor ordering. - Bulk: prefer
search().write()over loops;create([vals, ...])for bulk create. - Notifications:
ir.actions.client+display_notification. - Detailed logging in price/discount computations:
_logger.info("[PRICE] ...", ...).
Custom addons
Pricing & products:
product_sale_price_from_pricelist— auto-computes sale price from last purchase price + pricelist. Requires taxes on the product andlast_purchase_price_compute_type != "manual_update". Also applies supplier discounts fromsupplierinfo.product_pricelist_total_margin— total margin computed additively (Markup or Commercial Margin), with global limits.product_price_category_supplier— price categories per supplier.product_origin_char— free-text origin field per product (template-based).account_invoice_triple_discount_readonly— fix for triple-discount accumulation bug (always use it).
Sales & website:
website_sale_aplicoop— Eskaera: collaborative purchasing for consumer co-ops (group orders, per-member carts, cutoff/pickup dates, lazy loading, multi-language).website_sale_disable_cart— turns/shopinto a read-only catalog: hides the cart UI and redirects the standard/shop/cart*routes to a configurable URL (default/shop).portal_event_registration— portal users view their event registrations + upload attachments to chatter.
Membership:
membership_monthly_invoicing— auto-creates a monthly membership invoice per active member (cron-driven).membership_expiry_reminder— automated renewal-reminder emails near expiry, with online renew link.
Logistics & accounting:
stock_picking_batch_custom— batch picking extras: extra detailed-op columns, ordering by category/product/partner, and a full-screen operator (Basket Assembly) view.account_banking_mandate_batch— contextual action to bulk-create/validate SEPA mandates for selected partners.l10n_es_edi_tbai_reagyp_recibidas— TicketBAI fix: REAGYP vendor-bill regime key 19 → 02.
Documentation
- Per-addon details: its
README.rst(OCA) orREADME_DEV.md(technical). - Global patterns:
.github/copilot-instructions.md(extended version of this file). - Guides:
docs/QWEB_BEST_PRACTICES.md,docs/OCA_DOCUMENTATION.md,docs/LAZY_LOADING.md. - OCA
readme/structure (DESCRIPTION, INSTALL, CONFIGURE, USAGE, CONTRIBUTORS, CREDITS). Credits: Criptomart (author) + Elika Bilbo (funder).
Commits
[TAG] module: description — tags: [ADD] [FIX] [IMP] [REF] [REM] [I18N] [DOC].
Available skills
Per-language skills (odoo-python, odoo-xml-views, odoo-qweb-html, odoo-javascript) and the
OpenSpec workflow (openspec-explore/propose/apply-change/archive-change, /opsx:* commands) live in .claude/.