[REM] website_sale_aplicoop: remove dead code and orphaned tests

Duplicate _translate_labels fallback, unreachable /eskaera/add-to-cart and
/eskaera/save-cart routes (the frontend cart is localStorage-only and uses
save-order), redundant pickup wrappers, unused pagination/count helpers and
fields, deprecated JS shims, and the already-empty checkout_summary.js and
i18n key/init leftovers.

Also drops 11 tests/*.py never wired into tests/__init__.py: three were
unimplemented placeholders (setUp with no assertions), and the other eight
had real assertions but were bit-rotted against the current schema (e.g.
res.partner.is_supplier no longer exists) — wiring them in surfaced 43
failures unrelated to this cleanup. Verified 0 failed/0 errors of 270 tests
both before and after.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
GitHub Copilot 2026-08-16 22:31:13 +02:00
parent 6ba554c91b
commit b3999e2283
24 changed files with 5 additions and 5598 deletions

View file

@ -323,74 +323,6 @@ class AplicoopWebsiteSale(WebsiteSale):
)
return sale_order
def _create_draft_sale_order(
self,
group_order,
current_user,
sale_order_lines,
order_id,
pickup_date=None,
is_delivery=False,
):
"""Create a draft sale.order from prepared lines and propagate group fields.
Returns created sale.order record.
"""
consumer_group_id = self._validate_user_group_access(group_order, current_user)
_logger.info(
"[CONSUMER_GROUP DEBUG] _create_draft_sale_order: "
"group_order=%s, group_order.group_ids=%s, consumer_group_id=%s",
group_order.id,
group_order.group_ids.ids,
consumer_group_id,
)
effective_home_delivery, commitment_date = self._get_effective_delivery_context(
group_order, is_delivery
)
order_vals = {
"partner_id": current_user.partner_id.id,
"order_line": sale_order_lines,
"state": "draft",
"group_order_id": order_id,
"pickup_day": group_order.pickup_day,
"pickup_date": group_order.pickup_date,
"home_delivery": effective_home_delivery,
"consumer_group_id": consumer_group_id,
"commitment_date": commitment_date,
}
# Get salesperson for order creation (portal users need this)
salesperson = self._get_salesperson_for_order(current_user.partner_id)
if salesperson:
order_vals["user_id"] = salesperson.id
_logger.info(
"Creating draft sale.order with salesperson %s (%d)",
salesperson.name,
salesperson.id,
)
# Create order with sudo to avoid permission issues with portal users
sale_order = request.env["sale.order"].sudo().create(order_vals)
# Ensure the order has a name (sequence)
try:
if not sale_order.name or sale_order.name == "New":
sale_order._onchange_partner_id()
if not sale_order.name or sale_order.name == "New":
sale_order.name = "DRAFT-%s" % sale_order.id
except Exception as exc:
# Do not break creation on name generation issues
_logger.warning(
"Failed to generate name for draft sale order %s: %s",
sale_order.id,
exc,
)
return sale_order
def _build_confirmation_message(self, sale_order, group_order, is_delivery):
"""Build localized confirmation message for confirm_eskaera."""
# Get pickup day index, localized name and date string using helper
@ -447,28 +379,6 @@ class AplicoopWebsiteSale(WebsiteSale):
request_obj=request,
)
def _slot_time_label(self, slot):
return _pickup._slot_time_label(self, slot)
def _format_datetime_to_str(self, dt_val):
return _pickup._format_datetime_to_str(self, dt_val)
def _format_slot_pickup_info(self, group_order, slot):
return _pickup._format_slot_pickup_info(
self,
group_order,
slot,
request_obj=request,
)
def _format_legacy_pickup_info(self, group_order, is_delivery):
return _pickup._format_legacy_pickup_info(
self,
group_order,
is_delivery,
request_obj=request,
)
def _parse_save_cart_request(self):
"""Decode and validate the incoming save-cart request.
@ -1250,156 +1160,6 @@ class AplicoopWebsiteSale(WebsiteSale):
[("Content-Type", "application/json")],
)
@http.route(
["/eskaera/add-to-cart"],
type="http",
auth="user",
website=True,
methods=["POST"],
csrf=False,
)
def add_to_eskaera_cart(self, **post):
"""Validate and confirm product addition to cart.
The cart is managed in localStorage on the frontend.
This endpoint only validates that the product exists in the order.
"""
import json
try:
# Get JSON data from the request body
data = (
json.loads(request.httprequest.data) if request.httprequest.data else {}
)
order_id = int(data.get("order_id", 0))
product_id = int(data.get("product_id", 0))
quantity = float(data.get("quantity", 1))
group_order = request.env["group.order"].sudo().browse(order_id)
product = request.env["product.product"].sudo().browse(product_id)
# Validate that the order exists and is open
if not group_order.exists() or group_order.state != "open":
_logger.warning(
"add_to_eskaera_cart: Order %d not available (exists=%s, state=%s)",
order_id,
group_order.exists(),
group_order.state if group_order.exists() else "N/A",
)
return request.make_response(
json.dumps({"error": "Order is not available"}),
[("Content-Type", "application/json")],
)
if placed_response := self._build_already_placed_response(
request.env.user.partner_id.id, group_order
):
return placed_response
# Validate that the product is available in this order (use discovery logic)
available_products = group_order._get_products_for_group_order(
group_order.id
)
if product not in available_products:
_logger.warning(
"add_to_eskaera_cart: Product %d not available in order %d",
product_id,
order_id,
)
return request.make_response(
json.dumps({"error": "Product not available in this order"}),
[("Content-Type", "application/json")],
)
# Validate quantity
if quantity <= 0:
return request.make_response(
json.dumps({"error": "Quantity must be greater than 0"}),
[("Content-Type", "application/json")],
)
_logger.info(
"add_to_eskaera_cart: Added product %d (qty=%f) to order %d",
product_id,
quantity,
order_id,
)
# Get price with taxes using pricelist
_logger.info(
"add_to_eskaera_cart: Getting price for product %s (id=%s)",
product.name,
product_id,
)
pricelist = None
# Resolve pricelist using centralized helper
pricelist = self._resolve_pricelist()
if not pricelist:
_logger.error(
"add_to_eskaera_cart: ERROR - No pricelist found! Using list_price for product %s",
product.name,
)
product_variant = (
product.product_variant_ids[0] if product.product_variant_ids else False
)
if product_variant and pricelist:
try:
# Use OCA _get_price method - more robust and complete
price_info = product_variant._get_price(
qty=quantity,
pricelist=pricelist,
fposition=request.website.fiscal_position_id,
)
price_with_tax = price_info.get("value", product.list_price)
_logger.info(
"add_to_eskaera_cart: Product %s - Price: %.2f (original: %.2f, discount: %.1f%%)",
product.name,
price_with_tax,
price_info.get("original_value", 0),
price_info.get("discount", 0),
)
except Exception as e:
_logger.warning(
"add_to_eskaera_cart: Error getting price for product %s: %s. Using list_price=%.2f",
product.name,
str(e),
product.list_price,
)
else:
reason = "no pricelist" if not pricelist else "no variant"
_logger.info(
"add_to_eskaera_cart: Product %s - Using list_price fallback (reason: %s). Price=%.2f",
product.name,
reason,
price_with_tax,
)
response_data = {
"success": True,
"message": request.env._("%s added to cart", product.name),
"product_id": product_id,
"quantity": quantity,
"price": price_with_tax,
}
return request.make_response(
json.dumps(response_data), [("Content-Type", "application/json")]
)
except ValueError as e:
_logger.error("add_to_eskaera_cart: ValueError: %s", str(e))
return request.make_response(
json.dumps({"error": f"Invalid parameters: {str(e)}"}),
[("Content-Type", "application/json")],
)
except Exception as e:
_logger.error("add_to_eskaera_cart: Exception: %s", str(e), exc_info=True)
return request.make_response(json.dumps({"error": f"Error: {str(e)}"}))
@http.route(
["/eskaera/<int:order_id>/checkout"], type="http", auth="user", website=True
)
@ -1797,130 +1557,6 @@ class AplicoopWebsiteSale(WebsiteSale):
[("Content-Type", "application/json")],
)
@http.route(
["/eskaera/save-cart"],
type="http",
auth="user",
website=True,
methods=["POST"],
csrf=False,
)
def save_cart_draft(self, **post):
"""Save cart items as a draft sale.order with pickup date.
This controller delegates validation and heavy lifting to helpers
so the top-level flow remains easy to follow and McCabe-friendly.
"""
try:
_logger.warning("=== SAVE_CART_DRAFT CALLED ===")
try:
(
data,
order_id,
group_order,
current_user,
items,
pickup_date,
is_delivery,
) = self._parse_save_cart_request()
except BadRequestError as e:
return request.make_response(
json.dumps({"error": str(e)}),
[("Content-Type", "application/json")],
status=400,
)
except ForbiddenError as e:
return request.make_response(
json.dumps({"error": str(e)}),
[("Content-Type", "application/json")],
status=403,
)
except GroupOrderUnavailable:
order_id = None
try:
payload = self._decode_json_body()
order_id = (
int(payload.get("order_id"))
if payload.get("order_id")
else None
)
except Exception:
order_id = None
group_order = (
request.env["group.order"].sudo().browse(order_id)
if order_id
else False
)
return self._build_group_order_unavailable_response(group_order)
# Build sale.order lines and create draft using helpers
try:
sale_order_lines = self._process_cart_items(
items, group_order, pricelist=self._resolve_pricelist()
)
except ValueError as e:
return request.make_response(
json.dumps({"error": str(e)}),
[("Content-Type", "application/json")],
status=400,
)
sale_order = self._create_draft_sale_order(
group_order,
current_user,
sale_order_lines,
order_id,
pickup_date,
is_delivery=is_delivery,
)
_logger.info(
"Draft sale.order created: %d (name: %s) for partner %d",
sale_order.id,
sale_order.name,
current_user.partner_id.id,
)
# Compute a readable pickup slot label for the response. Prefer the
# order's stored computed label, otherwise derive from the group
# order using the same helper the confirmation flow uses.
pickup_slot_label = (
sale_order.pickup_slot_label
if getattr(sale_order, "pickup_slot_label", False)
else None
)
if not pickup_slot_label:
try:
pickup_slot_label = self._format_pickup_info(
group_order, is_delivery
)[0]
except Exception:
pickup_slot_label = None
return request.make_response(
json.dumps(
{
"success": True,
"message": request.env._("Cart saved as draft"),
"sale_order_id": sale_order.id,
"pickup_slot_label": pickup_slot_label,
}
),
[("Content-Type", "application/json")],
)
except Exception as e:
import traceback
_logger.error("save_cart_draft: Unexpected error: %s", str(e))
_logger.error(traceback.format_exc())
return request.make_response(
json.dumps({"error": str(e)}),
[("Content-Type", "application/json")],
status=500,
)
@http.route(
["/eskaera/load-draft"],
type="http",
@ -2723,107 +2359,6 @@ class AplicoopWebsiteSale(WebsiteSale):
_logger.error(traceback.format_exc())
return {"success": False, "error": f"Error confirming order: {str(e)}"}
def _translate_labels(self, labels_dict, lang):
"""Manually translate labels based on user language.
This is a fallback translation method for when Odoo's translation system
hasn't loaded translations from .po files properly.
"""
translations = {
"es_ES": {
"Draft Already Exists": "El Borrador Ya Existe",
"A saved draft already exists for the current order period.": "Un borrador guardado ya existe para el período actual del pedido.",
"You have two options:": "Tienes dos opciones:",
"Option 1: Merge with Existing Draft": "Opción 1: Fusionar con Borrador Existente",
"Combine your current cart with the existing draft.": "Combina tu carrito actual con el borrador existente.",
"Existing draft has": "El borrador existente tiene",
"Current cart has": "Tu carrito actual tiene",
"item(s)": "artículo(s)",
"Products will be merged by adding quantities. If a product exists in both, quantities will be combined.": "Los productos se fusionarán sumando cantidades. Si un producto existe en ambos, las cantidades se combinarán.",
"Option 2: Replace with Current Cart": "Opción 2: Reemplazar con Carrito Actual",
"Delete the old draft and save only the current cart items.": "Elimina el borrador anterior y guarda solo los artículos del carrito actual.",
"The existing draft will be permanently deleted.": "El borrador existente se eliminará permanentemente.",
"Merge": "Fusionar",
"Replace": "Reemplazar",
"Cancel": "Cancelar",
# Checkout page labels
"Home Delivery": "Entrega a Domicilio",
"Delivery Information": "Información de Entrega",
"Your order will be delivered the day after pickup between 11:00 - 14:00": "Tu pedido será entregado el día después de la recogida entre las 11:00 - 14:00",
"Important": "Importante",
"Once you confirm this order, you will not be able to modify it. Please review carefully before confirming.": "Una vez confirmes este pedido, no podrás modificarlo. Por favor, revisa cuidadosamente antes de confirmar.",
},
"eu_ES": {
"Draft Already Exists": "Zirriborro Dagoeneko Badago",
"A saved draft already exists for the current order period.": "Gordetako zirriborro bat dagoeneko badago uneko eskaera-aldirako.",
"You have two options:": "Bi aukera dituzu:",
"Option 1: Merge with Existing Draft": "1. Aukera: Existentea Duen Zirriborroarekin Batu",
"Combine your current cart with the existing draft.": "Batu zure gaur-oraingo saskia existentea duen zirriborroarekin.",
"Existing draft has": "Existentea duen zirriborroak du",
"Current cart has": "Zure gaur-oraingo saskiak du",
"item(s)": "artikulu(a)",
"Products will be merged by adding quantities. If a product exists in both, quantities will be combined.": "Produktuak batuko dira kantitateak gehituz. Produktu bat bian badago, kantitateak konbinatuko dira.",
"Option 2: Replace with Current Cart": "2. Aukera: Gaur-oraingo Askiarekin Ordeztu",
"Delete the old draft and save only the current cart items.": "Ezabatu zahar-zirriborroa eta gorde soilik gaur-oraingo saskiaren artikulua.",
"The existing draft will be permanently deleted.": "Existentea duen zirriborroa behin betiko ezabatuko da.",
"Merge": "Batu",
"Replace": "Ordeztu",
"Cancel": "Ezeztatu",
# Checkout page labels
"Home Delivery": "Etxera Bidalketa",
"Delivery Information": "Bidalketaren Informazioa",
"Your order will be delivered the day after pickup between 11:00 - 14:00": "Zure eskaera bidaliko da biltzeko eguaren ondoren 11:00 - 14:00 bitartean",
"Important": "Garrantzitsua",
"Once you confirm this order, you will not be able to modify it. Please review carefully before confirming.": "Behin eskaera hau berretsi ondoren, ezin izango duzu aldatu. Mesedez, arretaz berrikusi berretsi aurretik.",
},
# Also support 'eu' as a variant
"eu": {
"Draft Already Exists": "Zirriborro Dagoeneko Badago",
"A saved draft already exists for the current order period.": "Gordetako zirriborro bat dagoeneko badago uneko eskaera-aldirako.",
"You have two options:": "Bi aukera dituzu:",
"Option 1: Merge with Existing Draft": "1. Aukera: Existentea Duen Zirriborroarekin Batu",
"Combine your current cart with the existing draft.": "Batu zure gaur-oraingo saskia existentea duen zirriborroarekin.",
"Existing draft has": "Existentea duen zirriborroak du",
"Current cart has": "Zure gaur-oraingo saskiak du",
"item(s)": "artikulu(a)",
"Products will be merged by adding quantities. If a product exists in both, quantities will be combined.": "Produktuak batuko dira kantitateak gehituz. Produktu bat bian badago, kantitateak konbinatuko dira.",
"Option 2: Replace with Current Cart": "2. Aukera: Gaur-oraingo Askiarekin Ordeztu",
"Delete the old draft and save only the current cart items.": "Ezabatu zahar-zirriborroa eta gorde soilik gaur-oraingo saskiaren artikulua.",
"The existing draft will be permanently deleted.": "Existentea duen zirriborroa behin betiko ezabatuko da.",
"Merge": "Batu",
"Replace": "Ordeztu",
"Cancel": "Ezeztatu",
# Checkout page labels
"Home Delivery": "Etxera Bidalketa",
"Delivery Information": "Bidalketaren Informazioa",
"Your order will be delivered the day after pickup between 11:00 - 14:00": "Zure eskaera bidaliko da biltzeko eguaren ondoren 11:00 - 14:00 bitartean",
"Important": "Garrantzitsua",
"Once you confirm this order, you will not be able to modify it. Please review carefully before confirming.": "Behin eskaera hau berretsi ondoren, ezin izango duzu aldatu. Mesedez, arretaz berrikusi berretsi aurretik.",
},
}
# Get the translation dictionary for the user's language
# Try exact match first, then try without the region code (e.g., 'eu' from 'eu_ES')
lang_translations = translations.get(lang)
if not lang_translations and "_" in lang:
lang_code = lang.split("_")[0] # Get 'eu' from 'eu_ES'
lang_translations = translations.get(lang_code, {})
if not lang_translations:
lang_translations = {}
# Translate all English labels to the target language
translated = {}
for key, english_label in labels_dict.items():
translated[key] = lang_translations.get(english_label, english_label)
_logger.info(
"[_translate_labels] Language: %s, Translated %d labels",
lang,
len(translated),
)
return translated
@http.route(
["/eskaera/labels", "/eskaera/i18n"],
type="json",

View file

@ -149,18 +149,3 @@ def _get_translated_labels(self, lang=None, request_obj=None):
}
return labels
def _translate_labels(self, labels_dict, lang):
# Minimal fallback translator kept here; prefers env translations
translations = {
"es_ES": {},
}
lang_translations = translations.get(lang, {})
translated = {}
for key, english_label in labels_dict.items():
translated[key] = lang_translations.get(english_label, english_label)
_logger.info(
"[_translate_labels] Language: %s, Translated %d labels", lang, len(translated)
)
return translated