Odoo loop through a subscription line then set value to field - python

Hi am new to both python and Odoo development, I used the web interface for customization before. I was trying to create a class to
add a field to sale.subscription Model
subscription_tier = fields.Char(string='Subscription Tier',readonly=True)
which is working but the second part is not working
2. loop through subscription line to see if the customer has silver or gold subscription
then set it to the field subscription_tier
class subscription_tire_set(models.Model):
_inherit = 'sale.subscription'
subscription_tier = fields.Char(string='Subscription Tier',readonly=True)
#api.depends('recurring_invoice_line_ids.product_id')
def _compute_release_to_pay(self):
for n_subscription in self:
result = None
for n_subscription_line in n_subscription.recurring_invoice_line_ids:
if any(n_subscription_line.product_id) == 'gold':
result = 'gold'
break
else:
result = 'not'
subscription_tier = result
I probably am doing something horribly wrong
also a getting this massge when trying to open any customer in subscription
Something went wrong!
sale.subscription(10,).subscription_tier
Thank u for the help in advance.
What worked for me:
result = None
for n_subscription_line in n_subscription.recurring_invoice_line_ids:
if n_subscription_line.product_id.name == 'gold'
result = 'gold'
# break
else:
result
n_subscription.subscription_tier = result

It is not working because in the last line you are declaring a variable named subscription_tier and set its value to result, you should assign the result to subscription_tier field of the the n_subscription record:
#api.depends('recurring_invoice_line_ids.product_id')
def _compute_release_to_pay(self):
for n_subscription in self:
# Your code
n_subscription.subscription_tier = result
Edit:
any will return True or False and your expression any(n_subscription_line.product_id) == 'gold' will always be evaluated to False

Related

Python - UnboundLocalError: local variable "ID" referenced before assignment

Id, conf = recognizer.predict(gray[y:y+h,x:x+w]
def hour(cn):
for z in range(9,17):
if now.hour == z:
worksheet(cn, str(z)+":00")
def identify(number):
sht = gc.open("Test")
wks3 = sht.worksheet("NAMES")
b = wks3.acell('B'+str(number)).value
a = wks3.acell('A'+str(number)).value
if(Id == a and conf<65):
print(Id, conf)
Id = str(b)
Time = time.ctime()
hour(number)
elif(conf>64):
print(conf)
Id = "Unknown"
for m in range(2,100):
identify(m)
The above code is being used for facial recognition, I copied what I felt was necessary, it is not the entire code.
I'm trying create a function which I want to call back in a for loop
What am I doing wrong? I've been looking t this for 6 hours now, and anything I try doesn't seem to work.
I get a message back saying "UnboundLocalError: local variable 'Id' referenced before assignment"
It's impossible because I'm assigning with:
a = wks3.acell('A'+str(number)).value
So it grabs the ID number from the google spread sheet and checks if it is equaled to that, can someone tell me where I'm going wrong here?
def identify(number):
sht = gc.open("Test")
wks3 = sht.worksheet("NAMES")
b = wks3.acell('B'+str(number)).value
a = wks3.acell('A'+str(number)).value
#because you did, Id = ?
if(Id == a and conf<65):
print(Id, conf)
Id = str(b)
Time = time.ctime()
hour(number)
elif(conf>64):
print(conf)
Id = "Unknown"
Because you did, variable Id isn't passed as any parameter or global/local variable or as an argument to existing class.
If Id was parameter:
def identify(number,Id):
If Id was global variable:
def identify(number):
global Id
If Id was local variable:
def identify(number):
id = None # or some other data type
And if Id was argument from some class:
some_class.Id
In short you referenced Id before it was initialised. This is rookie mistake and there is some stuff where you can actually init a variable in if elif else statement but you need to trow a none of above logic of the rule.
if True: Id = 2; elif False: Id = 3; else: Id =0 #this is pseudocode, don't paste it in.
Also have in mind that next variable is also Unbound conf
EDIT:
Often to avoid this problem we write code like this:
def somefunction(parm1,parm2... ):
# global variables : description for variable stack is optional
global var1,var2 # if needed
#local variables
var3,var4 = None;
var5 = 'something else'
#in body functions : functions inside functions or just general program functions
def a(... ): return ...
#body : actually what function/program does.
# returning , finishing statement.

Loop through One2Many records Odoo 10

I am trying to loop through my One2Many records to avoid duplication.
class sales_target(models.Model):
_name = 'sales.target'
_description = 'Sales Target'
name = fields.Char(string='Name',required=True)
from_date = fields.Date(string='From Date',required=True)
to_date = fields.Date(string='To Date',required=True)
sales_team = fields.Many2one('crm.team',required=True)
sales_record_ids = fields.One2many('sales.target.record','sales_target_rec_id',string='Sales Record')
#api.one
def check_duplication(self,result):
count = 0
if self.sales_record_ids:
for record in self.sales_record_ids:
if result.id == record.sales_person_p_id:
count = 1
if count == 0:
self.write({'sales_record_ids':[(0,0,{'sales_person':result.name})]})
#api.one
def get_sales_person(self):
for res in self.sales_team.member_ids:
self.check_duplication(res)
The other class is as:
class sales_target_record(models.Model):
_name = 'sales.target.record'
sales_target_rec_id = fields.Many2one("sales.target")
sales_person = fields.Char(string='Sales Person',readonly=True,required=True)
sales_person_p_id = fields.Char(compute='get_value',store=True)
#api.onchange('sales_person')
#api.depends('sales_person')
def get_value(self):
res = self.env['res.partner'].search([('name','=',self.sales_person)])
self.sales_person_p_id = res[0].id
Now when I am hitting the button i still have duplicate records. However I tried to compare with name and things work good but I cannot compare with names since its not correct because names can be same but id cannot. That function was as:
#api.one
def check_duplication(self,result):
count = 0
if self.sales_record_ids:
for record in self.sales_record_ids:
if result.name == record.sales_person:
count = 1
if count == 0:
self.write({'sales_record_ids':[(0,0,{'sales_person':result.name})]})
Hope for guidance on this.
Can you try like this
#api.multi
def check_duplication(self,result):
if self.sales_record_ids:
for record in self.sales_record_ids:
if not result.name == record.sales_person:
self.write({'sales_record_ids':[(0,0,{'sales_person':result.name})]})
Concluding from the fact that for name it works properly, something might be wrong with your if condition.
sales_person_p_id is of type char, however you seem to compare it with an integer: result.id.
Have you made sure that both objects in your if condition are of the same type?
Try to make sales_person_p_id an integer field (e.g. via sales_person_p_id = fields.Integer(compute='get_value',store=True) or do some kind of type casting before comparing the objects.

Python Flask SQLalchemy query filter by boolean values ignore False

In my database I have rooms, these rooms have multiple boolean values like has_tv.
A user can search for a room in a city, he will be redirected to the result page, where he finds all rooms in the searched city.
Now there is a filter function which filters the current result set, by rooms which for example have a tv. For this the user checks a checkbox with the value has_tv
I managed to make it work, but it does not ignore False values. this means if a user check has_tv it will be true but all the other boolean values will be false (because they are unchecked). So this will show me only results where has_tv is true and all others false, I need to see results where has_tv is true and others are irrelevant, some can be false and true.
Thats what I use atm:
if form.validate_on_submit():
all_rooms_in_city = Zimmer.query.filter(or_(Zimmer.haustiere_erlaubt.is_(form.haustiere_erlaubt.data), Zimmer.bettwaesche_wird_gestellt.is_(form.bettwaesche_wird_gestellt.data))).all()
else:
all_rooms_in_city = Zimmer.query.order_by(desc("stadt")).all()
That are all values which can be checked (there are a lot, so hardcoding all possibilites is impossible):
class FilterZimmerForm(Form):
haustiere_erlaubt = BooleanField("Haustiere")
bettwaesche_wird_gestellt = BooleanField("Bettwaesche")
grill_vorhanden = BooleanField("grill_vorhanden")
safe_vorhanden = BooleanField("safe_vorhanden")
kuehlschrank_vorhanden = BooleanField("kuehlschrank_vorhanden")
rauchen_erlaubt = BooleanField("rauchen_erlaubt")
parkplatz_vorhanden = BooleanField("parkplatz_vorhanden")
kochmoeglichkeit_vorhanden = BooleanField("kochmoeglichkeit_vorhanden")
restaurant_im_haus_vorhanden = BooleanField("restaurant_im_haus_vorhanden")
handtuecher_werden_gestellt = BooleanField("handtuecher_werden_gestellt")
tv_vorhanden = BooleanField("tv_vorhanden")
waschmoeglichkeit_vorhanden = BooleanField("waschmoeglichkeit_vorhanden")
wlan_vorhanden = BooleanField("wlan_vorhanden")
Of course later if lets say two of them are checked, it shall show all rooms where the two checked values are true and all others shall not matter!
Here is a screenshot of the website where the function is needed:
EDIT:
It seems I found a solution, have tested a few times and it seems to work as intended but it does not feel like it is best practise:
if form.validate_on_submit():
filter_result = []
if form.haustiere_erlaubt.data == True:
filter_result.append(Zimmer.haustiere_erlaubt.is_(True))
if form.bettwaesche_wird_gestellt.data == True:
filter_result.append(Zimmer.bettwaesche_wird_gestellt.is_(True))
if form.grill_vorhanden.data == True:
filter_result.append(Zimmer.grill_vorhanden.is_(True))
if form.safe_vorhanden.data == True:
filter_result.append(Zimmer.safe_vorhanden.is_(True))
if form.kuehlschrank_vorhanden.data == True:
filter_result.append(Zimmer.kuehlschrank_vorhanden.is_(True))
if form.rauchen_erlaubt.data == True:
filter_result.append(Zimmer.rauchen_erlaubt.is_(True))
if form.parkplatz_vorhanden.data == True:
filter_result.append(Zimmer.parkplatz_vorhanden.is_(True))
if form.kochmoeglichkeit_vorhanden.data == True:
filter_result.append(Zimmer.kochmoeglichkeit_vorhanden.is_(True))
if form.restaurant_im_haus_vorhanden.data == True:
filter_result.append(Zimmer.restaurant_im_haus_vorhanden.is_(True))
if form.handtuecher_werden_gestellt.data == True:
filter_result.append(Zimmer.handtuecher_werden_gestellt.is_(True))
if form.tv_vorhanden.data == True:
filter_result.append(Zimmer.tv_vorhanden.is_(True))
if form.waschmoeglichkeit_vorhanden.data == True:
filter_result.append(Zimmer.waschmoeglichkeit_vorhanden.is_(True))
if form.wlan_vorhanden.data == True:
filter_result.append(Zimmer.wlan_vorhanden.is_(True))
for item in filter_result:
all_rooms_in_city = Zimmer.query.filter(item).all()
else:
all_rooms_in_city = Zimmer.query.order_by(desc("stadt")).all()
First if you want to avoid hardcoding you need some way to get programatically which attributes you want to use to filter and what the appropriate field in the form is called. I guess you could scan the Zimmer class and get the name of all boolean attributes, but for now I simply asume a list of strings with the name of the attribute where in the form the name is the same:
filter_list = ["haustiere_erlaubt", ...]
Then you need to add the filters to the query only if the form is true. So:
if form.validate_on_submit():
query = Zimmer.query
for filter_name in filter_list:
if getattr(form, filter_name).data:
query = query.filter(getattr(Zimmer, filter_name).is_(True)))
all_rooms_in_city = query.all()
I guess you could also build a dictionary of the appropriate filters and use filter_by:
filter_dict = { filter_name: True for filter_name in filter_list if getattr(form, filter_name).data }
all_rooms_in_city = Zimmer.query.filter_by(**filter_dict).all()
In your code you are redefining all_rooms_in_the_city in the for loop for each item, so only the last filter will actually apply.

django: using Q to filter taking into account blank choice scenario

There are 2 criteria in the form entered and submitted by user to filter the database. Because user might leave these two blank, so I made some scenarios. If it is left blank, then in database no need to filter by this constraint.
The default value is "None".
This is the post that I referenced: django conditionally filtering objects
I tried 2 ways , neither works, hope someone could help:
First way
if criteria_1 is None and criteria_2 !=None: return Q(criteria_2=criteria_2)
elif criteria_2 is None and criteria_1 !=None: return Q(criteria_1=criteria_1)
elif criteria_1 !=None and criteria_2 !=None: return Q(criteria_2=criteria_2,criteria_1=criteria_1)
elif criteria_1 is None and criteria_2 is None: return Q()
else: return Q()
queryset=XXX.objects.filter(Q,date_new__range=[start_date,end_date])
Second way
only_criteria_1_none=Q(criteria_1__isnull=True)
only_criteria_2_none=Q(criteria_2__isnull=True)
both_selected=Q(criteria_1=criteria_1,criteria_2=criteria_2)
both_none=Q(criteria_1__isnull=True,criteria_2__isnull=True)
queryset=XXX.objects.filter(only_criteria_1_none|only_criteria_2_none|both_selected|both_none)
Method 3 ---EDIT
forms.py
iquery = XXX.objects.values_list('region', flat=True).distinct()
iquery_choices = [('', '')] + [(region,region) for region in iquery]
region = forms.ChoiceField(choices=iquery_choices,required=False,widget=forms.Select())
-----same for country------the default value is ""
views.py
if country =="" and region !="":
queryset=XXX.objects.filter(country,date_new__range=[start_date,end_date])
if region ="" and country !="":
queryset=XXX.objects.filter(region,date_new__range=[start_date,end_date])
。。。。。。。。。。
Thanks in advance.
I don't quite understand why you need to use Q at all, django's query sets are done so lazily so it isn't ran until you actually need the results..
queryset = Foo.objects.filter(base_query_stuff)
if bar_criteria:
queryset = queryset.filter(bar_stuff)
if cheese_criteria:
queryset = queryset.filter(cheese_stuff)
return queryset
This makes your query look much easier to understand.

how to get entities which don't have certain attribute in datastore

I'm trying to make an appraisal system
This is my class
class Goal(db.Expando):
GID = db.IntegerProperty(required=True)
description = db.TextProperty(required=True)
time = db.FloatProperty(required=True)
weight = db.IntegerProperty(required=True)
Emp = db.UserProperty(auto_current_user=True)
Status = db.BooleanProperty(default=False)
Following things are given by employee,
class SubmitGoal(webapp.RequestHandler):
def post(self):
dtw = simplejson.loads(self.request.body)
try:
maxid = Goal.all().order("-GID").get().GID + 1
except:
maxid = 1
try:
g = Goal(GID=maxid, description=dtw[0], time=float(dtw[1]), weight=int(dtw[2]))
g.put()
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
Now, here Manager checks the goals and approve it or not.. if approved then status will be stored as true in datastore else false
idsta = simplejson.loads(self.request.body)
try:
g = db.Query(Goal).filter("GID =", int(idsta[0])).get()
if g:
if idsta[1]:
g.Status=True
try:
del g.Comments
except:
None
else:
g.Status=False
g.Comments=idsta[2]
db.put(g)
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
Now, this is where im stuck..."filter('status=',True)".. this is returning all the entities which has status true.. means which are approved.. i want those entities which are approved AND which have not been assessed by employee yet..
def get(self):
t = []
for g in Goal.all().filter("Status = ",True):
t.append([g.GID, g.description, g.time, g.weight, g.Emp])
self.response.out.write(simplejson.dumps(t))
def post(self):
idasm = simplejson.loads(self.request.body)
try:
g = db.Query(Goal).filter("GID =", int(idasm[0])).get()
if g:
g.AsmEmp=idasm[1]
db.put(g)
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
How am I supposed to do this? as I know that if I add another filter like "filter('AsmEmp =', not None)" this will only return those entities which have the AsmEmp attribute what I need is vice versa.
You explicitly can't do this. As the documentation states:
It is not possible to query for entities that are missing a given property.
Instead, create a property for is_assessed which defaults to False, and query on that.
could you not simply add another field for when employee_assessed = db.user...
and only populate this at the time when it is assessed?
The records do not lack the attribute in the datastore, it's simply set to None. You can query for those records with Goal.all().filter('status =', True).filter('AsmEmp =', None).
A few incidental suggestions about your code:
'Status' is a rather unintuitive name for a boolean.
It's generally good Python style to begin properties and attributes with a lower-case letter.
You shouldn't iterate over a query directly. This fetches results in batches, and is much less efficient than doing an explicit fetch. Instead, fetch the number of results you need with .fetch(n).
A try/except with no exception class specified and no action taken when an exception occurs is a very bad idea, and can mask a wide variety of issues.
Edit: I didn't notice that you were using an Expando - in which case #Daniel's answer is correct. There doesn't seem to be any good reason to use Expando here, though. Adding the property to the model (and updating existing entities) would be the easiest solution here.

Categories