ODOO 12 : show field of model “purchase.order” in form view of “account.invoice” - field

I added commission field in purchase order model and i want to show it in account invoice when i click on "create bill". below is my code but it doesn't work, I hope somebody can help me. Many thanks in advance.
class ConfirmComm(models.Model):
_inherit = "purchase.order"
commission = fields.Float(string='Commission', required='true', default=0)
#api.multi
def action_view_invoice(self, cr, uid, order, context=None):
if context is None:
context = {}
journal_id = self.pool['account.invoice'].default_get(cr, uid, ['journal_id'], context=context)['journal_id']
if not journal_id:
raise UserError(_('Error!'),
_('Please define purchase journal for this company: "%s" (id:%d).') % (
order.company_id.name, order.company_id.id))
invoice_vals = {
'name': order.partner_ref or '',
'origin': order.name,
# 'type': 'in_invoice',
# Sale order id as source_id
# 'source_id': order.id,
'reference': order.partner_ref or order.name,
'account_id': order.partner_invoice_id.property_account_receivable.id,
'partner_id': order.partner_invoice_id.id,
'journal_id': journal_id,
'commission': order.commission,
# 'invoice_line': [(6, 0, lines)],
'currency_id': order.pricelist_id.currency_id.id,
# 'comment': order.note,
'payment_term_id': order.payment_term_id or False,
'fiscal_position_id': order.fiscal_position_id,
'date_invoice': context.get('date_invoice', False),
'company_id': order.company_id.id,
'user_id': order.user_id and order.user_id.id or False,
}
_logger.info("KTR this is commissionTest $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ %d", order.commission)
invoice_vals.update(self._inv_get(cr, uid, order, context=context))
return invoice_vals

You need to add this field to model account.invoice, too, because there is no direct relation between purchase.order and account.invoice to use a related field or something fancy. To see that field in the invoice form view, you have to add it there, too (as usual).
The rest of your code should be okay, because setting the value by using in it purchase.order.action_view_invoice() would be the next important part, but you've already done that ;-)

Related

Rails - how to merge two objects and keep only duplications?

scope1 = User.where(:last_name => 'green')
scope2 = User.where(:last_name => 'mayer')
merged_scope = scope1.merge(scope2)
In merged_scope will be users with last name green and mayer. But let's suppose a following scenario:
scope1
-
peter green
mark green
joe green
and
scope2
-
caleb mayer
mark mayer
caroline mayer
and I am trying to get into merged_scope only records with the same first_name. Speaking about this specific case, then in merged_scope would be:
mark green
mark mayer
How to do something like this?
Thank you
EDIT:
This is a simplified example, the query is more complex and I need them generate separately (in the example above it can be generated in one query).
There may be a better way but my first thought is...
scope0 = User.where(last_name: 'green')
scope2 = User.where(last_name: 'mayer', first_name: scope0.map(&:first_name))
scope1 = User.where(last_name: 'green', first_name: scope2.map(&:first_mame))
merged_scope = scope1.merge(scope2)
extract all 'green'
map all first_name columns from the 'green' scope
extract all 'mayer' where first name is in the first_name array from the first scope,
extract all 'green' (again) this time where firs tname is in the first_name array from the second scope.
Result is two scopes, one for 'mayer' one for 'green' where first names of records in each scope must exist as first naemes in the other scope
You could try this little tricky query:
last_names = ["green", "mayer"]
User.joins("INNER JOIN users another ON another.last_name != users.last_name
AND users.first_name = another.first_name").
where(last_name: last_names, another: { last_name: last_names })

Rails 4 - Insert duplicate ActiveRecord data

I developed pointing some object and below is my code.
if ObjectRating.where(user_id: current_user.id, object_id: #object.id).present?
rating = ObjectRating.where(user_id: current_user.id, object_id: #object.id).first
if rating.update_attributes(rating_params)
#jsonResult.object = rating
else
#jsonResult.status = false
#jsonResult.message = "Please Retry"
end
else
rating = #object.object_ratings.new(rating_params)
rating.user_id = current_user.id
if rating.save
#jsonResult.object = rating
else
#jsonResult.status = false
#jsonResult.message = "Please Retry"
end
end
Rating params is
private
def rating_params
params.require(:object_rating).permit(:rating)
end
It works good but sometime insert duplicate data in to database.
+----------------------------------------------------------+
| id, object_id , user_id, rating, created_at, updated_at |
+----------------------------------------------------------+
| 1, 100, 200, 8 ,2015-06-26 10:52:34, 2015-06-26 10:52:48 |
| 2, 100, 200, 8 ,2015-06-26 10:52:34, 2015-06-26 10:52:34 |
| 3, 120, 230, 8 ,2015-06-26 10:54:32, 2015-06-26 10:54:32 |
+----------------------------------------------------------+
ID 1, 2 is same object .
I checked before save in controller, Why it create duplicate record for the next one?
you could add indexing of following columns object_id , user_id, rating.
Create migration like,
add_index :object_ratings, [:object_id , :user_id, :rating], unique: true
You can try uniqueness validation with scope.
validates :uniqueness => { scope: [:user_id, :object_id] }
All the ruby objects are inherited from the class Object directly or indirectly
Ex:
String.superclass -> Object < BasicObject
and every object has its object id
ObjectRating.object_id -> <some lenghthy number>
So when you search for object_id it actually search for base object id and hence you always gets results as not found
then as per your code, you save the record again.
My advice is to get rename the column ‘object_id’ in to something else (not to conflict with ruby/rails internals)
You could try something like this:
...
else
rating = ObjectRating.new(rating_params)
rating.user_id = current_user.id
...
Why? How many an objects will be create when #object.object_ratings.new?
Sometime it will possible creating Object.new(object_raing.params) and Object_ratings.new(params) both (or triple).

ruby on rails looping through a list of key value elements

I have a list of key value pairs like this.
PERSON_SUMMARY = {
first_names: %w(Mike Tim Jim kevin Alan Sara John Sammy t'Renée),
last_names: %w(Robinson Jackson Fox Terry Ali Brits Tyson Willis-St.\ Paul),
offenses: [
{ offense_name:'Speeding',
penalties: [
{ penalty_name: 'Prison', severity: 'Medium' },
{ penalty_name: 'Ticket', severity: 'Low' }
]
},
{ offense_name:'Shoplifting',
penalties: [
{ penalty_name: 'Prison', severity: 'Medium' },
{ penalty_name: 'Fine', severity: 'Low' }
]
}
]
}
I want to store and print only offense_name,**penalty_name** and severity one by one , but I am not able to get the right syntax.
Here is what I have tried so far:
PERSON_SUMMARY[:offenses].each do |offense|
offense_name = offense[:offense_name]
offense[:penalties].each do |penalty|
penalty_name = penalty[:penalty_name]
severity_val = penalty[:severity]
end
end
EDIT: Eventually I need to insert it into the database table through this function:
PersonOffense.where(person_id: person.id).first_or_create(
name: offense_name,
penalty: penalty_name ,
severity: severity_val
end
But I notice an issue, there are multiple penalty names above. Not sure how to insert them.
For example,
I need to insert offense_name twice in my table so that there are 2 entries in the table.
Speeding Prison Medium
Speeding Ticket Low
EDIT: I like Jesse's answer below. How can I use it to insert it in the same order to my method above (inserting offense_name,penalty_name and severity with the result of the answer given below by Jesse.
Rather than just using each, if you map over the offenses, and then flatten them in the end, you'll get what you want:
offenses = PERSON_SUMMARY[:offenses].map do |offense|
offense[:penalties].map do |penalty|
penalty.merge(name: offense[:offense_name])
end
end.flatten
=> [{:penalty_name=>"Prison", :severity=>"Medium", :name=>"Speeding"}, {:penalty_name=>"Ticket", :severity=>"Low", :name=>"Speeding"}, {:penalty_name=>"Prison", :severity=>"Medium", :name=>"Shoplifting"}, {:penalty_name=>"Fine", :severity=>"Low", :name=>"Shoplifting"}]
UPDATE
In ruby, the following is a hash, and you already have a hash
So you can just loop through your new array and create your PersonOffense:
offenses.each do |hash|
PersonOffense.where(person_id: person.id).first_or_create( hash )
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 - how to override the default <select> view for foreign key?

I have 2 django model
class Location
address = models.CharField(max_length=100)
city = models.CharField(max_length=20)
class Client
location = models.ForeignKey(Location)
name = models.CharField(max_length=100)
And I have the following admin.py
class ClientAdmin(admin.ModelAdmin):
fieldsets = [
('Client Details', {'fields': ['name']}),
('Location Details', {'fields': ['location']}),
]
admin.site.register(Client, ClientAdmin)
When I try to add a Client I like to have a editable "location" fields i.e. address and city text fields. django by default gives a list.. how can I get the fields from the foregin tables?
any way I can do this? I don't wish to register the Location table in the admin.
thanks
You could put an inline table for the location and use the method queryset to handle the field values.
So, this is the ideia of the solution:
class LocationInline(admin.StackedInline):
model = Location
def queryset(self, request):
query = ... #your custom query here
qs = super(LocationInline, self).queryset(request).filter(query)
return qs
class ClientAdmin(admin.ModelAdmin):
inlines = [LocationInline]
fieldsets = [
('Client Details', {'fields': ['name']}),
]
Edit:
There is another way to do it in django 1.1.
class ClientAdmin(admin.ModelAdmin):
fieldsets = [
('Client Details', {'fields': ['name']}),
('Location Details', {'fields': ['location']}),
]
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name = "location":
locations = Location.objects.filter( ... ) #your query
kwargs["queryset"] = Location.objects.filter(query)
return super(ClientAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
The docs are here: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_foreignkey
It's an old question, but answering this can help a lot of other people too.
So, I hope it helps! ;)

Resources