Skip to content

Commit ae01108

Browse files
committed
[IMP] last_ordered_products: Bridge modules created
- Created 3 other bridge modules to ensure that it will work if any individual module is installed. - Updated main module, Now it has only helper methods and compute method.
1 parent 9e01f9e commit ae01108

28 files changed

+215
-233
lines changed

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"python.languageServer": "None"
3+
}

last_ordered_products/__manifest__.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
{
22
'name': "Last Ordered Products",
33
'version': '1.0',
4-
'depends': ['sale_management', 'purchase', 'stock'],
4+
'depends': ['product'],
55
'author': "Parthav Chodvadiya (PPCH)",
66
'category': '',
77
'description': """
88
Show last ordered products for customers in sale order and for vendors in purchase order
99
""",
1010
'data': [
11-
'data/last_ordered_products_tour.xml',
12-
'views/account_move_form.xml',
13-
'views/sale_order_form.xml',
14-
'views/purchase_order_form.xml',
1511
'views/product_views.xml',
1612
],
1713
'assets': {

last_ordered_products/data/last_ordered_products_tour.xml

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
from . import product_product
22
from . import product_template
3-
from . import sale_order
4-
from . import sale_order_line

last_ordered_products/models/product_product.py

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
from datetime import datetime
21
from odoo import api, fields, models
3-
from odoo.osv import expression
42

53

64
class ProductProduct(models.Model):
@@ -11,7 +9,7 @@ class ProductProduct(models.Model):
119

1210
@api.depends_context('order_id')
1311
def _compute_last_order_time(self):
14-
"""Compute the last order time for each product based on the latest sale or purchase."""
12+
'''Compute the last order time for each product based on the latest sale or purchase.'''
1513

1614
order_type = False
1715
if self.env.context.get('active_model') == 'sale.order.line':
@@ -24,10 +22,7 @@ def _compute_last_order_time(self):
2422
active_id = self.env.context.get('active_id')
2523
if active_id:
2624
order_type = self.env['account.journal'].browse(active_id).type
27-
partner_id = self.env.context.get('partner_id') or self.env.context.get('default_partner_id')
28-
else:
29-
partner_id = self.env.context.get('partner_id')
30-
order_type = self.env.context.get('order_type')
25+
partner_id = self.env.context.get('default_partner_id')
3126

3227
if not partner_id:
3328
for record in self:
@@ -99,34 +94,3 @@ def _get_last_purchased_products(self, partner_id):
9994
last_purchased_order_products[product_id] = last_date
10095

10196
return last_purchased_order_products
102-
103-
@api.model
104-
def name_search(self, name='', args=None, operator='ilike', limit=100):
105-
'''Modify product dropdown in sale order line to show last sold date'''
106-
107-
domain = args or []
108-
partner_id = self.env.context.get('partner_id')
109-
order_type = self.env.context.get('order_type')
110-
active_id = self.env.context.get('active_id')
111-
if not order_type and active_id:
112-
order_type = self.env['account.journal'].browse(active_id).type
113-
114-
if partner_id:
115-
last_ordered_products = {}
116-
if order_type == 'sale':
117-
last_ordered_products = self._get_last_sold_products(partner_id)
118-
elif order_type == 'purchase':
119-
last_ordered_products = self._get_last_purchased_products(partner_id)
120-
121-
product_ids = list(last_ordered_products.keys())
122-
123-
products = self.search_fetch(expression.AND([domain, [('id', 'in', product_ids)], [("name", operator, name)]]), ['display_name'], limit=limit)
124-
limit_rest = limit and limit - len(products)
125-
if limit_rest is None or limit_rest > 0:
126-
products |= self.search_fetch(expression.AND([domain, [('id', 'not in', product_ids)], [("name", operator, name)]]), ['display_name'], limit=limit_rest)
127-
128-
products = sorted(products, key=lambda p: last_ordered_products.get(p.id, datetime.min), reverse=True)
129-
130-
return [(product.id, product.display_name, self.env['product.template']._get_time_ago_string(last_ordered_products.get(product.id, False))) for product in products]
131-
132-
return super().name_search(name, args, operator, limit)

last_ordered_products/models/product_template.py

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
from datetime import datetime
21
from odoo import api, fields, models
3-
from odoo.osv import expression
42

53

64
class ProductTemplate(models.Model):
@@ -11,7 +9,7 @@ class ProductTemplate(models.Model):
119

1210
@api.depends_context('order_id')
1311
def _compute_last_order_time(self):
14-
"""Compute the last order time for each product based on the latest sale or purchase."""
12+
'''Compute the last order time for each product based on the latest sale or purchase.'''
1513

1614
partner_id = self.env.context.get('partner_id')
1715
order_type = self.env.context.get('order_type')
@@ -80,32 +78,3 @@ def _get_time_ago_string(self, last_date):
8078
return f"{diff.seconds // 60}m"
8179
else:
8280
return f"{diff.seconds}s"
83-
84-
@api.model
85-
def name_search(self, name='', args=None, operator='ilike', limit=100):
86-
'''Modify product dropdown in sale order line to show last sold date'''
87-
88-
domain = args or []
89-
partner_id = self.env.context.get('partner_id')
90-
order_type = self.env.context.get('order_type')
91-
active_id = self.env.context.get('active_id')
92-
if not order_type and active_id:
93-
order_type = self.env['account.journal'].browse(active_id).type
94-
95-
if partner_id:
96-
last_ordered_products = {}
97-
if order_type == 'sale':
98-
last_ordered_products = self._get_last_sold_products(partner_id)
99-
100-
product_ids = list(last_ordered_products.keys())
101-
102-
products = self.search_fetch(expression.AND([domain, [('id', 'in', product_ids)], [("name", operator, name)]]), ['display_name'], limit=limit)
103-
limit_rest = limit and limit - len(products)
104-
if limit_rest is None or limit_rest > 0:
105-
products |= self.search_fetch(expression.AND([domain, [('id', 'not in', product_ids)], [("name", operator, name)]]), ['display_name'], limit=limit_rest)
106-
107-
products = sorted(products, key=lambda p: p.last_order_time if p.last_order_time else datetime.min, reverse=True)
108-
109-
return [(product.id, product.display_name, product.last_date_str if product.last_date_str else False) for product in products]
110-
111-
return super().name_search(name, args, operator, limit)

last_ordered_products/static/src/core/autocomplete/autocomplete.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
<t t-inherit="web.AutoComplete" t-inherit-mode="extension">
44
<xpath expr="//t[@t-esc='option.label']" position="replace">
55
<t t-if="option.time_str">
6-
<div class="d-flex justify-content-between">
6+
<div class="d-flex justify-content-between text-success">
77
<span><t t-esc="option.label" /></span>
8-
<span><t t-esc="option.time_str" /></span>
8+
<span class="px-2"><t t-esc="option.time_str" /></span>
99
</div>
1010
</t>
1111
<t t-else="">

last_ordered_products/static/src/js/tours/last_ordered_products.js

Lines changed: 0 additions & 129 deletions
This file was deleted.

last_ordered_products/static/src/views/fields/product_label_section_and_note_field.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ patch(ProductLabelSectionAndNoteFieldAutocomplete.prototype, {
55
mapRecordToOption(result) {
66
let res = super.mapRecordToOption(result)
77
let time_str = result[2] ? result[2] : ""
8+
if (time_str === ""){
9+
return res;
10+
}
811
res['time_str'] = time_str
912
return res
1013
},

last_ordered_products/tests/test_last_ordered_products.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ def test_product_variant_in_sale_order(self):
146146
res_ids = [r[0] for r in res]
147147
self.assertEqual(self.test_product_1.id, res_ids[0])
148148
self.assertEqual(self.test_product_2.id, res_ids[1])
149-
149+
150150
def test_product_variant_in_purchase_order(self):
151151
po_context = {
152152
'partner_id': self.test_partner_1.id,

last_ordered_products/views/product_views.xml

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,8 @@
1010
<field name="default_code"/>
1111
</div>
1212
</xpath>
13-
14-
<xpath expr="//div[@name='o_kanban_qty_available']" position="replace">
15-
<div t-if="record.is_storable.raw_value"
16-
name="o_kanban_qty_available">
17-
<field name="qty_available"/> On Hand
18-
<field name="virtual_available" invisible="1"/>
19-
<span t-if="record.virtual_available.raw_value - record.qty_available.raw_value >= 0" class="text-success">
20-
<span>(+</span><t t-out="record.virtual_available.raw_value - record.qty_available.raw_value"/><span>)</span>
21-
</span>
22-
<span t-else="" class="text-danger">
23-
<span>(</span><t t-out="record.virtual_available.raw_value - record.qty_available.raw_value"/><span>)</span>
24-
</span>
25-
</div>
26-
</xpath>
27-
2813
<field name="product_template_attribute_value_ids" position="after">
29-
<span invisible="not last_date_str"><field name="last_date_str"/> ago</span>
14+
<span invisible="not last_date_str" class="text-success"><field name="last_date_str"/> ago</span>
3015
<span invisible="true"><field name="last_order_time"/></span>
3116
</field>
3217
</field>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
'name': "Last Ordered Products (Purchase)",
3+
'version': '1.0',
4+
'depends': ['last_ordered_products', 'purchase'],
5+
'author': "Parthav Chodvadiya (PPCH)",
6+
'category': '',
7+
'description': """
8+
Show last ordered products for vendors in purchase order
9+
""",
10+
'data': [
11+
'views/purchase_order_form.xml',
12+
'views/account_move_form.xml',
13+
],
14+
'license': 'LGPL-3',
15+
'auto_install': True,
16+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import product_product
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from datetime import datetime
2+
from odoo import api, models
3+
from odoo.osv import expression
4+
5+
6+
class ProductProduct(models.Model):
7+
_inherit = 'product.product'
8+
9+
@api.model
10+
def name_search(self, name='', args=None, operator='ilike', limit=100):
11+
'''Modify product dropdown in sale order line to show last sold date'''
12+
13+
domain = args or []
14+
partner_id = self.env.context.get('partner_id')
15+
order_type = self.env.context.get('order_type')
16+
active_id = self.env.context.get('active_id')
17+
if not order_type and active_id:
18+
order_type = self.env['account.journal'].browse(active_id).type
19+
20+
if partner_id:
21+
last_ordered_products = {}
22+
# if order_type == 'sale':
23+
# last_ordered_products = self._get_last_sold_products(partner_id)
24+
if order_type == 'purchase':
25+
last_ordered_products = self._get_last_purchased_products(partner_id)
26+
27+
product_ids = list(last_ordered_products.keys())
28+
29+
products = self.search_fetch(expression.AND([domain, [('id', 'in', product_ids)], [("name", operator, name)]]), ['display_name'], limit=limit)
30+
limit_rest = limit and limit - len(products)
31+
if limit_rest is None or limit_rest > 0:
32+
products |= self.search_fetch(expression.AND([domain, [('id', 'not in', product_ids)], [("name", operator, name)]]), ['display_name'], limit=limit_rest)
33+
34+
products = sorted(products, key=lambda p: last_ordered_products.get(p.id, datetime.min), reverse=True)
35+
36+
return [(product.id, product.display_name, self.env['product.template']._get_time_ago_string(last_ordered_products.get(product.id, False))) for product in products]
37+
38+
return super().name_search(name, args, operator, limit)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models

0 commit comments

Comments
 (0)