Exemplo n.º 1
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
Exemplo n.º 2
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
Exemplo n.º 3
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 NobleCRM 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
        }
Exemplo n.º 4
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
Exemplo n.º 5
0
    def write(self, vals):
        has_been_posted = False
        for move in self:
            if move.company_id._is_accounting_unalterable():
                # write the hash and the secure_sequence_number when posting an account.move
                if vals.get('state') == 'posted':
                    has_been_posted = True

                # restrict the operation in case we are trying to write a forbidden field
                if (move.state == "posted"
                        and set(vals).intersection(MOVE_FIELDS)):
                    raise UserError(
                        _("According to the French law, you cannot modify a journal entry in order for its posted data to be updated or deleted. Unauthorized field: %s."
                          ) % ', '.join(MOVE_FIELDS))
                # restrict the operation in case we are trying to overwrite existing hash
                if (move.l10n_fr_hash and 'l10n_fr_hash' in vals) or (
                        move.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 accounting.'
                          ))
        res = super(AccountMove, self).write(vals)
        # write the hash and the secure_sequence_number when posting an account.move
        if has_been_posted:
            for move in self.filtered(
                    lambda m: m.company_id._is_accounting_unalterable() and
                    not (m.l10n_fr_secure_sequence_number or m.l10n_fr_hash)):
                new_number = move.company_id.l10n_fr_secure_sequence_id.next_by_id(
                )
                vals_hashing = {
                    'l10n_fr_secure_sequence_number': new_number,
                    'l10n_fr_hash': move._get_new_hash(new_number)
                }
                res |= super(AccountMove, move).write(vals_hashing)
        return res
Exemplo n.º 6
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 Infonoble.com (Only for NobleCRM Enterprise users).'''
              ) % report_dict)
Exemplo n.º 7
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
Exemplo n.º 8
0
    def _check_hash_integrity(self, company_id):
        """Checks that all posted moves have still the same data as when they were posted
        and raises an error with the result.
        """
        def build_move_info(move):
            entry_reference = _('(ref.: %s)')
            move_reference_string = move.ref and entry_reference % move.ref or ''
            return [move.name, move_reference_string]

        moves = self.search([('state', '=', 'posted'),
                             ('company_id', '=', company_id),
                             ('l10n_fr_secure_sequence_number', '!=', 0)],
                            order="l10n_fr_secure_sequence_number ASC")

        if not moves:
            raise UserError(
                _('There isn\'t any journal entry flagged for data inalterability yet for the company %s. This mechanism only runs for journal entries generated after the installation of the module France - Certification CGI 286 I-3 bis.'
                  ) % self.env.user.company_id.name)
        previous_hash = u''
        start_move_info = []
        for move in moves:
            if move.l10n_fr_hash != move._compute_hash(
                    previous_hash=previous_hash):
                raise UserError(
                    _('Corrupted data on journal entry with id %s.') % move.id)
            if not previous_hash:
                #save the date and sequence number of the first move hashed
                start_move_info = build_move_info(move)
            previous_hash = move.l10n_fr_hash
        end_move_info = build_move_info(move)

        report_dict = {
            'start_move_name': start_move_info[0],
            'start_move_ref': start_move_info[1],
            'end_move_name': end_move_info[0],
            'end_move_ref': end_move_info[1]
        }

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

                         The journal entries are guaranteed to be in their original and inalterable state
                         From: %(start_move_name)s %(start_move_ref)s
                         To: %(end_move_name)s %(end_move_ref)s

                         For this report to be legally meaningful, please download your certification from your customer account on Infonoble.com (Only for NobleCRM Enterprise users).'''
              ) % report_dict)
Exemplo n.º 9
0
 def _onchange_update_posted(self):
     if self.update_posted and self.company_id._is_accounting_unalterable():
         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)
Exemplo n.º 10
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
Exemplo n.º 11
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
Exemplo n.º 12
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
Exemplo n.º 13
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()
Exemplo n.º 14
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
Exemplo n.º 15
0
    def _convert_import_data(self, fields, options):
        """ Extracts the input BaseModel and fields list (with
            ``False``-y placeholders for fields to *not* import) into a
            format Model.import_data can use: a fields list without holes
            and the precisely matching data matrix

            :param list(str|bool): fields
            :returns: (data, fields)
            :rtype: (list(list(str)), list(str))
            :raises ValueError: in case the import data could not be converted
        """
        # Get indices for non-empty fields
        indices = [index for index, field in enumerate(fields) if field]
        if not indices:
            raise ValueError(_("You must configure at least one field to import"))
        # If only one index, itemgetter will return an atom rather
        # than a 1-tuple
        if len(indices) == 1:
            mapper = lambda row: [row[indices[0]]]
        else:
            mapper = operator.itemgetter(*indices)
        # Get only list of actually imported fields
        import_fields = [f for f in fields if f]

        rows_to_import = self._read_file(options)
        if options.get('headers'):
            rows_to_import = itertools.islice(rows_to_import, 1, None)
        data = [
            list(row) for row in pycompat.imap(mapper, rows_to_import)
            # don't try inserting completely empty rows (e.g. from
            # filtering out o2m fields)
            if any(row)
        ]

        return data, import_fields
Exemplo n.º 16
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
 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()
    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."))
Exemplo n.º 19
0
 def button_cancel(self):
     #by-pass the normal behavior/message that tells people can cancel a posted journal entry
     #if the journal allows it.
     if self.company_id._is_accounting_unalterable():
         raise UserError(
             _('You cannot modify a posted journal entry. This ensures its inalterability.'
               ))
     super(AccountMove, self).button_cancel()
Exemplo n.º 20
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
Exemplo n.º 21
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)
Exemplo n.º 22
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.move_id.state == 'posted' for l in self):
             raise UserError(
                 _("According to the French law, you cannot modify a journal item in order for its posted data to be updated or deleted. Unauthorized field: %s."
                   ) % ', '.join(LINE_FIELDS))
     return super(AccountMoveLine, self).write(vals)
Exemplo n.º 23
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
 def view_init(self, fields):
     """ Check some preconditions before the wizard executes. """
     for lead in self.env['crm.lead'].browse(
             self._context.get('active_ids', [])):
         if lead.probability == 100:
             raise UserError(
                 _("Closed/Dead leads cannot be converted into opportunities."
                   ))
     return False
Exemplo n.º 25
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')
     ]
Exemplo n.º 26
0
    def create_employee_from_applicant(self):
        """ Create an hr.employee from the hr.applicants """
        employee = False
        for applicant in self:
            contact_name = False
            if applicant.partner_id:
                address_id = applicant.partner_id.address_get(['contact'])['contact']
                contact_name = applicant.partner_id.name_get()[0][1]
            else :
                new_partner_id = self.env['res.partner'].create({
                    'is_company': False,
                    'name': applicant.partner_name,
                    'email': applicant.email_from,
                    'phone': applicant.partner_phone,
                    'mobile': applicant.partner_mobile
                })
                address_id = new_partner_id.address_get(['contact'])['contact']
            if applicant.job_id and (applicant.partner_name or contact_name):
                applicant.job_id.write({'no_of_hired_employee': applicant.job_id.no_of_hired_employee + 1})
                employee = self.env['hr.employee'].create({
                    'name': applicant.partner_name or contact_name,
                    'job_id': applicant.job_id.id,
                    'address_home_id': address_id,
                    'department_id': applicant.department_id.id or False,
                    'address_id': applicant.company_id and applicant.company_id.partner_id
                            and applicant.company_id.partner_id.id or False,
                    'work_email': applicant.department_id and applicant.department_id.company_id
                            and applicant.department_id.company_id.email or False,
                    'work_phone': applicant.department_id and applicant.department_id.company_id
                            and applicant.department_id.company_id.phone or False})
                applicant.write({'emp_id': employee.id})
                applicant.job_id.message_post(
                    body=_('New Employee %s Hired') % applicant.partner_name if applicant.partner_name else applicant.name,
                    subtype="hr_recruitment.mt_job_applicant_hired")
                employee._broadcast_welcome()
            else:
                raise UserError(_('You must define an Applied Job and a Contact Name for this applicant.'))

        employee_action = self.env.ref('hr.open_view_employee_list')
        dict_act_window = employee_action.read([])[0]
        if employee:
            dict_act_window['res_id'] = employee.id
        dict_act_window['view_mode'] = 'form,tree'
        return dict_act_window
Exemplo n.º 27
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',
     }
Exemplo n.º 28
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
Exemplo n.º 29
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)
Exemplo n.º 30
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)]})