How to Many2Many field relationship and map that in Invoice in odoo - mapping

how we suppose to do that, is it possible to use Many2many fields or we can create another model with vehicle_id and partner_id.
how create and edit vehicle_number fetch automatically cutomer_id many2many field when vehicle already existing vehicle number with different partner_id
class VehicleMaster(models.Model):
_name = "vehicle.master.model"
_description = "Vehicle Master"
_rec_name = 'x_vehicle_number_id'
x_brand_id = fields.Many2one('vehicle.brand.model', string="Brand Name",ondelete='restrict')
x_model_id = fields.Many2one('vehicle.model.model', string="Model Name",domain=" [('brand_id','=',x_brand_id)]",ondelete='restrict')
x_vehicle_number_id = fields.Char(string="Vehicle Number", required=True, tracking=True,ondelete='restrict')
x_customer_id = fields.Many2many('res.partner',string="Customers",required=True,tracking=True)
class CustomInvoice(models.Model):
_inherit = "account.move"
vehicle_number = fields.Many2one('vehicle.master.model',string='Vehicle number',domain="[('x_customer_id','=',partner_id)]")
I try to used vehicle.master.model in field many2many vehicle_number and relation with invoice module when create vehicle_number in invoice to not fetch automatically when vehicle_number is already created with different partner_id.

Related

grails - org.hibernate.QueryException (could not resolve property)

I'm trying to get the list of a specific rental from the current user.
Code in controller:
def index() {
if (isLoggedIn()) {
String username = getPrincipal().username
def accountInstance = Account.findByUsername(username)
def rentalInstanceList = Rental.findAll("from Rental as r where r.account_id=:accountid", [accountid: accountInstance.id])
}
}
account_id is a foreign key.
After running I get the error:
could not resolve property: account_id of: ers.Rental
What am I doing wrong?
Generally, in HQL you have to use the field names as defined in your domain classes. So, your query should look like:
def list = Rental.findAll("from Rental where accountId=:accountid", [accountid: accountInstance.id])
or
def list = Rental.findAllByAccount accountInstance
or even
def list = Rental.findAllByAccount getPrincipal()
if the return type of getPrincipal() has the id field.
findAll is not limited to instances of the calling class so I use executeQuery instead. https://stackoverflow.com/a/8916483/5011228

findAllWhere and List fetch

So I have the domain class as follows:
class Enrollment {
Course course
Date date
User user
static constraints = {
}
}
In my controller, I have this action :
def persons = Enrollment.list(fetch :[user : "a"])
render persons
I am trying to fetch only a user named "a" and its corresponding map. But it displays all..I tried FindAllWhere but throws an error
No such property: user for class: tester.EnrollmentController
I am assuming that the User class has a name property.
What about:
def user = User.findByName("a")
def persons = user ? Enrollment.findAllByUser(user) : []
Assuming here that you can find a unique user (name probably isn't unique enough), otherwise I would do something like:
def persons = Enrollment.createCriteria().list{
user {
eq('name', "a")
}
}

Sorting Model with Specific Data

I would like to sort data of my model base on a specific order.
Model: Grade
Table Column: category, value
values of category: Prelim, Midterm, Semi-finals, Finals
How do I sort the table Grade base on it's category with value of "Prelim, Midterm, Semi-Finals, Finals"?
If you dont want to replace them by numbers in the table as suggested by #titibouboul . You can just do.
class Grade
CATEGORY_IN_ORDER = ["Prelim", "Midterm", "Semi-Finals", "Finals"]
scope :ordered_by_category, lambda {"order(FIELD(category,#{CATEGORY_IN_ORDER.join(',')}))"}
end
then anywhere you can use this scope as:
Grade.ordered_by_category.where(YOUR_CRITERIA)
if you dont want to define scopes:
Grade.where(YOUR_CRITERIA).order("FIELD(category,#{CATEGORY_IN_ORDER.join(',')})")
More about order by FIELD syntax here:
http://www.electrictoolbox.com/mysql-order-specific-field-values/
You should replace them by a number :
1 = Prelim
2 = Midterm
3 = Semi-finals
4 = Finals
and then sort them in the model like this :
class Grade
...
default_scope -> { order('category ASC') }
...
end

Field Validation in Admin when field are dependent on other fields

How can i apply validation in admin on various fields when they are dependent on each other ?
e.g. Let say in i have a Field A(BooleanField) and Field B (CharField) what i want to do is if in admin user select the Field A(checkbox) and does not enter anything in Field B
and if he tries to save ,it should throw an error like a normal blank=False gives. So how can i do this kind of validation in admin .
E.g Use Case
I have a table having the following structure :-
INTERVIEW_TYPES = (
('default', 'None'),
('Paired Visit','Paired Visit'),
('Time Series', 'Time Series'),
),
class Interview(models.Model):
ic_number = models.CharField(verbose_name ="Visit Configuration Number",max_length=20,unique=True,null =True,blank=True)
ic_description = models.TextField(verbose_name ="Visit Configuration Description",null = True,blank=True)
title = models.CharField(verbose_name ="Visit Configuration Title",max_length=80,unique=True)
starting_section = models.ForeignKey(Section)
interview_type = models.CharField(verbose_name = "Mapped Visit",choices=CHOICES.INTERVIEW_TYPES, max_length=80, default="Time Series")
select_rating = models.CharField(choices=CHOICES.QUESTION_RATING, max_length=80, default="Select Rating")
view_notes = models.CharField(choices=CHOICES.VIEW_NOTES, max_length=80, default="Display Notes")
revisit = models.BooleanField(default=False)
.....and so on ......
class Meta:
verbose_name = 'Visit Configuration'
verbose_name_plural = 'Visit Configurations'
# ordering = ('rpn_number',)
def __unicode__(self):
return self.title
Its admin.py
class InterviewAdmin(admin.ModelAdmin):
list_display = ('id','title', 'starting_section','ic_number','show_prior_responses')
raw_id_fields = ('starting_section',)
admin.site.register(Interview, InterviewAdmin)
In admin , If i select the checkbox of revisit and in the field interview_type(which will show a dropdown having choices None,Paired Visit , Time Series) if a User has selected None from that dropdown and then press save button it should throw me an error like a normal blank=False shows, saying "This field is required"
How can i do this kind validation where fields are dependent on each other ?
Please Ignore syntax error is any .
Thanks
I got confused in response_change and overriding clean method finally this is what i did
override clean method by making a model form in admin.py
class InterviewAdminForm(forms.ModelForm):
class Meta:
model = Interview
def clean(self, *args, **kwargs):
cleaned_data = super(InterviewAdminForm, self).clean(*args, **kwargs)
if self.cleaned_data['interview_type'] == "default" \
and self.cleaned_data['Revisit'] == True:
raise forms.ValidationError({'interview_type': ["error message",]})
return cleaned_data
class InterviewAdmin(admin.ModelAdmin):
# call the form for Validation
form = InterviewAdminForm
#....and so on ....

Django Admin: Many-to-Many listbox doesn't show up with a through parameter

I have the following models:
class Message(models.Model):
date = models.DateTimeField()
user = models.ForeignKey(User)
thread = models.ForeignKey('self', blank=True, null=True)
...
class Forum(models.Model):
name = models.CharField(max_length=24)
messages = models.ManyToManyField(Message, through="Message_forum", blank=True, null=True)
...
class Message_forum(models.Model):
message = models.ForeignKey(Message)
forum = models.ForeignKey(Forum)
status = models.IntegerField()
position = models.IntegerField(blank=True, null=True)
tags = models.ManyToManyField(Tag, blank=True, null=True)
In the admin site, when I go to add/change a forum, I don't see the messages listbox as you'd expect. However, it shows up if I remove the 'through' parameter in the ManyToManyField declaration. What's up with that? I've registered all three models (plus Tag) to the admin site in admin.py.
TIA
Documentation says:
When you specify an intermediary model using the through argument to a
ManyToManyField, the admin will not display a widget by default.
But it's probably possible to display M2M fields in the admin change view even if the through attribute is defined.
class ForumAdminForm(forms.ModelForm):
mm = forms.ModelMultipleChoiceField(
queryset=models.Message.objects.all(),
widget=FilteredSelectMultiple(_('ss'), False, attrs={'rows':'10'}))
def __init__(self, *args, **kwargs):
if 'instance' in kwargs:
initial = kwargs.setdefault('initial', {})
initial['mm'] = [t.service.pk for t in kwargs['instance'].message_forum_set.all()]
forms.ModelForm.__init__(self, *args, **kwargs)
def save(self, commit=True):
instance = forms.ModelForm.save(self, commit)
old_save_m2m = self.save_m2m
def save_m2m():
old_save_m2m()
messages = [s for s in self.cleaned_data['ss']]
for mf in instance.message_forum_set.all():
if mf.service not in messages:
mf.delete()
else:
messages.remove(mf.service)
for message in messages:
Message_forum.objects.create(message=message, forum=instance)
self.save_m2m = save_m2m
return instance
class Meta:
model = models.Forum
class ForumAdmin(admin.ModelAdmin):
form = ForumAdminForm
Take a look at the official documentation:
I learned a lot from #Fedor's answer, but some comments and cleanup may be still beneficial.
class ForumAdminForm(forms.ModelForm):
messages = forms.ModelMultipleChoiceField(
queryset=Message.objects.all(),
widget=FilteredSelectMultiple('Message', False))
# Technically, you don't need to manually set initial here for ForumAdminForm
# However, you NEED to do the following for MessageAdminForm
def __init__(self, *args, **kwargs):
if 'instance' in kwargs:
# a record is being changed. building initial
initial = kwargs.setdefault('initial', {})
initial['messages'] = [t.message.pk for t in kwargs['instance'].message_forum_set.all()]
super(ForumAdminForm, self).__init__(*args, **kwargs)
def save(self, commit=True):
if not self.is_valid():
raise HttpResponseForbidden
instance = super(ForumAdminForm, self).save(self, commit)
def save_m2m_with_through():
messages = [t for t in self.cleaned_data['messages']
old_memberships = instance.message_forum_set.all()
for old in old_memberships:
if old.message not in messages:
# and old membership is cleaned by the user
old.delete()
for message in [x for x in messages not in map(lambda x: x.message, old_memberships)]:
membership = Member_forum(message=messsage, forum=instance)
# You may have to initialize status, position and tag for your need
membership.save()
if commit:
save_m2m_with_through()
else:
self.save_m2m = save_m2m_with_through
return instance
class Meta:
model = Forum
fields = {'name', 'messages')
There's one caveat: if you have another many-to-many relationship in the models (that is without through), super(ForumAdminForm, self).save(self, commit) will set self.save_m2m in case commit is False. However, calling this would cause an error, because this function also tries to save the many-to-many with through as well. You may need to save all other many-to-many relationship manually, or catch the exception, or else.
Django admin nicely support many-to-many intermediary models that using the through argument .
For example you have these Person and Group models with intermediate Membership model:
models.py
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Now in admin.py file ,
Define an inline class for the intermediate Membership model:
#admin.register(Membership)
class MembershipInline(admin.TabularInline):
model = Membership
extra = 1
And use them in admin views of models:
#admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
#admin.register(Group)
class GroupAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
More info in official docs:
Models,
Admin

Resources