0
votes

If have two entities "payment" and "bill". With each payment the user must be able to pay one or more "biils" That is done by adding a One2Many field (of type bill) in the payment model. How can I add a constrain to ensure that a payment should have at least one bill ? (ensure that the One2Many list is not empty). I have tried this code but it is not working cause the user can create one payment without having to add "bill" to the One2Many Bills attibute.

class PaymentCenter(models.Model):
    _name = 'center.payment'
    _description = 'Payment'
    _inherit = ['mail.thread', 'mail.activity.mixin']

    bill_ids = fields.One2many('center.bill',
                                    "payment_id",
                                    string=" Bills", required=True)

    @api.constrains('bill_ids')
    def _constrains_bill_ids(self):
        if not self.bill_ids or len(self.bill_ids)==0:
            raise ValidationError("You must add at least one bill to the payment")

class BillCenter(models.Model):
    _name = 'center.bill'
    _inherits = {'ir.attachment': 'attachment_id'}

    payment_id = fields.Many2one('center.payment', string="Payment")
2

2 Answers

1
votes

@constrains will be triggered only if the declared fields in the decorated method are included in the create or write call. It implies that fields not present in a view will not trigger a call during record creation.
A override of create is necessary to make sure a constraint will always be triggered (e.g. to test the absence of value).

Try to override create method and check if bill_ids is present:

@api.model
def create(self, values):
    if 'bill_ids' not in values:
        values['bill_ids'] = False
    return super(PaymentCenter, self).create(values)  

When You add the code above the constrains should work and If you try to delete bills and save It raises a validation error (it is because of bill_ids is present in values argument of write method. Example of one bill deleted {'bill_ids': [[2, id, False]]}).

You can also raise the error in the create method.

You can let users create payments without filling bill_ids and raise a user error when they try to validate a payment without a bill.

def validate_payment(self):
    for payment in self:
        if not payment.bill_ids:
            raise UserError(_("You must add at least one bill to the payment."))
0
votes

Use validator function..

from django.db import models  
from django.core.exceptions import ValidationError 

# validator function 
def validate_bill_ids(value): 
    if not value: 
        raise ValidationError("Bills id required") 


class YourModel(models.Model): 
    bill_ids = fields.One2many('center.bill',
                                    "payment_id",
                                    string=" Bills", required=True,
                        validators =[validate_bill_ids] 
                        )