diff --git a/addons/repair/models/account_move.py b/addons/repair/models/account_move.py
index e3f1a932186..dc617e4da2f 100644
--- a/addons/repair/models/account_move.py
+++ b/addons/repair/models/account_move.py
@@ -8,6 +8,10 @@ class AccountMove(models.Model):
repair_ids = fields.One2many('repair.order', 'invoice_id', readonly=True, copy=False)
+ def unlink(self):
+ self.repair_ids.filtered(lambda repair: repair.state != 'cancel').state = '2binvoiced'
+ return super().unlink()
+
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
diff --git a/addons/repair/models/repair.py b/addons/repair/models/repair.py
index a526db4059f..eb234402295 100644
--- a/addons/repair/models/repair.py
+++ b/addons/repair/models/repair.py
@@ -47,13 +47,13 @@ class Repair(models.Model):
default_address_id = fields.Many2one('res.partner', compute='_compute_default_address_id')
state = fields.Selection([
('draft', 'Quotation'),
- ('cancel', 'Cancelled'),
('confirmed', 'Confirmed'),
('under_repair', 'Under Repair'),
('ready', 'Ready to Repair'),
('2binvoiced', 'To be Invoiced'),
('invoice_except', 'Invoice Exception'),
- ('done', 'Repaired')], string='Status',
+ ('done', 'Repaired'),
+ ('cancel', 'Cancelled')], string='Status',
copy=False, default='draft', readonly=True, tracking=True,
help="* The \'Draft\' status is used when a user is encoding a new and unconfirmed repair order.\n"
"* The \'Confirmed\' status is used when a user confirms the repair order.\n"
@@ -111,6 +111,7 @@ class Repair(models.Model):
amount_tax = fields.Float('Taxes', compute='_amount_tax', store=True)
amount_total = fields.Float('Total', compute='_amount_total', store=True)
tracking = fields.Selection(string='Product Tracking', related="product_id.tracking", readonly=False)
+ invoice_state = fields.Selection(string='Invoice State', related='invoice_id.state')
@api.depends('partner_id')
def _compute_default_address_id(self):
@@ -191,6 +192,14 @@ class Repair(models.Model):
else:
self.location_id = False
+ def unlink(self):
+ for order in self:
+ if order.state not in ('draft', 'cancel'):
+ raise UserError(_('You can not delete a repair order once it has been confirmed. You must first cancel it.'))
+ if order.state == 'cancel' and order.invoice_id and order.invoice_id.posted_before:
+ raise UserError(_('You can not delete a repair order which is linked to an invoice which has been posted once.'))
+ return super().unlink()
+
def button_dummy(self):
# TDE FIXME: this button is very interesting
return True
@@ -199,7 +208,7 @@ class Repair(models.Model):
if self.filtered(lambda repair: repair.state != 'cancel'):
raise UserError(_("Repair must be canceled in order to reset it to draft."))
self.mapped('operations').write({'state': 'draft'})
- return self.write({'state': 'draft'})
+ return self.write({'state': 'draft', 'invoice_id': False})
def action_validate(self):
self.ensure_one()
@@ -251,10 +260,9 @@ class Repair(models.Model):
return True
def action_repair_cancel(self):
- if self.filtered(lambda repair: repair.state == 'done'):
- raise UserError(_("Cannot cancel completed repairs."))
- if any(repair.invoiced for repair in self):
- raise UserError(_('The repair order is already invoiced.'))
+ invoice_to_cancel = self.filtered(lambda repair: repair.invoice_id.state == 'draft').invoice_id
+ if invoice_to_cancel:
+ invoice_to_cancel.button_cancel()
self.mapped('operations').write({'state': 'cancel'})
return self.write({'state': 'cancel'})
@@ -475,7 +483,7 @@ class Repair(models.Model):
repair.write({'repaired': True})
vals = {'state': 'done'}
vals['move_id'] = repair.action_repair_done().get(repair.id)
- if not repair.invoiced and repair.invoice_method == 'after_repair':
+ if not repair.invoice_id and repair.invoice_method == 'after_repair':
vals['state'] = '2binvoiced'
repair.write(vals)
return True
diff --git a/addons/repair/views/repair_views.xml b/addons/repair/views/repair_views.xml
index 2d1aa4219b3..a0fd4177c42 100644
--- a/addons/repair/views/repair_views.xml
+++ b/addons/repair/views/repair_views.xml
@@ -34,21 +34,22 @@
-
+
-
-
+
+