Example #1
0
    def action_validate(self):
        self._check_security_action_validate()

        current_employee = self.env['hr.employee'].search(
            [('user_id', '=', self.env.uid)], limit=1)
        for holiday in self:
            if holiday.state not in ['confirm', 'validate1']:
                raise UserError(
                    _('Leave request must be confirmed in order to approve it.'
                      ))
            if holiday.state == 'validate1' and not holiday.env.user.has_group(
                    'hr_holidays.group_hr_holidays_manager'):
                raise UserError(
                    _('Only an HR Manager can apply the second approval on leave requests.'
                      ))

            holiday.write({'state': 'validate'})
            if holiday.double_validation:
                holiday.write({'second_approver_id': current_employee.id})
            else:
                holiday.write({'first_approver_id': current_employee.id})
            if holiday.holiday_type == 'employee' and holiday.type == 'remove':
                holiday._validate_leave_request()
            elif holiday.holiday_type == 'category':
                leaves = self.env['hr.holidays']
                for employee in holiday.category_id.employee_ids:
                    values = holiday._prepare_create_by_category(employee)
                    leaves += self.with_context(
                        mail_notify_force_send=False).create(values)
                # TODO is it necessary to interleave the calls?
                leaves.action_approve()
                if leaves and leaves[0].double_validation:
                    leaves.action_validate()
        return True
Example #2
0
    def _interval_dates(self, frequency, company):
        """
        Method used to compute the theoretical date from which account move lines should be fetched
        @param {string} frequency: a valid value of the selection field on the object (daily, monthly, annually)
            frequencies are literal (daily means 24 hours and so on)
        @param {recordset} company: the company for which the closing is done
        @return {dict} the theoretical date from which account move lines are fetched.
            date_stop date to which the move lines are fetched, always now()
            the dates are in their GECOERP Database string representation
        """
        date_stop = datetime.utcnow()
        interval_from = None
        name_interval = ''
        if frequency == 'daily':
            interval_from = date_stop - timedelta(days=1)
            name_interval = _('Daily Closing')
        elif frequency == 'monthly':
            month_target = date_stop.month > 1 and date_stop.month - 1 or 12
            year_target = month_target < 12 and date_stop.year or date_stop.year - 1
            interval_from = date_stop.replace(year=year_target,
                                              month=month_target)
            name_interval = _('Monthly Closing')
        elif frequency == 'annually':
            year_target = date_stop.year - 1
            interval_from = date_stop.replace(year=year_target)
            name_interval = _('Annual Closing')

        return {
            'interval_from': FieldDateTime.to_string(interval_from),
            'date_stop': FieldDateTime.to_string(date_stop),
            'name_interval': name_interval
        }
Example #3
0
    def _notification_recipients(self, message, groups):
        """ Handle HR users and officers recipients that can validate or refuse holidays
        directly from email. """
        groups = super(Holidays,
                       self)._notification_recipients(message, groups)

        self.ensure_one()
        hr_actions = []
        if self.state == 'confirm':
            app_action = self._notification_link_helper(
                'controller', controller='/hr_holidays/validate')
            hr_actions += [{'url': app_action, 'title': _('Approve')}]
        if self.state in ['confirm', 'validate', 'validate1']:
            ref_action = self._notification_link_helper(
                'controller', controller='/hr_holidays/refuse')
            hr_actions += [{'url': ref_action, 'title': _('Refuse')}]

        new_group = ('group_hr_holidays_user',
                     lambda partner: bool(partner.user_ids) and any(
                         user.has_group('hr_holidays.group_hr_holidays_user')
                         for user in partner.user_ids), {
                             'actions': hr_actions,
                         })

        return [new_group] + groups
Example #4
0
    def write(self, vals):
        has_been_posted = False
        for order in self:
            if order.company_id._is_accounting_unalterable():
                # write the hash and the secure_sequence_number when posting or invoicing an pos.order
                if vals.get('state') in ['paid', 'done', 'invoiced']:
                    has_been_posted = True

                # restrict the operation in case we are trying to write a forbidden field
                if (order.state in ['paid', 'done', 'invoiced']
                        and set(vals).intersection(ORDER_FIELDS)):
                    raise UserError(
                        _('According to the French law, you cannot modify a point of sale order. Forbidden fields: %s.'
                          ) % ', '.join(ORDER_FIELDS))
                # restrict the operation in case we are trying to overwrite existing hash
                if (order.l10n_fr_hash and 'l10n_fr_hash' in vals) or (
                        order.l10n_fr_secure_sequence_number
                        and 'l10n_fr_secure_sequence_number' in vals):
                    raise UserError(
                        _('You cannot overwrite the values ensuring the inalterability of the point of sale.'
                          ))
        res = super(pos_order, self).write(vals)
        # write the hash and the secure_sequence_number when posting or invoicing a pos order
        if has_been_posted:
            for order in self.filtered(
                    lambda o: o.company_id._is_accounting_unalterable() and
                    not (o.l10n_fr_secure_sequence_number or o.l10n_fr_hash)):
                new_number = order.company_id.l10n_fr_pos_cert_sequence_id.next_by_id(
                )
                vals_hashing = {
                    'l10n_fr_secure_sequence_number': new_number,
                    'l10n_fr_hash': order._get_new_hash(new_number)
                }
                res |= super(pos_order, order).write(vals_hashing)
        return res
Example #5
0
    def _check_hash_integrity(self, company_id):
        """Checks that all posted or invoiced pos orders have still the same data as when they were posted
        and raises an error with the result.
        """
        def build_order_info(order):
            entry_reference = _('(Receipt ref.: %s)')
            order_reference_string = order.pos_reference and entry_reference % order.pos_reference or ''
            return [
                ctx_tz(order,
                       'date_order'), order.l10n_fr_secure_sequence_number,
                order.name, order_reference_string,
                ctx_tz(order, 'write_date')
            ]

        orders = self.search([('state', 'in', ['paid', 'done', 'invoiced']),
                              ('company_id', '=', company_id),
                              ('l10n_fr_secure_sequence_number', '!=', 0)],
                             order="l10n_fr_secure_sequence_number ASC")

        if not orders:
            raise UserError(
                _('There isn\'t any order flagged for data inalterability yet for the company %s. This mechanism only runs for point of sale orders generated after the installation of the module France - Certification CGI 286 I-3 bis. - POS'
                  ) % self.env.user.company_id.name)
        previous_hash = u''
        start_order_info = []
        for order in orders:
            if order.l10n_fr_hash != order._compute_hash(
                    previous_hash=previous_hash):
                raise UserError(
                    _('Corrupted data on point of sale order with id %s.') %
                    order.id)
            previous_hash = order.l10n_fr_hash

        orders_sorted_date = orders.sorted(lambda o: o.date_order)
        start_order_info = build_order_info(orders_sorted_date[0])
        end_order_info = build_order_info(orders_sorted_date[-1])

        report_dict = {
            'start_order_name': start_order_info[2],
            'start_order_ref': start_order_info[3],
            'start_order_date': start_order_info[0],
            'end_order_name': end_order_info[2],
            'end_order_ref': end_order_info[3],
            'end_order_date': end_order_info[0]
        }

        # Raise on success
        raise UserError(
            _('''Successful test !

                         The point of sale orders are guaranteed to be in their original and inalterable state
                         From: %(start_order_name)s %(start_order_ref)s recorded on %(start_order_date)s
                         To: %(end_order_name)s %(end_order_ref)s recorded on %(end_order_date)s

                         For this report to be legally meaningful, please download your certification from your customer account on GECOERP.com (Only for GECOERP Enterprise users).'''
              ) % report_dict)
Example #6
0
 def _message_notification_recipients(self, message, recipients):
     result = super(Holidays, self)._message_notification_recipients(
         message, recipients)
     leave_type = self.env[message.model].browse(message.res_id).type
     title = _("See Leave") if leave_type == 'remove' else _(
         "See Allocation")
     for res in result:
         if result[res].get('button_access'):
             result[res]['button_access']['title'] = title
     return result
Example #7
0
    def _parse_import_data_recursive(self, model, prefix, data, import_fields,
                                     options):
        # Get fields of type date/datetime
        all_fields = self.env[model].fields_get()
        for name, field in all_fields.items():
            name = prefix + name
            if field['type'] in ('date', 'datetime') and name in import_fields:
                # Parse date
                index = import_fields.index(name)
                dt = datetime.datetime
                server_format = DEFAULT_SERVER_DATE_FORMAT if field[
                    'type'] == 'date' else DEFAULT_SERVER_DATETIME_FORMAT

                if options.get('%s_format' % field['type'],
                               server_format) != server_format:
                    # datetime.str[fp]time takes *native strings* in both
                    # versions, for both data and pattern
                    user_format = pycompat.to_native(
                        options.get('%s_format' % field['type']))
                    for num, line in enumerate(data):
                        if line[index]:
                            line[index] = line[index].strip()
                        if line[index]:
                            try:
                                line[index] = dt.strftime(
                                    dt.strptime(
                                        pycompat.to_native(line[index]),
                                        user_format), server_format)
                            except ValueError as e:
                                raise ValueError(
                                    _("Column %s contains incorrect values. Error in line %d: %s"
                                      ) % (name, num + 1, e))
                            except Exception as e:
                                raise ValueError(
                                    _("Error Parsing Date [%s:L%d]: %s") %
                                    (name, num + 1, e))
            # Check if the field is in import_field and is a relational (followed by /)
            # Also verify that the field name exactly match the import_field at the correct level.
            elif any(name + '/' in import_field
                     and name == import_field.split('/')[prefix.count('/')]
                     for import_field in import_fields):
                # Recursive call with the relational as new model and add the field name to the prefix
                self._parse_import_data_recursive(field['relation'],
                                                  name + '/', data,
                                                  import_fields, options)
            elif field['type'] in ('float',
                                   'monetary') and name in import_fields:
                # Parse float, sometimes float values from file have currency symbol or () to denote a negative value
                # We should be able to manage both case
                index = import_fields.index(name)
                self._parse_float_from_data(data, index, name, options)
        return data
Example #8
0
 def message_get_suggested_recipients(self):
     recipients = super(Applicant, self).message_get_suggested_recipients()
     for applicant in self:
         if applicant.partner_id:
             applicant._message_add_suggested_recipient(
                 recipients,
                 partner=applicant.partner_id,
                 reason=_('Contact'))
         elif applicant.email_from:
             applicant._message_add_suggested_recipient(
                 recipients,
                 email=applicant.email_from,
                 reason=_('Contact Email'))
     return recipients
Example #9
0
    def _read_file(self, options):
        """ Dispatch to specific method to read file content, according to its mimetype or file type
            :param options : dict of reading options (quoting, separator, ...)
        """
        self.ensure_one()
        # guess mimetype from file content
        mimetype = guess_mimetype(self.file)
        (file_extension, handler,
         req) = FILE_TYPE_DICT.get(mimetype, (None, None, None))
        if handler:
            try:
                return getattr(self, '_read_' + file_extension)(options)
            except Exception:
                _logger.warn(
                    "Failed to read file '%s' (transient id %d) using guessed mimetype %s",
                    self.file_name or '<unknown>', self.id, mimetype)

        # try reading with user-provided mimetype
        (file_extension, handler,
         req) = FILE_TYPE_DICT.get(self.file_type, (None, None, None))
        if handler:
            try:
                return getattr(self, '_read_' + file_extension)(options)
            except Exception:
                _logger.warn(
                    "Failed to read file '%s' (transient id %d) using user-provided mimetype %s",
                    self.file_name or '<unknown>', self.id, self.file_type)

        # fallback on file extensions as mime types can be unreliable (e.g.
        # software setting incorrect mime types, or non-installed software
        # leading to browser not sending mime types)
        if self.file_name:
            p, ext = os.path.splitext(self.file_name)
            if ext in EXTENSIONS:
                try:
                    return getattr(self, '_read_' + ext[1:])(options)
                except Exception:
                    _logger.warn(
                        "Failed to read file '%s' (transient id %s) using file extension",
                        self.file_name, self.id)

        if req:
            raise ImportError(
                _("Unable to load \"{extension}\" file: requires Python module \"{modname}\""
                  ).format(extension=file_extension, modname=req))
        raise ValueError(
            _("Unsupported file format \"{}\", import only supports CSV, ODS, XLS and XLSX"
              ).format(self.file_type))
Example #10
0
    def action_refuse(self):
        self._check_security_action_refuse()

        current_employee = self.env['hr.employee'].search(
            [('user_id', '=', self.env.uid)], limit=1)
        for holiday in self:
            if holiday.state not in ['confirm', 'validate', 'validate1']:
                raise UserError(
                    _('Leave request must be confirmed or validated in order to refuse it.'
                      ))

            if holiday.state == 'validate1':
                holiday.write({
                    'state': 'refuse',
                    'first_approver_id': current_employee.id
                })
            else:
                holiday.write({
                    'state': 'refuse',
                    'second_approver_id': current_employee.id
                })
            # Delete the meeting
            if holiday.meeting_id:
                holiday.meeting_id.unlink()
            # If a category that created several holidays, cancel all related
            holiday.linked_request_ids.action_refuse()
        self._remove_resource_leave()
        return True
Example #11
0
 def unlink(self):
     for holiday in self.filtered(lambda holiday: holiday.state not in
                                  ['draft', 'cancel', 'confirm']):
         raise UserError(
             _('You cannot delete a leave which is in %s state.') %
             (holiday.state, ))
     return super(Holidays, self).unlink()
Example #12
0
 def copy(self, default=None):
     view = self.env['ir.ui.view'].browse(self.view_id.id)
     # website.page's ir.ui.view should have a different key than the one it
     # is copied from.
     # (eg: website_version: an ir.ui.view record with the same key is
     # expected to be the same ir.ui.view but from another version)
     new_view = view.copy({
         'key': view.key + '.copy',
         'name': '%s %s' % (view.name, _('(copy)'))
     })
     default = {
         'name': '%s %s' % (self.name, _('(copy)')),
         'url': self.env['website'].get_unique_path(self.url),
         'view_id': new_view.id,
     }
     return super(Page, self).copy(default=default)
Example #13
0
    def _fields_view_get_address(self, arch):
        arch = super(Partner, self)._fields_view_get_address(arch)
        # render the partner address accordingly to address_view_id
        doc = etree.fromstring(arch)
        if doc.xpath("//field[@name='city_id']"):
            return arch

        replacement_xml = """
            <div>
                <field name="country_enforce_cities" invisible="1"/>
                <field name='city' placeholder="%(placeholder)s"
                    attrs="{
                        'invisible': [('country_enforce_cities', '=', True), ('city_id', '!=', False)],
                        'readonly': [('type', '=', 'contact')%(parent_condition)s]
                    }"
                />
                <field name='city_id' placeholder="%(placeholder)s"
                    context="{'default_country_id': country_id}"
                    domain="[('country_id', '=', country_id)]"
                    attrs="{
                        'invisible': [('country_enforce_cities', '=', False)],
                        'readonly': [('type', '=', 'contact')%(parent_condition)s]
                    }"
                />
            </div>
        """

        replacement_data = {
            'placeholder': _('City'),
        }

        def _arch_location(node):
            in_subview = False
            view_type = False
            parent = node.getparent()
            while parent is not None and (not view_type or not in_subview):
                if parent.tag == 'field':
                    in_subview = True
                elif parent.tag in ['list', 'tree', 'kanban', 'form']:
                    view_type = parent.tag
                parent = parent.getparent()
            return {
                'view_type': view_type,
                'in_subview': in_subview,
            }

        for city_node in doc.xpath("//field[@name='city']"):
            location = _arch_location(city_node)
            replacement_data['parent_condition'] = ''
            if location['view_type'] == 'form' or not location['in_subview']:
                replacement_data['parent_condition'] = ", ('parent_id', '!=', False)"

            replacement_formatted = replacement_xml % replacement_data
            for replace_node in etree.fromstring(replacement_formatted).getchildren():
                city_node.addprevious(replace_node)
            parent = city_node.getparent()
            parent.remove(city_node)

        arch = etree.tostring(doc, encoding='unicode')
        return arch
Example #14
0
    def _send_email(self):
        """ send notification email to a new portal user """
        if not self.env.user.email:
            raise UserError(
                _('You must have an email address in your User Preferences to send emails.'
                  ))

        # determine subject and body in the portal user's language
        template = self.env.ref('portal.mail_template_data_portal_welcome')
        for wizard_line in self:
            lang = wizard_line.user_id.lang
            partner = wizard_line.user_id.partner_id

            portal_url = partner.with_context(
                signup_force_type_in_url='',
                lang=lang)._get_signup_url_for_action()[partner.id]
            partner.signup_prepare()

            if template:
                template.with_context(dbname=self._cr.dbname,
                                      portal_url=portal_url,
                                      lang=lang).send_mail(wizard_line.id,
                                                           force_send=True)
            else:
                _logger.warning(
                    "No email template found for sending email to the portal user"
                )

        return True
Example #15
0
 def create(self, vals):
     # restrict the operation in case we are trying to set a forbidden field
     if self.company_id._is_accounting_unalterable():
         if vals.get('update_posted'):
             field_string = self._fields['update_posted'].get_description(self.env)['string']
             raise UserError(_("According to the French law, you cannot modify a journal in order for its posted data to be updated or deleted. Unauthorized field: %s.") % field_string)
     return super(AccountJournal, self).create(vals)
Example #16
0
    def get_google_drive_url(self, res_id, template_id):
        self.ensure_one()
        self = self.sudo()

        model = self.model_id
        filter_name = self.filter_id.name if self.filter_id else False
        record = self.env[model.model].browse(res_id).read()[0]
        record.update({'model': model.name, 'filter': filter_name})
        name_gdocs = self.name_template
        try:
            name_gdocs = name_gdocs % record
        except:
            raise UserError(
                _("At least one key cannot be found in your Google Drive name pattern"
                  ))

        attachments = self.env["ir.attachment"].search([
            ('res_model', '=', model.model), ('name', '=', name_gdocs),
            ('res_id', '=', res_id)
        ])
        url = False
        if attachments:
            url = attachments[0].url
        else:
            url = self.copy_doc(res_id, template_id, name_gdocs,
                                model.model).get('url')
        return url
Example #17
0
 def _read_xls_book(self, book):
     sheet = book.sheet_by_index(0)
     # emulate Sheet.get_rows for pre-0.9.4
     for row in pycompat.imap(sheet.row, range(sheet.nrows)):
         values = []
         for cell in row:
             if cell.ctype is xlrd.XL_CELL_NUMBER:
                 is_float = cell.value % 1 != 0.0
                 values.append(
                     pycompat.text_type(cell.value)
                     if is_float else pycompat.text_type(int(cell.value)))
             elif cell.ctype is xlrd.XL_CELL_DATE:
                 is_datetime = cell.value % 1 != 0.0
                 # emulate xldate_as_datetime for pre-0.9.3
                 dt = datetime.datetime(*xlrd.xldate.xldate_as_tuple(
                     cell.value, book.datemode))
                 values.append(
                     dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT
                                 ) if is_datetime else dt.
                     strftime(DEFAULT_SERVER_DATE_FORMAT))
             elif cell.ctype is xlrd.XL_CELL_BOOLEAN:
                 values.append(u'True' if cell.value else u'False')
             elif cell.ctype is xlrd.XL_CELL_ERROR:
                 raise ValueError(
                     _("Error cell found while reading XLS/XLSX file: %s") %
                     xlrd.error_text_from_code.get(
                         cell.value, "unknown error code %s" % cell.value))
             else:
                 values.append(cell.value)
         if any(x for x in values if x.strip()):
             yield values
Example #18
0
 def get_empty_list_help(self, help):
     return super(
         Applicant,
         self.with_context(
             empty_list_help_model='hr.job',
             empty_list_help_id=self.env.context.get('default_job_id'),
             empty_list_help_document_name=_(
                 "job applicants"))).get_empty_list_help(help)
    def _get_pos_mercury_config_id(self, config, journal_id):
        journal = config.journal_ids.filtered(lambda r: r.id == journal_id)

        if journal and journal.pos_mercury_config_id:
            return journal.pos_mercury_config_id
        else:
            raise UserError(
                _("No Mercury configuration associated with the journal."))
Example #20
0
 def unlink(self):
     for line in self.filtered(
             lambda s: s.company_id._is_accounting_unalterable(
             ) and s.journal_id.journal_user):
         raise UserError(
             _('You cannot modify anything on a bank statement line (name: %s) that was created by point of sale operations.'
               ) % (line.name, ))
     return super(AccountBankStatementLine, self).unlink()
Example #21
0
 def _compute_ressource_id(self):
     result = {}
     for record in self:
         word = self._get_key_from_url(record.google_drive_template_url)
         if word:
             record.google_drive_resource_id = word
         else:
             raise UserError(_("Please enter a valid Google Document URL."))
     return result
Example #22
0
 def build_order_info(order):
     entry_reference = _('(Receipt ref.: %s)')
     order_reference_string = order.pos_reference and entry_reference % order.pos_reference or ''
     return [
         ctx_tz(order,
                'date_order'), order.l10n_fr_secure_sequence_number,
         order.name, order_reference_string,
         ctx_tz(order, 'write_date')
     ]
Example #23
0
 def write(self, vals):
     # restrict the operation in case we are trying to write a forbidden field
     if set(vals).intersection(LINE_FIELDS):
         if any(l.company_id._is_accounting_unalterable()
                and l.order_id.state in ['done', 'invoiced'] for l in self):
             raise UserError(
                 _('According to the French law, you cannot modify a point of sale order line. Forbidden fields: %s.'
                   ) % ', '.join(LINE_FIELDS))
     return super(PosOrderLine, self).write(vals)
Example #24
0
 def message_get_suggested_recipients(self):
     recipients = super(Track, self).message_get_suggested_recipients()
     for track in self:
         if track.partner_email != track.partner_id.email:
             track._message_add_suggested_recipient(
                 recipients,
                 email=track.partner_email,
                 reason=_('Speaker Email'))
     return recipients
Example #25
0
 def _is_journal_alterable(self):
     self.ensure_one()
     critical_domain = [('journal_id', '=', self.id),
                         '|', ('l10n_fr_hash', '!=', False),
                         '&', ('l10n_fr_secure_sequence_number', '!=', False),
                         ('l10n_fr_secure_sequence_number', '!=', 0)]
     if self.env['account.move'].search(critical_domain):
         raise UserError(_('It is not permitted to disable the data inalterability in this journal (%s) since journal entries have already been protected.') % (self.name, ))
     return True
Example #26
0
 def _check_session_timing(self):
     self.ensure_one()
     date_today = datetime.utcnow()
     session_start = Datetime.from_string(self.start_at)
     if not date_today - timedelta(hours=24) <= session_start:
         raise UserError(
             _("This session has been opened another day. To comply with the French law, you should close sessions on a daily basis. Please close session %s and open a new one."
               ) % self.name)
     return True
Example #27
0
    def get_error_messages(self):
        emails = []
        partners_error_empty = self.env['res.partner']
        partners_error_emails = self.env['res.partner']
        partners_error_user = self.env['res.partner']

        for wizard_user in self.with_context(active_test=False).filtered(
                lambda w: w.in_portal and not w.partner_id.user_ids):
            email = extract_email(wizard_user.email)
            if not email:
                partners_error_empty |= wizard_user.partner_id
            elif email in emails:
                partners_error_emails |= wizard_user.partner_id
            user = self.env['res.users'].sudo().with_context(
                active_test=False).search([('login', '=', email)])
            if user:
                partners_error_user |= wizard_user.partner_id
            emails.append(email)

        error_msg = []
        if partners_error_empty:
            error_msg.append(
                "%s\n- %s" %
                (_("Some contacts don't have a valid email: "), '\n- '.join(
                    partners_error_empty.mapped('display_name'))))
        if partners_error_emails:
            error_msg.append(
                "%s\n- %s" %
                (_("Several contacts have the same email: "), '\n- '.join(
                    partners_error_emails.mapped('email'))))
        if partners_error_user:
            error_msg.append("%s\n- %s" % (_(
                "Some contacts have the same email as an existing portal user:"******"To resolve this error, you can: \n"
                  "- Correct the emails of the relevant contacts\n"
                  "- Grant access only to contacts with unique emails"))
        return error_msg
Example #28
0
 def open_track_speakers_list(self):
     return {
         'name': _('Speakers'),
         'domain': [('id', 'in', self.mapped('partner_id').ids)],
         'view_type': 'form',
         'view_mode': 'kanban,form',
         'res_model': 'res.partner',
         'view_id': False,
         'type': 'ir.actions.act_window',
     }
Example #29
0
    def action_apply(self):
        self.env['res.partner'].check_access_rights('write')
        """ From selected partners, add corresponding users to chosen portal group. It either granted
            existing user, or create new one (and add it to the group).
        """
        error_msg = self.get_error_messages()
        if error_msg:
            raise UserError("\n\n".join(error_msg))

        for wizard_user in self.sudo().with_context(active_test=False):
            group_portal = wizard_user.wizard_id.portal_id
            if not group_portal.is_portal:
                raise UserError(
                    _('Group %s is not a portal') % group_portal.name)
            user = wizard_user.partner_id.user_ids[
                0] if wizard_user.partner_id.user_ids else None
            # update partner email, if a new one was introduced
            if wizard_user.partner_id.email != wizard_user.email:
                wizard_user.partner_id.write({'email': wizard_user.email})
            # add portal group to relative user of selected partners
            if wizard_user.in_portal:
                user_portal = None
                # create a user if necessary, and make sure it is in the portal group
                if not user:
                    if wizard_user.partner_id.company_id:
                        company_id = wizard_user.partner_id.company_id.id
                    else:
                        company_id = self.env[
                            'res.company']._company_default_get('res.users').id
                    user_portal = wizard_user.sudo().with_context(
                        company_id=company_id)._create_user()
                else:
                    user_portal = user
                wizard_user.write({'user_id': user_portal.id})
                if not wizard_user.user_id.active or group_portal not in wizard_user.user_id.groups_id:
                    wizard_user.user_id.write({
                        'active':
                        True,
                        'groups_id': [(4, group_portal.id)]
                    })
                    # prepare for the signup process
                    wizard_user.user_id.partner_id.signup_prepare()
                    wizard_user.with_context(active_test=True)._send_email()
                wizard_user.refresh()
            else:
                # remove the user (if it exists) from the portal group
                if user and group_portal in user.groups_id:
                    # if user belongs to portal only, deactivate it
                    if len(user.groups_id) <= 1:
                        user.write({
                            'groups_id': [(3, group_portal.id)],
                            'active': False
                        })
                    else:
                        user.write({'groups_id': [(3, group_portal.id)]})
Example #30
0
 def action_draft(self):
     for holiday in self:
         if not holiday.can_reset:
             raise UserError(
                 _('Only an HR Manager or the concerned employee can reset to draft.'
                   ))
         if holiday.state not in ['confirm', 'refuse']:
             raise UserError(
                 _('Leave request state must be "Refused" or "To Approve" in order to reset to Draft.'
                   ))
         holiday.write({
             'state': 'draft',
             'first_approver_id': False,
             'second_approver_id': False,
         })
         linked_requests = holiday.mapped('linked_request_ids')
         for linked_request in linked_requests:
             linked_request.action_draft()
         linked_requests.unlink()
     return True