Adding a constraint for a field in Odoo - python

This is what I have to do:
"Add a field for registering children to the employee object. It is possible to enter several children and enter the first and last name and date of birth for each of them. Show the field on the form view, in the Private information tab, below the field for the number of children (children). Show the field only if the number of children is greater than 0."
I have done this:
#api.onchange('children', 'name_child', 'date_of_birth')
def onchange_usage(self):
if self.children > 0:
self.name_child = True
self.date_of_birth = True
else:
self.name_child = False
self.date_of_birth = False
children = fields.Integer(string='Children')
name_child = fields.Char(string='Name of the Child')
date_of_birth = fields.Date(string='Date of Birth')
Does anybody know what is wrong with this code? Thank u.

You can simply add invisible for the fields name_child and date_of_birth
attrs="{'invisible':[('children', '=', 0)]}"

Related

Accessing a value from another model in odoo

I have 2 simple models:
the first one is to create a product total
the other one is to calculate product total.
I want to get the product total value from the second model and pass first model how can I do that?
I want to get ans fields value from second model ans pass total field from first model
class MyinvoiceInvoice(models.Model):
_name = "myinvoice.invoice"
total = fields.Integer(string="Total",store=True)
class InvoiceLine(models.Model):
_name = "myinvoice.invoice.line"
_description = "myinvoice.invoice.line"
_inherit = "myinvoice.invoice"
customer_id = fields.Many2one('myinvoice.invoice', string='Customer Id')
product_id = fields.Many2one('myinvoice.product', string='Product')
quanitity = fields.Integer(string="Quanitity")
unit_price = fields.Integer(string="Unit Price",related='product_id.price')
line_total = fields.Integer(string="Line Total",compute='_compute_total')
ans = fields.Integer(string='ans')
#api.depends('quanitity')
def _compute_total(self):
check = 0
for record in self:
if record.quanitity:
record.line_total = record.unit_price * record.quanitity
check += record.line_total
else:
record.quanitity = 0
record.ans = check
I'm not sure if I understood your question accurately, but it seems that you are trying to get the ans field filled up based on whatever the total is. First of all find and get which field links both these model (in your case it is the customer_id field), probably there will be a Many2one relation between these two models. Using this related field (customer_id) you can user related fields to obtain the total into ans. It would be something like the following:
ans = fields.Integer(related=customer_id.total, string='ans')

How to copy purchase order value to account.invoice in odoo11

I have created a custom field in the purchase order and another in account.invoice with the same name budget_id, when I create a purchase order and create a bill from this order I would like to copy the value of budget_id in the purchase order to the budget_id in the bill.
I have overridden the smart button method "action_view_invoice" in purchase.order and added my code but nothing happen. Are there other ways to do that?
Thanks in advance!
my code
#api.multi
def action_view_invoice(self):
action = self.env.ref('account.action_invoice_tree2')
result = action.read()[0]
result['context'] = {'type': 'in_invoice', 'default_purchase_id': self.id}
if not self.invoice_ids:
# Choose a default account journal in the same currency in case a new invoice is created
journal_domain = [
('type', '=', 'purchase'),
('company_id', '=', self.company_id.id),
('currency_id', '=', self.currency_id.id),
]
default_journal_id = self.env['account.journal'].search(journal_domain, limit=1)
if default_journal_id:
result['context']['default_journal_id'] = default_journal_id.id
else:
# Use the same account journal than a previous invoice
result['context']['default_journal_id'] = self.invoice_ids[0].journal_id.id
# choose the view_mode accordingly
if len(self.invoice_ids) != 1:
result['domain'] = "[('id', 'in', " + str(self.invoice_ids.ids) + ")]"
elif len(self.invoice_ids) == 1:
res = self.env.ref('account.invoice_supplier_form', False)
result['views'] = [(res and res.id or False, 'form')]
result['res_id'] = self.invoice_ids.id
result['context']['default_origin'] = self.name
result['context']['default_reference'] = self.partner_ref
result['context']['default_budget_id'] = self.budget_id.id # my code here
return result
The account.invoice object has the field purchase_id which is a link with purchase.order.
So in the account.invoice you can get any of the way(like in the vendor bill creation best approch) the purchase order budget_id field value into account.invoice budget_id field.
Code link - Purchase link In Invoice

Add additional fields after phone number lookup in the database in Django

I am building an app that look for each phone number in the database. If there is any duplicate, I want to grab the first phone number found as the main record for that phone number, then for the duplicate information(name, location), get each one of those fields, and add it to the main record phone number fields (name, location), separated by a semi colon.
The outcome would look like this after checking the duplicate information of the main phone number record found:
Name Location Phone number
Helene,Sandra New Yok, Boston 000-000
Please find my model below:
class Document(models.Model):
name = models.CharField(null=True, max_length=254, blank=True)
location = models.CharField(null=True, max_length=254, blank=True)
phone_number = models.CharField(null=True, max_length=254, blank=True)
I am a bit lost on to achieve the above. Any help would be much appreciated.
Below is what I have tried so far:(not working)
from django.shortcuts import render
from .models import Document
def index(request):
search_number = list(Document.objects.order_by('-created').values("phone_number").distinct().order_by()) # Dictionary list of all numbers sorted by creation data without duplicate
for x in search_number:
try:
look_up = Document.objects.values("phone_number")
list_in_dba = look_up.phone_number
x in list_in_dba['phone_number']
print("Yes")
except:
print("No")
return render(request, 'snippets/index.html')
I would start with something like this.
## this will get you all document records that have a duplicate phone-number
## and also group them by phone-number.
duplicate_phone_numbers = Document.objects.values('phone_number').\
annotate(total_items=Count('phone_number')).order_by('-total_items').filter(total_items__gt=1)
for entry in duplicate_phone_numbers:
records = Document.objects.filter(phone_number=entry.get('phone_number')
## unsure whether you want to just output the info here or
## update the actual record
all_names = ''
all_locations = ''
for x in records:
all_names += x.name + ";"
all_locations += x.location + ";"
print all_names, all_locations, entry.get('phone_number')
# to update the actual record
record = records[0]
record.name = all_names
record.location = all_locations
record.save()

How to automatically change model fields in django

I have a model and I want to know if it is possible to set a condition that triggers a change in the model field. For example, I have a model
class BillboardTracker(models.Model):
client_name = models.CharField(max_length=400)
entry_date = models.DateTimeField(default=datetime.now)
duration = models.PositiveIntegerField()
expiry_date = models.DateField()
is_expired = models.BooleanField(default=False)
I want to know if it is possible to have a function in the model that makes is_expired equals to True when the expiry date is up. I tried this
def expire(self):
if datetime.now == self.expiry_date:
self.is_expired = True
but it's not working. Is it possible to implement this?
Use a #property
The simplest thing here is not to have an is expired field at all! It's not needed. What you need is a property.
class BillboardTracker(models.Model):
client_name = models.CharField(max_length=400)
entry_date = models.DateTimeField(default=datetime.now)
duration = models.PositiveIntegerField()
expiry_date = models.DateField()
#property
def is_expired(self):
if datetime.now > self.expiry_date:
return True
return False
Remember, you don't have a field in a database, if that field is the same as another field with a simple calculation. This automatically eliminates your head ache of having to flag items as expired.
If you want to find out if an object has expired.
if instance.is_expired == True:
print 'yes, that ones gone'
Filtering
If you wanted to retrieve a whole set of objects that have expired
BillboardTracker.objects.filter(expiry_date__le=datetime.now())
This is why I mentioned that you don't need to store a field that can be easily calculated.
Index advantage
In most RDBMS a boolean field (such as your is_expired column) cannot be indexed effectively. So that actually means the above query will be faster than a query on that boolean field provided you create an index on the expiry_date field.
You need to make two changes in this function,
Firstly use datetime.now() and secondly,
You might want to update your logic like this :
def expire(self):
if datetime.now() >= self.expiry_date:
self.is_expired = True
return True
else:
return False
Because sometimes both the values might not be exactly same but still BillboardTracker need is_expired = True for all previous dates.
And in your views :
def your_view(request):
instance = BillboardTracker.objects.get(id=some_id)
if instance.is_expired() == True:
print 'expired'
else:
print 'fresh'

Django forms DateTimeInput widget- how to specify max date?

I have a form displayed in my Django project, and one of the form fields is a DateTimeInput widget, defined with:
presentation_date = mDateTimeField(required=False, label="Presentation date", widget=forms.DateTimeInput(format='%d/%m/%Y %H:%M'))
This widget currently displays all dates between the start of last year to the end of this year (01/01/2016- 31/12/2017). However, at the end of last year this caused some issues, as it meant that users were unable to select dates for the beginning of this year. What I want to do is extend the range of the dates available for selection in the widget by one year (i.e the new range would be 01/01/2016- 31/12/2018).
I understand that it is possible to do this using form validation (for example, by writing a view such as clean_presentation_date() and performing the validation inside that view, but this won't solve the issue I'm having- as currently, dates before 01/01/2016 or after 31/12/2017 (displayed in the datetimepicker calendar that's shown when the user selects the field in the form) are 'greyed out' and it is not possible to select them. This is exactly the functionality that I want, but I just want to change the values of the dates on which it is performed, so that at least the whole of the next calendar year is always selectable.
I have searched for maxDate & minDate variables within the forms.py file where the form with this field is defined, but can't find anything that looks like it is what's restricting which dates are available to be selected, and which are not selectable.
The view that's showing the page with this form on it is defined with:
def concept(request, project_id):
project = Project.objects.prefetch_related('budget_versions').get(id=project_id)
deposit = Deposit.objects.get_or_create(project=project)[0]
presentations = project.budget_versions.select_related('meeting').prefetch_related('budget_items', 'cci_items', 'presenters').filter(version_number__isnull=False).annotate(vn=F('version_number') * -1).order_by('presentation_date', 'created', '-vn')
end_details = EndDetails.objects.get_or_create(project=project)[0]
presentation_formset = BudgetPresentationFormset(prefix="presentations", instance=project, queryset=presentations)
drawing_formset = DrawingUploadFormset(prefix="drawings", queryset=Drawing.objects.filter(budget__in=presentations).order_by('budget__presentation_date', 'budget__created'))
context = {
'project': project,
'presentations': presentations,
'presentation_formset': presentation_formset,
'drawing_formset': drawing_formset,
'deposit_form': DepositInfoForm(instance=deposit),
'ended_form': EndDetailsForm(instance=end_details),
'budget_notes_form': BudgetNotesForm(instance=project.budget_overview),
}
The particular form I'm looking at is the presentations one, defined in forms.py:
class FirstPresentationForm(ValidatedForm):
""" UNUSED """
who_presenting = forms.CharField()
details = forms.CharField(required=False, label='Original option costed')
presentation_date = mDateTimeField(required=False, label="Presentation date", widget=forms.DateTimeInput(format='%d/%m/%Y %H:%M')) #ERF(19/12/2016 # 1210) Remove 'datetimepicker' from field..., attrs=({'class':'datetimepicker'})))
class Meta:
model = Budget
fields = ('presentation_date','who_presenting','details')
def __init__(self, *args, **kwargs):
instance = kwargs.get('instance', {})
project = instance.project
who_presenting = [pe.employee.id for pe in project.assigned.select_related('employee').filter(role=Role.P)]
#Make into an array with two employee IDs, or None. If two results were found, they will already be in the right format
if len(who_presenting)==1:
who_presenting.append(None)
elif not who_presenting:
who_presenting = None
if instance.presentation_date:
pres_meeting, created = Meeting.objects.get_or_create(project=project, purpose='6')
self.pres_meeting_id = pres_meeting.id
self.pres_meeting_creator = pres_meeting.event_creator or ''
if created:
pres_meeting.date = instance.presentation_date
pres_meeting.save()
initial = kwargs.get('initial', {})
initial={
'who_presenting': who_presenting,
}
kwargs['initial'] = initial
super(FirstPresentationForm, self).__init__(*args, **kwargs)
self.fields['who_presenting'] = AutoFlexiSelect(model='e', required=False, choices=get_choices('DESIGN_EMPLOYEE_CHOICES'), current_id=who_presenting, label="Who is presenting")
self.fields['presentation_date'].widget.attrs.update({'data-meeting-id': getattr(self,'pres_meeting_id', ''), 'data-meeting-creator': getattr(self,'pres_meeting_creator', '')})
def save(self, commit=True):
project = self.instance.project
data = self.cleaned_data
try: ProjectEmployee.objects.filter(project=project, role=Role.P).delete() #Delete current records, if any, to prevent build up on editing this field
except ObjectDoesNotExist: pass
if data['who_presenting']:
designers = data['who_presenting']
# Get the ids from the form field (received as a string)
designers = [re.sub('\D+', '', s) for s in designers.split(',')]
who_presenting_1 = Employee.objects.get(id=designers[0])
who_presenting_2 = designers[1] #If only one employee in selected choice, this will be None
if who_presenting_2: who_presenting_2 = Employee.objects.get(id=designers[1]) #If two employees in selected choice, sets the second one
pe = ProjectEmployee(project=project, employee=who_presenting_1, role=Role.P)
pe.save()
if who_presenting_2: #If a second designer, delete as well
pe = ProjectEmployee(project=project, employee=who_presenting_2, role=Role.P)
pe.save()
if 'presentation_date' in self.changed_data:
from events.models import refresh_group_cache
print '************'
pres_meeting = Meeting.objects.get(project=project, purpose='6')
self.instance.meeting = pres_meeting
self.instance.save()
print 'Updating date', data['presentation_date'], pres_meeting.id
pres_meeting.date = data['presentation_date']
pres_meeting.save()
refresh_group_cache(pres_meeting.event_creator.calendar_id, pres_meeting.date.year, pres_meeting.date.month, pres_meeting.event_id, pres_meeting)
return super(FirstPresentationForm, self).save(commit=commit)
I have tried passing/ setting max_date as an attribute of the presentation_date variable, but it doesn't appear to have an attribute/ property by this name...
How can I specify a particular date as this widget's maxDate, so that the user is able to select dates up until December of next year, rather than just up until December of this year?
Edit
The mDateTimeField that's using the widget is also defined in forms.py, with:
class mDateTimeField(forms.DateTimeField):
def __init__(self, *args, **kwargs):
kwargs.setdefault('input_formats', DATE_INPUT_FORMATS)
super(mDateTimeField, self).__init__(*args, **kwargs)
This should help you:
widgets = {
'start_date': forms.DateInput(attrs={
'class':'datepicker', 'data-min': YOUR_MIN_DATE,
'data-max': YOUR_MAX_DATE}),
}
Usage:
minDate: $(this).data('min'),
maxDate: $(this).data('max'),

Categories

Resources