How to correctly Update Odoo / Openerp website context? - python

I trying to adapt the module https://www.odoo.com/apps/modules/9.0/website_sale_product_brand/ to have a select box on the shop page, and filter by brand and category, and not to have to go to a diferent page and select the brand.
In that module they update context with the brand_id so the sale_product_domain function could append to the domain. In the module, it filter it as a charm, but in my code not....
Any guest?
When I debug self.env.context in the sale_product_domain function not brand if append, but in the website_sale_product_brand yes, with the exactly same code
controller.py
class WebsiteSale(website_sale):
#http.route(['/shop',
'/shop/page/<int:page>',
'/shop/category/<model("product.public.category"):category>',
'/shop/category/<model("product.public.category"):category>/page/<int:page>',
],type='http',auth='public',website=True)
def shop(self, page=0, category=None, search='', brand=None, **post):
# Update context to modify sale_product_domain function from website model
if brand:
context = dict(request.env.context)
context.setdefault('brand', int(brand))
request.env.context = context
result = super(WebsiteSale, self).shop(page=page, category=category,
brand=brand, search=search,
**post)
#append brand to keep so links mantain brand filter
keep = QueryURL('/shop',
brand=brand,
category=category and int(category),
search=search,)
#attrib=attrib_list TODO
#Update result
result.qcontext['keep'] = keep
result.qcontext['brands'] = http.request.env['product.brand'].search([]) #use to populate template select box
result.qcontext['sel_brand_id'] = brand #use to select the selected brand on brand select box
return result
models.py
class WebSite(models.Model):
_inherit = 'website'
#api.multi
def sale_product_domain(self):
domain = super(WebSite, self).sale_product_domain()
print self.env.context
if 'brand' in self.env.context:
domain.append(
('product_brand_id', '=', self.env.context['brand']))
return domain

ctx = dict (request.context)
ctx.update ({'bin_size': True})
request.context = ctx
That's it!

Related

Search for similar products quoted by Different vendors and get cheapest in order_line

I am using Odoo and python.
I am trying to search for similar products in "purchase.order.line" quoted by different vendors and then get the cheapest vendor.
Below are the pics:
Vendor 1
Vendor 2
The upper section is class PurchaseOrder
and where there is Products and price is class PurchaseOrderLine
The below code is what I was trying to do for the cheapest product in the second class "purchase.order.line".
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
supplier_prequalification_id = fields.Many2one("supplier.prequalification", string="Supplier Prequalification")
class PurchaseOrderLine(models.Model):
_inherit = 'purchase.order.line'
supplier_prequalification_id = fields.Many2one("supplier.prequalification", related="order_id.supplier_prequalification_id", string="Supplier Prequalification", store=True)
cheapest = fields.Boolean(string="Cheapest Price", compute="compute_cheapest")
vendor = fields.Many2one("res.partner", string="Vendor", related="partner_id", store=True)
count = fields.Float()
def compute_cheapest(self):
for rec in self:
partner = rec.env['purchase.order'].search([('partner_id', '=', rec.partner_id.id)])
for each_partner in partner:
line = each_partner.order_line
for item in line:
if item.product_id.__________:
item.count = min(item.price_unit)
if item.count:
item.write({'cheapest': True})
else:
item.write({'cheapest': False})
The place where I have put the dash is where I am stuck. How can I search in every vendor's oder_line and find similar products quoted by them. The cheapest price for that product I can store it on count float and then if count I do the last code of selecting boolean true.
Doesn't have to store cheapest on count. We can just say cheapest write boolean.
....
item.write({'cheapest': True})
else:
item.write({'cheapest': False})
NB: I have set field quality to Boolean that's why in the end I am writting "True" or "False"
Or is there a better way to do it
Any help will be appreciated

Perform CRUD operations on product class?

I'm a newbie to Django-oscar and I'm trying to develop a simple CRUD operation on Product. I've forked the catalogue app and created a views.py file
I fired the query Product.objects.create(title='Hello') and a product does get created with the following error:
AttributeError: 'NoneType' object has no attribute 'attributes'
product_title = 'MyPhone'
upc=987654321
product_class = ProductClass.objects.get_or_create(name='Phone')
def createProduct(request):
line1
product.name = product_title
product.product_class = product_class
product.upc=upc
product.save()
When I put product=Product() in line1 I get the following error:
Cannot assign "(, False)": "Product.product_class" must be a "ProductClass" instance.
When I put product = Product.objects.create(upc=upc) I get the following error :
NoneType' object has no attribute 'attributes'
Anyone guide me on how to write a simple create operation?
ProductClass, Product, Category, ProductCategory = get_classes(
'catalogue.models', ('ProductClass', 'Product', 'Category',
'ProductCategory'))
create_from_breadcrumbs = get_class('catalogue.categories', 'create_from_breadcrumbs')
def _create_item(product_class, category_str, upc, title,
description, stats):
# Ignore any entries that are NULL
if description == 'NULL':
description = ''
# Create item class and item
product_class, __ = ProductClass.objects.get_or_create(name=product_class)
try:
item = Product.objects.get(upc=upc)
stats['updated_items'] += 1
except Product.DoesNotExist:
item = Product()
stats['new_items'] += 1
item.upc = upc
item.title = title
item.description = description
item.product_class = product_class
item.save()
# Category
cat = create_from_breadcrumbs(category_str)
ProductCategory.objects.update_or_create(product=item, category=cat)
return item
This is the actual way to manipulate products with provided information to the function in django oscar. For better design decisions you need to follow this convention. Modify it as you want. Let me know if you want more help. Thank you.

Odoo: How to create many records in Transient.Model?

This code only creates one record. What is wrong?
class PartnerTagCreate(models.TransientModel):
""" Choose tags to be added to partner."""
_name = 'partner.tags.create'
_description = __doc__
market_id = fields.Many2one('partner.tags', string='Market Tag')
application_id = fields.Many2one('partner.tags', string='Application Tag')
partner_id = fields.Integer()
#api.multi
def create_contact_tag(self):
for record in self.env['sale.order.line'].browse(self._context.get('active_ids', [])):
vals = {}
vals['partner_id'] = record.order_partner_id
self.write(vals)
return True
I need this function to create one record for each order_partner_id I selected before opening the wizard...
How to achieve that?
Here my new code (function) ...
def create_contact_tag(self):
sale_order_line_ids = self.env['sale.order.line'].browse(self._context.get('active_ids', []))
for partner in sale_order_line_ids:
values = {}
values['partner_id'] = partner.order_partner_id
self.create(values)
return {}
This creates one record for marketing_id and/or application_id and dedicated records for each partner_id in the record.
You use the 'create' method to create new records; this is the same for TransientModel as for the persistent Model.
So, replace
self.write(vals)
by
self.create(vals)
and you should be fine.

How to edit flask-admin to support multi tenancy?

I'm using Flask-peewee, looking for a way to give permission to admins, I'd like to make a multi tenancy admin dashboard.
I have made for displaying deals:
class DealsAdmin(ModelAdmin):
columns = ('deal_name', 'deal_desc', 'created_on')
exclude = ('created_on','merchand_id')
def get_query(self):
loggedin_username=auth.get_logged_in_user()
merchant=Merchant.select().where(Merchant.id == loggedin_username).get()
return self.model.select().where(self.model.merchand_id == loggedin_username)
So now I'd like to keep the loggedinuserid for Merchant id when they want to edit forms.
*Edit on image text: Merchant_id must be the auth.loggedinid as default
Remove the field from being displayed in the form, then hook into on_model_change:
class MyDealModelView(ModelView):
form_excluded_columns = ('merchant_id',)
def on_model_change(form, model, is_created):
model.merchant_id = login.current_user.merchant_id;
http://flask-admin.readthedocs.org/en/latest/api/mod_model/#flask.ext.admin.model.BaseModelView.on_model_change

Autocomplete-Light channel name conflict

I have a Django project containing two apps, Expenses and Sales which both have models named Item. I'm using django-autocomplete-light to ease the selection of Item. This works for either Expenses or Sales depending on which channel I register last but the other one wrongly shows the same Items.
autocomplete_light_registry.py
from sales.models import Item as SalesItem
from expenses.models import Item as ExpenseItem
class ExpenseChannel(autocomplete_light.ChannelBase):
def query_filter(self, results):
q = self.request.GET.get('q', None)
if q:
if results.model == ExpenseItem:
results = results.filter(
Q(name__icontains=q)
return results
class SalesChannel(autocomplete_light.ChannelBase):
def query_filter(self, results):
q = self.request.GET.get('q', None)
if q:
if results.model == SalesItem:
results = results.filter(
Q(name__icontains=q)
return results
autocomplete_light.register(ExpenseItem, ExpenseChannel, placeholder='Select an item (e)')
autocomplete_light.register(SalesItem, SalesChannel, placeholder='Select an item (s)')
admin.py
For sales app, similar in expenses
import autocomplete_light
class SalesItemInline(admin.TabularInline):
fields = ('item', )
model = SalesItem
form = autocomplete_light.modelform_factory(SalesItem)
Checking the log when using the autocomplete fields i see the same url being fetched from both views.
"GET /autocomplete/channel/ItemChannel/?q= HTTP/1.1" 200 1416
How do I configure this so list of sales.Item is returned in Admin Sales view and list of expenses.Item is returned in Admin Expenses view?
What's happening is that the channel class is generated in most cases and it's name is generated too. However, you can avoid channel class generation and channel name generation (hopefully, or this would really suck).
From the registry documentation:
Three cases are possible:
specify model class and ModelNameChannel will be generated extending ChannelBase, with attribute model=model
specify a model and a channel class that does not have a model attribute, and a ModelNameChannel will be generated, with attribute
model=model
specify a channel class with a model attribute, and the channel is directly registered
The solution to avoid channel class generation is to be in the third case: register a model and channel class with a model attribute.
autocomplete_light_registry.py
from sales.models import Item as SalesItem
from expenses.models import Item as ExpenseItem
class ExpenseChannel(autocomplete_light.ChannelBase):
placeholder='Select an item (e)'
model = ExpenseItem
def query_filter(self, results):
q = self.request.GET.get('q', None)
if q:
if results.model == ExpenseItem:
results = results.filter(
Q(name__icontains=q)
return results
class SalesChannel(autocomplete_light.ChannelBase):
model = SalesItem
placeholder = 'Select an item (s)'
def query_filter(self, results):
q = self.request.GET.get('q', None)
if q:
if results.model == SalesItem:
results = results.filter(
Q(name__icontains=q)
return results
autocomplete_light.register(ExpenseChannel)
autocomplete_light.register(SalesChannel)
That would work up to 0.7rc2.
Starting 0.7rc3 (to be released when the pending issue is closed), register() has a new keyword argument, channel_name, which you may use.
But you should be careful with your code, it seems like the query_filter() implementation from your classes is the same as the default implementation ...

Categories