Compare commits
2 commits
ff87243476
...
331a2e8944
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
331a2e8944 | ||
|
|
813c8071d9 |
8 changed files with 224 additions and 147 deletions
|
|
@ -188,7 +188,9 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
"error_unknown": env_lang._("Unknown error"),
|
"error_unknown": env_lang._("Unknown error"),
|
||||||
"error_invalid_data": env_lang._("Invalid data provided"),
|
"error_invalid_data": env_lang._("Invalid data provided"),
|
||||||
"error_order_not_found": env_lang._("Order not found"),
|
"error_order_not_found": env_lang._("Order not found"),
|
||||||
"error_no_draft_orders": env_lang._("No draft orders found for this week"),
|
"error_no_draft_orders": env_lang._(
|
||||||
|
"No draft orders found for the current order period"
|
||||||
|
),
|
||||||
"invalid_quantity": env_lang._("Please enter a valid quantity"),
|
"invalid_quantity": env_lang._("Please enter a valid quantity"),
|
||||||
# ============ CONFIRMATION MESSAGES ============
|
# ============ CONFIRMATION MESSAGES ============
|
||||||
"save_draft_confirm": env_lang._(
|
"save_draft_confirm": env_lang._(
|
||||||
|
|
@ -207,7 +209,7 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
# ============ DRAFT MODAL LABELS ============
|
# ============ DRAFT MODAL LABELS ============
|
||||||
"draft_already_exists": env_lang._("Draft Already Exists"),
|
"draft_already_exists": env_lang._("Draft Already Exists"),
|
||||||
"draft_exists_message": env_lang._(
|
"draft_exists_message": env_lang._(
|
||||||
"A saved draft already exists for this week."
|
"A saved draft already exists for the current order period."
|
||||||
),
|
),
|
||||||
"draft_two_options": env_lang._("You have two options:"),
|
"draft_two_options": env_lang._("You have two options:"),
|
||||||
"draft_option1_title": env_lang._("Option 1: Merge with Existing Draft"),
|
"draft_option1_title": env_lang._("Option 1: Merge with Existing Draft"),
|
||||||
|
|
@ -1428,34 +1430,41 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
status=status,
|
status=status,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _find_recent_draft_order(self, partner_id, order_id):
|
def _find_recent_draft_order(self, partner_id, group_order):
|
||||||
"""Find most recent draft sale.order for partner and group_order in current week.
|
"""Find most recent draft sale.order for partner in the active order period.
|
||||||
|
|
||||||
Returns the record or empty recordset.
|
Priority for period matching:
|
||||||
|
1) If group_order.pickup_date is set, match that exact pickup_date
|
||||||
|
(prevents reusing stale drafts from previous cycles of same group.order).
|
||||||
|
2) Fallback to current-week create_date bounds when pickup_date is not set.
|
||||||
|
|
||||||
|
Returns the recordset (limit=1) or empty recordset.
|
||||||
"""
|
"""
|
||||||
from datetime import datetime
|
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
today = datetime.now().date()
|
today = datetime.now().date()
|
||||||
start_of_week = today - timedelta(days=today.weekday())
|
start_of_week = today - timedelta(days=today.weekday())
|
||||||
end_of_week = start_of_week + timedelta(days=6)
|
end_of_week = start_of_week + timedelta(days=6)
|
||||||
|
|
||||||
drafts = (
|
domain = [
|
||||||
request.env["sale.order"]
|
("partner_id", "=", partner_id),
|
||||||
.sudo()
|
("group_order_id", "=", group_order.id),
|
||||||
.search(
|
("state", "=", "draft"),
|
||||||
|
]
|
||||||
|
|
||||||
|
if group_order.pickup_date:
|
||||||
|
domain.append(("pickup_date", "=", group_order.pickup_date))
|
||||||
|
else:
|
||||||
|
domain.extend(
|
||||||
[
|
[
|
||||||
("partner_id", "=", partner_id),
|
|
||||||
("group_order_id", "=", order_id),
|
|
||||||
("state", "=", "draft"),
|
|
||||||
("create_date", ">=", f"{start_of_week} 00:00:00"),
|
("create_date", ">=", f"{start_of_week} 00:00:00"),
|
||||||
("create_date", "<=", f"{end_of_week} 23:59:59"),
|
("create_date", "<=", f"{end_of_week} 23:59:59"),
|
||||||
],
|
]
|
||||||
order="create_date desc",
|
|
||||||
limit=1,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
request.env["sale.order"]
|
||||||
|
.sudo()
|
||||||
|
.search(domain, order="create_date desc", limit=1)
|
||||||
)
|
)
|
||||||
return drafts
|
|
||||||
|
|
||||||
@http.route(["/eskaera/<int:order_id>"], type="http", auth="user", website=True)
|
@http.route(["/eskaera/<int:order_id>"], type="http", auth="user", website=True)
|
||||||
def eskaera_shop(self, order_id, **post):
|
def eskaera_shop(self, order_id, **post):
|
||||||
|
|
@ -2258,7 +2267,7 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
csrf=False,
|
csrf=False,
|
||||||
)
|
)
|
||||||
def load_draft_cart(self, **post):
|
def load_draft_cart(self, **post):
|
||||||
"""Load items from the most recent draft sale.order for this week."""
|
"""Load items from the most recent draft sale.order for current period."""
|
||||||
import json
|
import json
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -2318,16 +2327,18 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
status=400,
|
status=400,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Find the most recent draft sale.order for this partner from this week
|
# Find the most recent draft sale.order for this partner in active period
|
||||||
# The helper _find_recent_draft_order computes the week bounds itself,
|
# The helper _find_recent_draft_order computes the period criteria itself,
|
||||||
# so we only need to call it here.
|
# so we only need to call it here.
|
||||||
|
|
||||||
# Find the most recent matching draft order using helper
|
# Find the most recent matching draft order using helper
|
||||||
draft_orders = self._find_recent_draft_order(
|
draft_orders = self._find_recent_draft_order(
|
||||||
current_user.partner_id.id, order_id
|
current_user.partner_id.id, group_order
|
||||||
)
|
)
|
||||||
if not draft_orders:
|
if not draft_orders:
|
||||||
error_msg = request.env._("No draft orders found for this week")
|
error_msg = request.env._(
|
||||||
|
"No draft orders found for the current order period"
|
||||||
|
)
|
||||||
return request.make_response(
|
return request.make_response(
|
||||||
json.dumps({"error": error_msg}),
|
json.dumps({"error": error_msg}),
|
||||||
[("Content-Type", "application/json")],
|
[("Content-Type", "application/json")],
|
||||||
|
|
@ -2496,17 +2507,9 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
status=400,
|
status=400,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if a draft already exists for this group order and user
|
# Check if a draft already exists for this user in current order period
|
||||||
existing_drafts = (
|
existing_drafts = self._find_recent_draft_order(
|
||||||
request.env["sale.order"]
|
current_user.partner_id.id, group_order
|
||||||
.sudo()
|
|
||||||
.search(
|
|
||||||
[
|
|
||||||
("group_order_id", "=", order_id),
|
|
||||||
("partner_id", "=", current_user.partner_id.id),
|
|
||||||
("state", "=", "draft"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
_logger.info(
|
_logger.info(
|
||||||
|
|
@ -2633,18 +2636,9 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
status=400,
|
status=400,
|
||||||
)
|
)
|
||||||
|
|
||||||
# First, check if there's already a draft sale.order for this user in this group order
|
# Reuse only draft from the current group_order cycle (not stale ones)
|
||||||
existing_order = (
|
existing_order = self._find_recent_draft_order(
|
||||||
request.env["sale.order"]
|
current_user.partner_id.id, group_order
|
||||||
.sudo()
|
|
||||||
.search(
|
|
||||||
[
|
|
||||||
("partner_id", "=", current_user.partner_id.id),
|
|
||||||
("group_order_id", "=", group_order.id),
|
|
||||||
("state", "=", "draft"),
|
|
||||||
],
|
|
||||||
limit=1,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if existing_order:
|
if existing_order:
|
||||||
|
|
@ -2934,7 +2928,7 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
translations = {
|
translations = {
|
||||||
"es_ES": {
|
"es_ES": {
|
||||||
"Draft Already Exists": "El Borrador Ya Existe",
|
"Draft Already Exists": "El Borrador Ya Existe",
|
||||||
"A saved draft already exists for this week.": "Un borrador guardado ya existe para esta semana.",
|
"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:",
|
"You have two options:": "Tienes dos opciones:",
|
||||||
"Option 1: Merge with Existing Draft": "Opción 1: Fusionar con Borrador Existente",
|
"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.",
|
"Combine your current cart with the existing draft.": "Combina tu carrito actual con el borrador existente.",
|
||||||
|
|
@ -2957,7 +2951,7 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
},
|
},
|
||||||
"eu_ES": {
|
"eu_ES": {
|
||||||
"Draft Already Exists": "Zirriborro Dagoeneko Badago",
|
"Draft Already Exists": "Zirriborro Dagoeneko Badago",
|
||||||
"A saved draft already exists for this week.": "Gordetako zirriborro bat dagoeneko badago asteburu honetarako.",
|
"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:",
|
"You have two options:": "Bi aukera dituzu:",
|
||||||
"Option 1: Merge with Existing Draft": "1. Aukera: Existentea Duen Zirriborroarekin Batu",
|
"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.",
|
"Combine your current cart with the existing draft.": "Batu zure gaur-oraingo saskia existentea duen zirriborroarekin.",
|
||||||
|
|
@ -2981,7 +2975,7 @@ class AplicoopWebsiteSale(WebsiteSale):
|
||||||
# Also support 'eu' as a variant
|
# Also support 'eu' as a variant
|
||||||
"eu": {
|
"eu": {
|
||||||
"Draft Already Exists": "Zirriborro Dagoeneko Badago",
|
"Draft Already Exists": "Zirriborro Dagoeneko Badago",
|
||||||
"A saved draft already exists for this week.": "Gordetako zirriborro bat dagoeneko badago asteburu honetarako.",
|
"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:",
|
"You have two options:": "Bi aukera dituzu:",
|
||||||
"Option 1: Merge with Existing Draft": "1. Aukera: Existentea Duen Zirriborroarekin Batu",
|
"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.",
|
"Combine your current cart with the existing draft.": "Batu zure gaur-oraingo saskia existentea duen zirriborroarekin.",
|
||||||
|
|
|
||||||
|
|
@ -240,15 +240,8 @@ msgstr "<span>Día de Recogida</span>"
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#. odoo-python
|
#. odoo-python
|
||||||
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
||||||
msgid "A draft already exists for this week."
|
msgid "A saved draft already exists for the current order period."
|
||||||
msgstr "Ya existe un borrador para esta semana."
|
msgstr "Ya existe un borrador guardado para el período actual del pedido."
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#. odoo-python
|
|
||||||
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
|
||||||
#: code:addons/website_sale_aplicoop/models/js_translations.py:0
|
|
||||||
msgid "A saved draft already exists for this week."
|
|
||||||
msgstr "Ya existe un borrador guardado para esta semana."
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.eskaera_shop
|
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.eskaera_shop
|
||||||
|
|
@ -918,9 +911,8 @@ msgstr ""
|
||||||
#. odoo-python
|
#. odoo-python
|
||||||
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
||||||
#: code:addons/website_sale_aplicoop/models/js_translations.py:0
|
#: code:addons/website_sale_aplicoop/models/js_translations.py:0
|
||||||
#, fuzzy
|
msgid "No draft orders found for the current order period"
|
||||||
msgid "No draft orders found for this week"
|
msgstr "No se encontraron borradores para el período actual del pedido"
|
||||||
msgstr "Ya existe un borrador para esta semana."
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.eskaera_page
|
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.eskaera_page
|
||||||
|
|
@ -1453,46 +1445,16 @@ msgstr "con el borrador guardado."
|
||||||
msgid "{{ product.name }}"
|
msgid "{{ product.name }}"
|
||||||
msgstr "{{ product.name }}"
|
msgstr "{{ product.name }}"
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "Consumer Group"
|
|
||||||
msgstr "Grupo de Consumidores"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "Delivery Information"
|
|
||||||
msgstr "Información de Envío"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
||||||
msgid "Delivery Date"
|
msgid "Delivery Date"
|
||||||
msgstr "Fecha de Entrega"
|
msgstr "Fecha de Entrega"
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "Pickup Date"
|
|
||||||
msgstr "Fecha de Recogida"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "Delivery Notice"
|
|
||||||
msgstr "Aviso de Envío"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "No special delivery instructions"
|
|
||||||
msgstr "Sin instrucciones especiales de entrega"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
||||||
msgid "Pickup Location"
|
msgid "Pickup Location"
|
||||||
msgstr "Lugar de Recogida"
|
msgstr "Lugar de Recogida"
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.portal_order_page_sidebar_button
|
|
||||||
msgid "Load in Cart"
|
|
||||||
msgstr "Recargar Carrito"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model:product.ribbon,name:website_sale_aplicoop.out_of_stock_ribbon
|
#: model:product.ribbon,name:website_sale_aplicoop.out_of_stock_ribbon
|
||||||
msgid "Out of Stock"
|
msgid "Out of Stock"
|
||||||
|
|
|
||||||
|
|
@ -241,15 +241,8 @@ msgstr "<span>Biltzeko Lekua:</span>"
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#. odoo-python
|
#. odoo-python
|
||||||
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
||||||
msgid "A draft already exists for this week."
|
msgid "A saved draft already exists for the current order period."
|
||||||
msgstr "Zirriborro bat dagoeneko existitzen da astean honetan."
|
msgstr "Gordetako zirriborro bat dagoeneko badago uneko eskaera-aldirako."
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#. odoo-python
|
|
||||||
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
|
||||||
#: code:addons/website_sale_aplicoop/models/js_translations.py:0
|
|
||||||
msgid "A saved draft already exists for this week."
|
|
||||||
msgstr "Gordetako zirriborro bat dagoeneko existitzen da astean honetan."
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.eskaera_shop
|
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.eskaera_shop
|
||||||
|
|
@ -917,9 +910,8 @@ msgstr ""
|
||||||
#. odoo-python
|
#. odoo-python
|
||||||
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
#: code:addons/website_sale_aplicoop/controllers/website_sale.py:0
|
||||||
#: code:addons/website_sale_aplicoop/models/js_translations.py:0
|
#: code:addons/website_sale_aplicoop/models/js_translations.py:0
|
||||||
#, fuzzy
|
msgid "No draft orders found for the current order period"
|
||||||
msgid "No draft orders found for this week"
|
msgstr "Ez da zirriborrorik aurkitu uneko eskaera-aldirako"
|
||||||
msgstr "Zirriborro bat dagoeneko existitzen da astean honetan."
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.eskaera_page
|
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.eskaera_page
|
||||||
|
|
@ -1453,46 +1445,16 @@ msgstr "gordetako zirriborroarekin."
|
||||||
msgid "{{ product.name }}"
|
msgid "{{ product.name }}"
|
||||||
msgstr "{{ product.name }}"
|
msgstr "{{ product.name }}"
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "Consumer Group"
|
|
||||||
msgstr "Kontsumo Taldea"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "Delivery Information"
|
|
||||||
msgstr "Delibatua Informazioa"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
||||||
msgid "Delivery Date"
|
msgid "Delivery Date"
|
||||||
msgstr "Entrega Data"
|
msgstr "Entrega Data"
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "Pickup Date"
|
|
||||||
msgstr "Biltzea Data"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "Delivery Notice"
|
|
||||||
msgstr "Delibatua Oharra"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
|
||||||
msgid "No special delivery instructions"
|
|
||||||
msgstr "Ez dago entregaren instrukzio bereziak"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.sale_order_portal_content_aplicoop
|
||||||
msgid "Pickup Location"
|
msgid "Pickup Location"
|
||||||
msgstr "Biltzeko Lekua"
|
msgstr "Biltzeko Lekua"
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
|
||||||
#: model_terms:ir.ui.view,arch_db:website_sale_aplicoop.portal_order_page_sidebar_button
|
|
||||||
msgid "Load in Cart"
|
|
||||||
msgstr "Saskia Berrkargatu"
|
|
||||||
|
|
||||||
#. module: website_sale_aplicoop
|
#. module: website_sale_aplicoop
|
||||||
#: model:product.ribbon,name:website_sale_aplicoop.out_of_stock_ribbon
|
#: model:product.ribbon,name:website_sale_aplicoop.out_of_stock_ribbon
|
||||||
msgid "Out of Stock"
|
msgid "Out of Stock"
|
||||||
|
|
|
||||||
|
|
@ -645,16 +645,65 @@ class GroupOrder(models.Model):
|
||||||
Only updates orders in 'draft' or 'open' states.
|
Only updates orders in 'draft' or 'open' states.
|
||||||
"""
|
"""
|
||||||
orders = self.search([("state", "in", ["draft", "open"])])
|
orders = self.search([("state", "in", ["draft", "open"])])
|
||||||
_logger.info("Cron: Updating dates for %d active group orders", len(orders))
|
cron_started_at = fields.Datetime.now()
|
||||||
|
_logger.info(
|
||||||
|
"Cron: Starting group.order date update at %s for %d active orders (ids=%s)",
|
||||||
|
cron_started_at,
|
||||||
|
len(orders),
|
||||||
|
orders.ids,
|
||||||
|
)
|
||||||
|
processed_orders = 0
|
||||||
|
failed_orders = []
|
||||||
for order in orders:
|
for order in orders:
|
||||||
# Confirm BEFORE recomputing dates: cutoff_date still points to the
|
before_values = {
|
||||||
# current cycle's cutoff (today or past), so the check works correctly.
|
"state": order.state,
|
||||||
# After confirmation, recompute dates so they advance to the next cycle.
|
"period": order.period,
|
||||||
order._confirm_linked_sale_orders()
|
"start_date": order.start_date,
|
||||||
order._compute_cutoff_date()
|
"end_date": order.end_date,
|
||||||
order._compute_pickup_date()
|
"cutoff_day": order.cutoff_day,
|
||||||
order._compute_delivery_date()
|
"pickup_day": order.pickup_day,
|
||||||
_logger.info("Cron: Date update completed")
|
"cutoff_date": order.cutoff_date,
|
||||||
|
"pickup_date": order.pickup_date,
|
||||||
|
"delivery_date": order.delivery_date,
|
||||||
|
"home_delivery": order.home_delivery,
|
||||||
|
}
|
||||||
|
_logger.info(
|
||||||
|
"Cron: Processing group order %s (%s) with values before recompute: %s",
|
||||||
|
order.id,
|
||||||
|
order.name,
|
||||||
|
before_values,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
# Confirm BEFORE recomputing dates: cutoff_date still points to the
|
||||||
|
# current cycle's cutoff (today or past), so the check works correctly.
|
||||||
|
# After confirmation, recompute dates so they advance to the next cycle.
|
||||||
|
order._confirm_linked_sale_orders()
|
||||||
|
order._compute_cutoff_date()
|
||||||
|
order._compute_pickup_date()
|
||||||
|
order._compute_delivery_date()
|
||||||
|
processed_orders += 1
|
||||||
|
_logger.info(
|
||||||
|
"Cron: Finished group order %s (%s). Dates after recompute: cutoff=%s, pickup=%s, delivery=%s",
|
||||||
|
order.id,
|
||||||
|
order.name,
|
||||||
|
order.cutoff_date,
|
||||||
|
order.pickup_date,
|
||||||
|
order.delivery_date,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
failed_orders.append(order.id)
|
||||||
|
_logger.exception(
|
||||||
|
"Cron: Error while processing group order %s (%s). Initial values were: %s",
|
||||||
|
order.id,
|
||||||
|
order.name,
|
||||||
|
before_values,
|
||||||
|
)
|
||||||
|
_logger.info(
|
||||||
|
"Cron: Date update completed. processed=%d failed=%d failed_ids=%s",
|
||||||
|
processed_orders,
|
||||||
|
len(failed_orders),
|
||||||
|
failed_orders,
|
||||||
|
)
|
||||||
|
|
||||||
def _confirm_linked_sale_orders(self):
|
def _confirm_linked_sale_orders(self):
|
||||||
"""Confirm draft/sent sale orders linked to this group order.
|
"""Confirm draft/sent sale orders linked to this group order.
|
||||||
|
|
@ -669,13 +718,26 @@ class GroupOrder(models.Model):
|
||||||
|
|
||||||
today = fields.Date.today()
|
today = fields.Date.today()
|
||||||
|
|
||||||
|
if not self.cutoff_date:
|
||||||
|
_logger.warning(
|
||||||
|
"Cron: Group order %s (%s) has no cutoff_date (state=%s, period=%s, cutoff_day=%s, start_date=%s). Skipping sale order confirmation for this cycle.",
|
||||||
|
self.id,
|
||||||
|
self.name,
|
||||||
|
self.state,
|
||||||
|
self.period,
|
||||||
|
self.cutoff_day,
|
||||||
|
self.start_date,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
# Skip if cutoff hasn't passed yet (the cycle is still open for orders)
|
# Skip if cutoff hasn't passed yet (the cycle is still open for orders)
|
||||||
if self.cutoff_date >= today:
|
if self.cutoff_date >= today:
|
||||||
_logger.info(
|
_logger.info(
|
||||||
"Cron: Skipping group order %s (%s) - cutoff date %s not yet passed",
|
"Cron: Skipping group order %s (%s) - cutoff date %s not yet passed (today=%s)",
|
||||||
self.id,
|
self.id,
|
||||||
self.name,
|
self.name,
|
||||||
self.cutoff_date,
|
self.cutoff_date,
|
||||||
|
today,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ def _register_translations():
|
||||||
# Draft Modal Labels
|
# Draft Modal Labels
|
||||||
# ========================
|
# ========================
|
||||||
_("Draft Already Exists")
|
_("Draft Already Exists")
|
||||||
_("A saved draft already exists for this week.")
|
_("A saved draft already exists for the current order period.")
|
||||||
_("You have two options:")
|
_("You have two options:")
|
||||||
_("Option 1: Merge with Existing Draft")
|
_("Option 1: Merge with Existing Draft")
|
||||||
_("Combine your current cart with the existing draft.")
|
_("Combine your current cart with the existing draft.")
|
||||||
|
|
@ -89,7 +89,7 @@ def _register_translations():
|
||||||
# Error Messages
|
# Error Messages
|
||||||
# ========================
|
# ========================
|
||||||
_("Error: Order ID not found")
|
_("Error: Order ID not found")
|
||||||
_("No draft orders found for this week")
|
_("No draft orders found for the current order period")
|
||||||
_("Connection error")
|
_("Connection error")
|
||||||
_("Error loading order")
|
_("Error loading order")
|
||||||
_("Error loading draft")
|
_("Error loading draft")
|
||||||
|
|
|
||||||
|
|
@ -1015,7 +1015,7 @@
|
||||||
all_categories: "All categories",
|
all_categories: "All categories",
|
||||||
// Draft modal labels
|
// Draft modal labels
|
||||||
draft_already_exists: "Draft Already Exists",
|
draft_already_exists: "Draft Already Exists",
|
||||||
draft_exists_message: "A saved draft already exists for this week.",
|
draft_exists_message: "A saved draft already exists for the current order period.",
|
||||||
draft_two_options: "You have two options:",
|
draft_two_options: "You have two options:",
|
||||||
draft_option1_title: "Option 1: Merge with Existing Draft",
|
draft_option1_title: "Option 1: Merge with Existing Draft",
|
||||||
draft_option1_desc: "Combine your current cart with the existing draft.",
|
draft_option1_desc: "Combine your current cart with the existing draft.",
|
||||||
|
|
|
||||||
|
|
@ -566,3 +566,49 @@ class TestDateCalculations(TransactionCase):
|
||||||
order.pickup_date,
|
order.pickup_date,
|
||||||
f"Pickup date should be set for active order {order.name}",
|
f"Pickup date should be set for active order {order.name}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_cron_update_dates_skips_orders_without_cutoff_date(self):
|
||||||
|
"""Cron should not crash if an active order lacks cutoff_date.
|
||||||
|
|
||||||
|
A malformed or partially configured active group order should be logged
|
||||||
|
and skipped for sale-order confirmation, but must not block recomputing
|
||||||
|
the rest of active orders.
|
||||||
|
"""
|
||||||
|
today = fields.Date.today()
|
||||||
|
|
||||||
|
valid_order = self.env["group.order"].create(
|
||||||
|
{
|
||||||
|
"name": "Valid Cron Order",
|
||||||
|
"group_ids": [(6, 0, [self.group.id])],
|
||||||
|
"start_date": today,
|
||||||
|
"pickup_day": "2", # Wednesday
|
||||||
|
"cutoff_day": "0", # Monday
|
||||||
|
"period": "weekly",
|
||||||
|
"state": "open",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
invalid_order = self.env["group.order"].create(
|
||||||
|
{
|
||||||
|
"name": "Invalid Cron Order Without Cutoff",
|
||||||
|
"group_ids": [(6, 0, [self.group.id])],
|
||||||
|
"start_date": today,
|
||||||
|
"pickup_day": "2", # Wednesday
|
||||||
|
"cutoff_day": False,
|
||||||
|
"period": "weekly",
|
||||||
|
"state": "open",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
invalid_order.cutoff_date,
|
||||||
|
"Precondition failed: invalid order should not have cutoff_date",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.env["group.order"]._cron_update_dates()
|
||||||
|
|
||||||
|
valid_order.invalidate_recordset()
|
||||||
|
invalid_order.invalidate_recordset()
|
||||||
|
|
||||||
|
self.assertTrue(valid_order.cutoff_date)
|
||||||
|
self.assertTrue(valid_order.pickup_date)
|
||||||
|
self.assertFalse(invalid_order.cutoff_date)
|
||||||
|
|
|
||||||
|
|
@ -667,3 +667,54 @@ class TestConfirmEskaera_Integration(TransactionCase):
|
||||||
existing_order.invalidate_recordset()
|
existing_order.invalidate_recordset()
|
||||||
self.assertEqual(len(existing_order.order_line), 1)
|
self.assertEqual(len(existing_order.order_line), 1)
|
||||||
self.assertEqual(existing_order.order_line[0].product_uom_qty, 5)
|
self.assertEqual(existing_order.order_line[0].product_uom_qty, 5)
|
||||||
|
|
||||||
|
@patch("odoo.http.request")
|
||||||
|
def test_confirm_eskaera_ignores_old_period_draft(self, mock_request):
|
||||||
|
"""Old draft from previous pickup_date must not be reused."""
|
||||||
|
mock_request.env = self.env.with_user(self.user)
|
||||||
|
mock_request.env.lang = "es_ES"
|
||||||
|
mock_request.httprequest = Mock()
|
||||||
|
|
||||||
|
old_draft = self.env["sale.order"].create(
|
||||||
|
{
|
||||||
|
"partner_id": self.partner.id,
|
||||||
|
"group_order_id": self.group_order.id,
|
||||||
|
"state": "draft",
|
||||||
|
"pickup_date": date.today() - timedelta(days=7),
|
||||||
|
"order_line": [
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"product_id": self.product.id,
|
||||||
|
"product_uom_qty": 1,
|
||||||
|
"price_unit": 20.0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"order_id": self.group_order.id,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"product_id": self.product.id,
|
||||||
|
"quantity": 4,
|
||||||
|
"product_price": 20.0,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_delivery": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_request.httprequest.data = json.dumps(data).encode("utf-8")
|
||||||
|
|
||||||
|
response = self.controller.confirm_eskaera()
|
||||||
|
response_data = json.loads(response.data.decode("utf-8"))
|
||||||
|
|
||||||
|
self.assertTrue(response_data.get("success"))
|
||||||
|
self.assertNotEqual(response_data["sale_order_id"], old_draft.id)
|
||||||
|
|
||||||
|
old_draft.invalidate_recordset()
|
||||||
|
self.assertEqual(old_draft.state, "draft")
|
||||||
|
self.assertEqual(old_draft.order_line[0].product_uom_qty, 1)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue