예제 #1
0
 def action_in_progress(self):
     self.ensure_one()
     if not all(obj.line_ids for obj in self):
         raise UserError(
             _("You cannot confirm agreement '%s' because there is no product line."
               ) % self.name)
     if self.type_id.quantity_copy == 'none' and self.vendor_id:
         for requisition_line in self.line_ids:
             if requisition_line.price_unit <= 0.0:
                 raise UserError(
                     _('You cannot confirm the blanket order without price.'
                       ))
             if requisition_line.product_qty <= 0.0:
                 raise UserError(
                     _('You cannot confirm the blanket order without quantity.'
                       ))
             requisition_line.create_supplier_info()
         self.write({'state': 'ongoing'})
     else:
         self.write({'state': 'in_progress'})
     # Set the sequence number regarding the requisition type
     if self.name == 'New':
         if self.is_quantity_copy != 'none':
             self.name = self.env['ir.sequence'].next_by_code(
                 'purchase.requisition.purchase.tender')
         else:
             self.name = self.env['ir.sequence'].next_by_code(
                 'purchase.requisition.blanket.order')
예제 #2
0
    def act_update(self):
        '''
        Function called by the wizard.
        '''
        flag, gengo = self.gengo_authentication()
        if not flag:
            raise UserError(gengo)
        for wizard in self:
            supported_langs = self.env[
                'ir.translation']._get_all_supported_languages()
            language = self.env[
                'ir.translation']._get_gengo_corresponding_language(
                    wizard.lang_id.code)
            if language not in supported_langs:
                raise UserError(
                    _('This language is not supported by the Gengo translation services.'
                      ))

            ctx = self.env.context.copy()
            ctx['gengo_language'] = wizard.lang_id.id
            if wizard.sync_limit > 200 or wizard.sync_limit < 1:
                raise UserError(
                    _('The number of terms to sync should be between 1 to 200 to work with Gengo translation services.'
                      ))
            if wizard.sync_type in ['send', 'both']:
                self.with_context(ctx)._sync_request(wizard.sync_limit)
            if wizard.sync_type in ['receive', 'both']:
                self.with_context(ctx)._sync_response(wizard.sync_limit)
        return {'type': 'ir.actions.act_window_close'}
예제 #3
0
    def _create_invoice_from_xml(self, attachment):
        decoders = self._get_xml_decoders()

        # Convert attachment -> etree
        content = base64.b64decode(attachment.datas)
        try:
            tree = etree.fromstring(content)
        except Exception:
            raise UserError(
                _('The xml file is badly formatted : {}').format(
                    attachment.name))

        for xml_type, check_func, decode_func in decoders:
            check_res = check_func(tree, attachment.name)

            if check_res.get('flag') and not check_res.get('error'):
                invoice_ids = decode_func(tree)
                if invoice_ids:
                    invoice_ids._remove_ocr_option()
                    break

        try:
            return invoice_ids
        except UnboundLocalError:
            raise UserError(
                _('No decoder was found for the xml file: {}. The file is badly formatted, not supported or the decoder is not installed'
                  ).format(attachment.name))
예제 #4
0
 def _onchange_picking_id(self):
     move_dest_exists = False
     product_return_moves = [(5, )]
     if self.picking_id and self.picking_id.state != 'done':
         raise UserError(_("You may only return Done pickings."))
     for move in self.picking_id.move_lines:
         if move.state == 'cancel':
             continue
         if move.scrapped:
             continue
         if move.move_dest_ids:
             move_dest_exists = True
         product_return_moves.append(
             (0, 0,
              self._prepare_stock_return_picking_line_vals_from_move(move)))
     if self.picking_id and not product_return_moves:
         raise UserError(
             _("No products to return (only lines in Done state and not fully returned yet can be returned)."
               ))
     if self.picking_id:
         self.product_return_moves = product_return_moves
         self.move_dest_exists = move_dest_exists
         self.parent_location_id = self.picking_id.picking_type_id.warehouse_id and self.picking_id.picking_type_id.warehouse_id.view_location_id.id or self.picking_id.location_id.location_id.id
         self.original_location_id = self.picking_id.location_id.id
         location_id = self.picking_id.location_id.id
         if self.picking_id.picking_type_id.return_picking_type_id.default_location_dest_id.return_location:
             location_id = self.picking_id.picking_type_id.return_picking_type_id.default_location_dest_id.id
         self.location_id = location_id
예제 #5
0
 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.'))
     self.mapped('operations').write({'state': 'cancel'})
     return self.write({'state': 'cancel'})
예제 #6
0
파일: partner.py 프로젝트: malakhA/coffice
    def create_membership_invoice(self, product, amount):
        """ Create Customer Invoice of Membership for partners.
        """
        invoice_vals_list = []
        for partner in self:
            addr = partner.address_get(['invoice'])
            if partner.free_member:
                raise UserError(_("Partner is a free Member."))
            if not addr.get('invoice', False):
                raise UserError(
                    _("Partner doesn't have an address to make the invoice."))

            invoice_vals_list.append({
                'type':
                'out_invoice',
                'partner_id':
                partner.id,
                'invoice_line_ids': [(0, None, {
                    'product_id': product.id,
                    'quantity': 1,
                    'price_unit': amount,
                    'tax_ids': [(6, 0, product.taxes_id.ids)]
                })]
            })

        return self.env['account.move'].create(invoice_vals_list)
예제 #7
0
    def _update_move_lines(self):
        """ update a move line to save the workorder line data"""
        self.ensure_one()
        if self.lot_id:
            move_lines = self.move_id.move_line_ids.filtered(
                lambda ml: ml.lot_id == self.lot_id and not ml.lot_produced_ids
            )
        else:
            move_lines = self.move_id.move_line_ids.filtered(
                lambda ml: not ml.lot_id and not ml.lot_produced_ids)

        # Sanity check: if the product is a serial number and `lot` is already present in the other
        # consumed move lines, raise.
        if self.product_id.tracking != 'none' and not self.lot_id:
            raise UserError(
                _('Please enter a lot or serial number for %s !' %
                  self.product_id.display_name))

        if self.lot_id and self.product_id.tracking == 'serial' and self.lot_id in self.move_id.move_line_ids.filtered(
                lambda ml: ml.qty_done).mapped('lot_id'):
            raise UserError(
                _('You cannot consume the same serial number twice. Please correct the serial numbers encoded.'
                  ))

        # Update reservation and quantity done
        for ml in move_lines:
            rounding = ml.product_uom_id.rounding
            if float_compare(self.qty_done, 0,
                             precision_rounding=rounding) <= 0:
                break
            quantity_to_process = min(self.qty_done,
                                      ml.product_uom_qty - ml.qty_done)
            self.qty_done -= quantity_to_process

            new_quantity_done = (ml.qty_done + quantity_to_process)
            # if we produce less than the reserved quantity to produce the finished products
            # in different lots,
            # we create different component_move_lines to record which one was used
            # on which lot of finished product
            if float_compare(new_quantity_done,
                             ml.product_uom_qty,
                             precision_rounding=rounding) >= 0:
                ml.write({
                    'qty_done': new_quantity_done,
                    'lot_produced_ids': self._get_produced_lots(),
                })
            else:
                new_qty_reserved = ml.product_uom_qty - new_quantity_done
                default = {
                    'product_uom_qty': new_quantity_done,
                    'qty_done': new_quantity_done,
                    'lot_produced_ids': self._get_produced_lots(),
                }
                ml.copy(default=default)
                ml.with_context(bypass_reservation_update=True).write({
                    'product_uom_qty':
                    new_qty_reserved,
                    'qty_done':
                    0
                })
예제 #8
0
 def action_send_mail(self):
     self.ensure_one()
     if not self.env.user.has_group('hr.group_hr_manager'):
         raise UserError(
             _("You don't have the right to do this. Please contact an Administrator."
               ))
     if not self.work_email:
         raise UserError(
             _("There is no professional email address for this employee."))
     template = self.env.ref('hr_presence.mail_template_presence', False)
     compose_form = self.env.ref('mail.email_compose_message_wizard_form',
                                 False)
     ctx = dict(
         default_model="hr.employee",
         default_res_id=self.id,
         default_use_template=bool(template),
         default_template_id=template.id,
         default_composition_mode='comment',
         default_is_log=True,
         custom_layout='mail.mail_notification_light',
     )
     return {
         'name': _('Compose Email'),
         'type': 'ir.actions.act_window',
         'view_mode': 'form',
         'res_model': 'mail.compose.message',
         'views': [(compose_form.id, 'form')],
         'view_id': compose_form.id,
         'target': 'new',
         'context': ctx,
     }
예제 #9
0
파일: ir_model.py 프로젝트: malakhA/coffice
 def write(self, vals):
     if self and ('is_mail_thread' in vals or 'is_mail_activity' in vals
                  or 'is_mail_blacklist' in vals):
         if not all(rec.state == 'manual' for rec in self):
             raise UserError(_('Only custom models can be modified.'))
         if 'is_mail_thread' in vals and not all(
                 rec.is_mail_thread <= vals['is_mail_thread']
                 for rec in self):
             raise UserError(
                 _('Field "Mail Thread" cannot be changed to "False".'))
         if 'is_mail_activity' in vals and not all(
                 rec.is_mail_activity <= vals['is_mail_activity']
                 for rec in self):
             raise UserError(
                 _('Field "Mail Activity" cannot be changed to "False".'))
         if 'is_mail_blacklist' in vals and not all(
                 rec.is_mail_blacklist <= vals['is_mail_blacklist']
                 for rec in self):
             raise UserError(
                 _('Field "Mail Blacklist" cannot be changed to "False".'))
         res = super(IrModel, self).write(vals)
         self.flush()
         # setup models; this reloads custom models in registry
         self.pool.setup_models(self._cr)
         # update database schema of models
         models = self.pool.descendants(self.mapped('model'), '_inherits')
         self.pool.init_models(
             self._cr, models, dict(self._context,
                                    update_custom_fields=True))
     else:
         res = super(IrModel, self).write(vals)
     return res
예제 #10
0
    def write(self, values):
        """Override to:
        - Add constraints to prevent doing changes that are not supported such
            as modifying the template or the attribute of existing lines.
        - Clean up related values and related variants when archiving or when
            updating `value_ids`.
        """
        if 'product_tmpl_id' in values:
            for ptal in self:
                if ptal.product_tmpl_id.id != values['product_tmpl_id']:
                    raise UserError(
                        _("You cannot move the attribute %s from the product %s to the product %s.") %
                        (ptal.attribute_id.display_name, ptal.product_tmpl_id.display_name, values['product_tmpl_id'])
                    )

        if 'attribute_id' in values:
            for ptal in self:
                if ptal.attribute_id.id != values['attribute_id']:
                    raise UserError(
                        _("On the product %s you cannot transform the attribute %s into the attribute %s.") %
                        (ptal.product_tmpl_id.display_name, ptal.attribute_id.display_name, values['attribute_id'])
                    )
        # Remove all values while archiving to make sure the line is clean if it
        # is ever activated again.
        if not values.get('active', True):
            values['value_ids'] = [(5, 0, 0)]
        res = super(ProductTemplateAttributeLine, self).write(values)
        if 'active' in values:
            self.env['product.template'].invalidate_cache(fnames=['attribute_line_ids'])
        # If coming from `create`, no need to update the values and the variants
        # before all lines are created.
        if self.env.context.get('update_product_template_attribute_values', True):
            self._update_product_template_attribute_values()
        return res
예제 #11
0
    def action_send_sms(self):
        self.ensure_one()
        if not self.env.user.has_group('hr.group_hr_manager'):
            raise UserError(
                _("You don't have the right to do this. Please contact an Administrator."
                  ))
        if not self.mobile_phone:
            raise UserError(
                _("There is no professional mobile for this employee."))

        context = dict(self.env.context)
        context.update(default_res_model='hr.employee',
                       default_res_id=self.id,
                       default_composition_mode='comment',
                       default_number_field_name='mobile_phone')

        template = self.env.ref('hr_presence.sms_template_presence', False)
        if not template:
            context['default_body'] = _(
                """Exception made if there was a mistake of ours, it seems that you are not at your office and there is not request of leaves from you.
Please, take appropriate measures in order to carry out this work absence.
Do not hesitate to contact your manager or the human resource department.""")
        else:
            context['default_template_id'] = template.id

        return {
            "type": "ir.actions.act_window",
            "res_model": "sms.composer",
            "view_mode": 'form',
            "context": context,
            "name": "Send SMS Text Message",
            "target": "new",
        }
예제 #12
0
    def action_send_survey(self):
        """ Open a window to compose an email, pre-filled with the survey message """
        # Ensure that this survey has at least one page with at least one question.
        if (not self.page_ids and self.questions_layout
                == 'page_per_section') or not self.question_ids:
            raise UserError(
                _('You cannot send an invitation for a survey that has no questions.'
                  ))

        if self.state == 'closed':
            raise UserError(
                _("You cannot send invitations for closed surveys."))

        template = self.env.ref('survey.mail_template_user_input_invite',
                                raise_if_not_found=False)

        local_context = dict(
            self.env.context,
            default_survey_id=self.id,
            default_use_template=bool(template),
            default_template_id=template and template.id or False,
            notif_layout='mail.mail_notification_light',
        )
        return {
            'type': 'ir.actions.act_window',
            'view_mode': 'form',
            'res_model': 'survey.invite',
            'target': 'new',
            'context': local_context,
        }
예제 #13
0
    def default_get(self, fields):
        rec = super(payment_register, self).default_get(fields)
        active_ids = self._context.get('active_ids')
        if not active_ids:
            return rec
        invoices = self.env['account.move'].browse(active_ids)

        # Check all invoices are open
        if any(invoice.state != 'posted' or invoice.invoice_payment_state != 'not_paid' or not invoice.is_invoice() for invoice in invoices):
            raise UserError(_("You can only register payments for open invoices"))
        # Check all invoices are inbound or all invoices are outbound
        outbound_list = [invoice.is_outbound() for invoice in invoices]
        first_outbound = invoices[0].is_outbound()
        if any(x != first_outbound for x in outbound_list):
            raise UserError(_("You can only register at the same time for payment that are all inbound or all outbound"))
        if any(inv.company_id != invoices[0].company_id for inv in invoices):
            raise UserError(_("You can only register at the same time for payment that are all from the same company"))
        if 'invoice_ids' not in rec:
            rec['invoice_ids'] = [(6, 0, invoices.ids)]
        if 'journal_id' not in rec:
            rec['journal_id'] = self.env['account.journal'].search([('company_id', '=', self.env.company.id), ('type', 'in', ('bank', 'cash'))], limit=1).id
        if 'payment_method_id' not in rec:
            if invoices[0].is_inbound():
                domain = [('payment_type', '=', 'inbound')]
            else:
                domain = [('payment_type', '=', 'outbound')]
            rec['payment_method_id'] = self.env['account.payment.method'].search(domain, limit=1).id
        return rec
예제 #14
0
 def action_validate(self):
     if not self.exists():
         return
     self.ensure_one()
     if not self.user_has_groups('stock.group_stock_manager'):
         raise UserError(_("Only a stock manager can validate an inventory adjustment."))
     if self.state != 'confirm':
         raise UserError(_(
             "You can't validate the inventory '%s', maybe this inventory " +
             "has been already validated or isn't ready.") % (self.name))
     inventory_lines = self.line_ids.filtered(lambda l: l.product_id.tracking in ['lot', 'serial'] and not l.prod_lot_id and l.theoretical_qty != l.product_qty)
     lines = self.line_ids.filtered(lambda l: float_compare(l.product_qty, 1, precision_rounding=l.product_uom_id.rounding) > 0 and l.product_id.tracking == 'serial' and l.prod_lot_id)
     if inventory_lines and not lines:
         wiz_lines = [(0, 0, {'product_id': product.id, 'tracking': product.tracking}) for product in inventory_lines.mapped('product_id')]
         wiz = self.env['stock.track.confirmation'].create({'inventory_id': self.id, 'tracking_line_ids': wiz_lines})
         return {
             'name': _('Tracked Products in Inventory Adjustment'),
             'type': 'ir.actions.act_window',
             'view_mode': 'form',
             'views': [(False, 'form')],
             'res_model': 'stock.track.confirmation',
             'target': 'new',
             'res_id': wiz.id,
         }
     self._action_done()
     self.line_ids._check_company()
     self._check_company()
     return True
예제 #15
0
 def _run(self, records):
     for box in self:
         for record in records:
             if not record.journal_id:
                 raise UserError(_("Please check that the field 'Journal' is set on the Bank Statement"))
             if not record.journal_id.company_id.transfer_account_id:
                 raise UserError(_("Please check that the field 'Transfer Account' is set on the company."))
             box._create_bank_statement_line(record)
     return {}
예제 #16
0
    def test_smtp_connection(self):
        for server in self:
            smtp = False
            try:
                smtp = self.connect(mail_server_id=server.id)
                # simulate sending an email from current user's address - without sending it!
                email_from, email_to = self.env.user.email, '*****@*****.**'
                if not email_from:
                    raise UserError(
                        _('Please configure an email on the current user to simulate '
                          'sending an email message via this outgoing server'))
                # Testing the MAIL FROM step should detect sender filter problems
                (code, repl) = smtp.mail(email_from)
                if code != 250:
                    raise UserError(
                        _('The server refused the sender address (%(email_from)s) '
                          'with error %(repl)s') % locals())
                # Testing the RCPT TO step should detect most relaying problems
                (code, repl) = smtp.rcpt(email_to)
                if code not in (250, 251):
                    raise UserError(
                        _('The server refused the test recipient (%(email_to)s) '
                          'with error %(repl)s') % locals())
                # Beginning the DATA step should detect some deferred rejections
                # Can't use self.data() as it would actually send the mail!
                smtp.putcmd("data")
                (code, repl) = smtp.getreply()
                if code != 354:
                    raise UserError(
                        _('The server refused the test connection '
                          'with error %(repl)s') % locals())
            except UserError as e:
                # let UserErrors (messages) bubble up
                raise e
            except Exception as e:
                raise UserError(
                    _("Connection Test Failed! Here is what we got instead:\n %s"
                      ) % ustr(e))
            finally:
                try:
                    if smtp:
                        smtp.close()
                except Exception:
                    # ignored, just a consequence of the previous exception
                    pass

        title = _("Connection Test Succeeded!")
        message = _("Everything seems properly set up!")
        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': title,
                'message': message,
                'sticky': False,
            }
        }
예제 #17
0
    def write(self, values):
        if 'company_id' in values:
            for location in self:
                if location.company_id.id != values['company_id']:
                    raise UserError(
                        _("Changing the company of this record is forbidden at this point, you should rather archive it and create a new one."
                          ))
        if 'usage' in values and values['usage'] == 'view':
            if self.mapped('quant_ids'):
                raise UserError(
                    _("This location's usage cannot be changed to view as it contains products."
                      ))
        if 'usage' in values or 'scrap_location' in values:
            modified_locations = self.filtered(
                lambda l: any(l[f] != values[f] if f in values else False
                              for f in {'usage', 'scrap_location'}))
            reserved_quantities = self.env['stock.move.line'].search_count([
                ('location_id', 'in', modified_locations.ids),
                ('product_qty', '>', 0),
            ])
            if reserved_quantities:
                raise UserError(
                    _("You cannot change the location type or its use as a scrap"
                      " location as there are products reserved in this location."
                      " Please unreserve the products first."))
        if 'active' in values:
            if values['active'] == False:
                for location in self:
                    warehouses = self.env['stock.warehouse'].search([
                        ('active', '=', True), '|',
                        ('lot_stock_id', '=', location.id),
                        ('view_location_id', '=', location.id)
                    ])
                    if warehouses:
                        raise UserError(
                            _("You cannot archive the location %s as it is"
                              " used by your warehouse %s") %
                            (location.display_name,
                             warehouses[0].display_name))

            if not self.env.context.get('do_not_check_quant'):
                children_location = self.env['stock.location'].with_context(
                    active_test=False).search([('id', 'child_of', self.ids)])
                internal_children_locations = children_location.filtered(
                    lambda l: l.usage == 'internal')
                children_quants = self.env['stock.quant'].search([
                    ('quantity', '!=', 0), ('reserved_quantity', '!=', 0),
                    ('location_id', 'in', internal_children_locations.ids)
                ])
                if children_quants and values['active'] == False:
                    raise UserError(
                        _('You still have some product in locations %s') %
                        (','.join(children_quants.mapped('location_id.name'))))
                else:
                    super(Location, children_location - self).with_context(
                        do_not_check_quant=True).write(values)
        return super(Location, self).write(values)
예제 #18
0
 def _assert_primary_email(self):
     if not hasattr(self, "_primary_email") or not isinstance(
             self._primary_email, str):
         raise UserError(
             _('Invalid primary email field on model %s') % self._name)
     if self._primary_email not in self._fields or self._fields[
             self._primary_email].type != 'char':
         raise UserError(
             _('Invalid primary email field on model %s') % self._name)
예제 #19
0
    def post(self):
        """ Create the journal items for the payment and update the payment's state to 'posted'.
            A journal entry is created containing an item in the source liquidity account (selected journal's default_debit or default_credit)
            and another in the destination reconcilable account (see _compute_destination_account_id).
            If invoice_ids is not empty, there will be one reconcilable move line per invoice to reconcile with.
            If the payment is a transfer, a second journal entry is created in the destination journal to receive money from the transfer account.
        """
        AccountMove = self.env['account.move'].with_context(default_type='entry')
        for rec in self:

            if rec.state != 'draft':
                raise UserError(_("Only a draft payment can be posted."))

            if any(inv.state != 'posted' for inv in rec.invoice_ids):
                raise ValidationError(_("The payment cannot be processed because the invoice is not open!"))

            # keep the name in case of a payment reset to draft
            if not rec.name:
                # Use the right sequence to set the name
                if rec.payment_type == 'transfer':
                    sequence_code = 'account.payment.transfer'
                else:
                    if rec.partner_type == 'customer':
                        if rec.payment_type == 'inbound':
                            sequence_code = 'account.payment.customer.invoice'
                        if rec.payment_type == 'outbound':
                            sequence_code = 'account.payment.customer.refund'
                    if rec.partner_type == 'supplier':
                        if rec.payment_type == 'inbound':
                            sequence_code = 'account.payment.supplier.refund'
                        if rec.payment_type == 'outbound':
                            sequence_code = 'account.payment.supplier.invoice'
                rec.name = self.env['ir.sequence'].next_by_code(sequence_code, sequence_date=rec.payment_date)
                if not rec.name and rec.payment_type != 'transfer':
                    raise UserError(_("You have to define a sequence for %s in your company.") % (sequence_code,))

            moves = AccountMove.create(rec._prepare_payment_moves())
            moves.filtered(lambda move: move.journal_id.post_at != 'bank_rec').post()

            # Update the state / move before performing any reconciliation.
            move_name = self._get_move_name_transfer_separator().join(moves.mapped('name'))
            rec.write({'state': 'posted', 'move_name': move_name})

            if rec.payment_type in ('inbound', 'outbound'):
                # ==== 'inbound' / 'outbound' ====
                if rec.invoice_ids:
                    (moves[0] + rec.invoice_ids).line_ids \
                        .filtered(lambda line: not line.reconciled and line.account_id == rec.destination_account_id)\
                        .reconcile()
            elif rec.payment_type == 'transfer':
                # ==== 'transfer' ====
                moves.mapped('line_ids')\
                    .filtered(lambda line: line.account_id == rec.company_id.transfer_account_id)\
                    .reconcile()

        return True
예제 #20
0
파일: event.py 프로젝트: malakhA/coffice
 def button_reg_close(self):
     """ Close Registration """
     for registration in self:
         today = fields.Datetime.now()
         if registration.event_id.date_begin <= today and registration.event_id.state == 'confirm':
             registration.write({'state': 'done', 'date_closed': today})
         elif registration.event_id.state == 'draft':
             raise UserError(_("You must wait the event confirmation before doing this action."))
         else:
             raise UserError(_("You must wait the event starting day before doing this action."))
예제 #21
0
 def process_coupon(self):
     """
     Apply the entered coupon code if valid, raise an UserError otherwise.
     """
     sales_order = self.env['sale.order'].browse(
         self.env.context.get('active_id'))
     error_status = self.apply_coupon(sales_order, self.coupon_code)
     if error_status.get('error', False):
         raise UserError(error_status.get('error', False))
     if error_status.get('not_found', False):
         raise UserError(error_status.get('not_found', False))
예제 #22
0
 def get_access_token(self, scope=None):
     Config = self.env['ir.config_parameter'].sudo()
     google_drive_refresh_token = Config.get_param(
         'google_drive_refresh_token')
     user_is_admin = self.env.is_admin()
     if not google_drive_refresh_token:
         if user_is_admin:
             dummy, action_id = self.env[
                 'ir.model.data'].get_object_reference(
                     'base_setup', 'action_general_configuration')
             msg = _(
                 "There is no refresh code set for Google Drive. You can set it up from the configuration panel."
             )
             raise RedirectWarning(msg, action_id,
                                   _('Go to the configuration panel'))
         else:
             raise UserError(
                 _("Google Drive is not yet configured. Please contact your administrator."
                   ))
     google_drive_client_id = Config.get_param('google_drive_client_id')
     google_drive_client_secret = Config.get_param(
         'google_drive_client_secret')
     #For Getting New Access Token With help of old Refresh Token
     data = {
         'client_id': google_drive_client_id,
         'refresh_token': google_drive_refresh_token,
         'client_secret': google_drive_client_secret,
         'grant_type': "refresh_token",
         'scope': scope or 'https://www.googleapis.com/auth/drive'
     }
     headers = {"Content-type": "application/x-www-form-urlencoded"}
     try:
         req = requests.post(GOOGLE_TOKEN_ENDPOINT,
                             data=data,
                             headers=headers,
                             timeout=TIMEOUT)
         req.raise_for_status()
     except requests.HTTPError:
         if user_is_admin:
             dummy, action_id = self.env[
                 'ir.model.data'].get_object_reference(
                     'base_setup', 'action_general_configuration')
             msg = _(
                 "Something went wrong during the token generation. Please request again an authorization code ."
             )
             raise RedirectWarning(msg, action_id,
                                   _('Go to the configuration panel'))
         else:
             raise UserError(
                 _("Google Drive is not yet configured. Please contact your administrator."
                   ))
     return req.json().get('access_token')
예제 #23
0
 def post(self):
     for rec in self.filtered(lambda x: x.l10n_latam_use_documents and
                              (not x.name or x.name == '/')):
         if not rec.l10n_latam_sequence_id:
             raise UserError(
                 _('No sequence or document number linked to invoice id %s')
                 % rec.id)
         if rec.type in ('in_receipt', 'out_receipt'):
             raise UserError(
                 _('We do not accept the usage of document types on receipts yet. '
                   ))
         rec.l10n_latam_document_number = rec.l10n_latam_sequence_id.next_by_id(
         )
     return super().post()
예제 #24
0
 def write(self, values):
     if 'production_id' in values:
         raise UserError(
             _('You cannot link this work order to another manufacturing order.'
               ))
     if 'workcenter_id' in values:
         for workorder in self:
             if workorder.workcenter_id.id != values['workcenter_id']:
                 if workorder.state in ('progress', 'done', 'cancel'):
                     raise UserError(
                         _('You cannot change the workcenter of a work order that is in progress or done.'
                           ))
                 workorder.leave_id.resource_id = self.env[
                     'mrp.workcenter'].browse(
                         values['workcenter_id']).resource_id
     if list(values.keys()) != ['time_ids'] and any(
             workorder.state == 'done' for workorder in self):
         raise UserError(_('You can not change the finished work order.'))
     if 'date_planned_start' in values or 'date_planned_finished' in values:
         for workorder in self:
             start_date = fields.Datetime.to_datetime(
                 values.get(
                     'date_planned_start')) or workorder.date_planned_start
             end_date = fields.Datetime.to_datetime(
                 values.get('date_planned_finished')
             ) or workorder.date_planned_finished
             if start_date and end_date and start_date > end_date:
                 raise UserError(
                     _('The planned end date of the work order cannot be prior to the planned start date, please correct this to save the work order.'
                       ))
             # Update MO dates if the start date of the first WO or the
             # finished date of the last WO is update.
             if workorder == workorder.production_id.workorder_ids[
                     0] and 'date_planned_start' in values:
                 workorder.production_id.with_context(
                     force_date=True).write({
                         'date_planned_start':
                         fields.Datetime.to_datetime(
                             values['date_planned_start'])
                     })
             if workorder == workorder.production_id.workorder_ids[
                     -1] and 'date_planned_finished' in values:
                 workorder.production_id.with_context(
                     force_date=True).write({
                         'date_planned_finished':
                         fields.Datetime.to_datetime(
                             values['date_planned_finished'])
                     })
     return super(MrpWorkorder, self).write(values)
예제 #25
0
    def button_start(self):
        self.ensure_one()
        # As button_start is automatically called in the new view
        if self.state in ('done', 'cancel'):
            return True

        # Need a loss in case of the real time exceeding the expected
        timeline = self.env['mrp.workcenter.productivity']
        if self.duration < self.duration_expected:
            loss_id = self.env['mrp.workcenter.productivity.loss'].search(
                [('loss_type', '=', 'productive')], limit=1)
            if not len(loss_id):
                raise UserError(
                    _("You need to define at least one productivity loss in the category 'Productivity'. Create one from the Manufacturing app, menu: Configuration / Productivity Losses."
                      ))
        else:
            loss_id = self.env['mrp.workcenter.productivity.loss'].search(
                [('loss_type', '=', 'performance')], limit=1)
            if not len(loss_id):
                raise UserError(
                    _("You need to define at least one productivity loss in the category 'Performance'. Create one from the Manufacturing app, menu: Configuration / Productivity Losses."
                      ))
        if self.production_id.state != 'progress':
            self.production_id.write({
                'date_start': datetime.now(),
            })
        timeline.create({
            'workorder_id': self.id,
            'workcenter_id': self.workcenter_id.id,
            'description': _('Time Tracking: ') + self.env.user.name,
            'loss_id': loss_id[0].id,
            'date_start': datetime.now(),
            'user_id':
            self.env.user.id,  # FIXME sle: can be inconsistent with company_id
            'company_id': self.company_id.id,
        })
        if self.state == 'progress':
            return True
        else:
            start_date = datetime.now()
            vals = {
                'state': 'progress',
                'date_start': start_date,
                'date_planned_start': start_date,
            }
            if self.date_planned_finished < start_date:
                vals['date_planned_finished'] = start_date
            return self.write(vals)
예제 #26
0
    def upgrade_module(self):
        Module = self.env['ir.module.module']

        # install/upgrade: double-check preconditions
        mods = Module.search([('state', 'in', ['to upgrade', 'to install'])])
        if mods:
            query = """ SELECT d.name
                        FROM ir_module_module m
                        JOIN ir_module_module_dependency d ON (m.id = d.module_id)
                        LEFT JOIN ir_module_module m2 ON (d.name = m2.name)
                        WHERE m.id in %s and (m2.state IS NULL or m2.state IN %s) """
            self._cr.execute(query, (tuple(mods.ids), ('uninstalled', )))
            unmet_packages = [row[0] for row in self._cr.fetchall()]
            if unmet_packages:
                raise UserError(
                    _('The following modules are not installed or unknown: %s')
                    % ('\n\n' + '\n'.join(unmet_packages)))

            mods.download()

        # terminate transaction before re-creating cursor below
        self._cr.commit()
        api.Environment.reset()
        coffice.modules.registry.Registry.new(self._cr.dbname,
                                              update_module=True)

        return {'type': 'ir.actions.act_window_close'}
예제 #27
0
    def _check_global_default(self, vals, matching_filters):
        """ _check_global_default(dict, list(dict), dict) -> None

        Checks if there is a global default for the model_id requested.

        If there is, and the default is different than the record being written
        (-> we're not updating the current global default), raise an error
        to avoid users unknowingly overwriting existing global defaults (they
        have to explicitly remove the current default before setting a new one)

        This method should only be called if ``vals`` is trying to set
        ``is_default``

        :raises coffice.exceptions.UserError: if there is an existing default and
                                            we're not updating it
        """
        domain = self._get_action_domain(vals.get('action_id'))
        defaults = self.search(domain + [
            ('model_id', '=', vals['model_id']),
            ('user_id', '=', False),
            ('is_default', '=', True),
        ])

        if not defaults:
            return
        if matching_filters and (matching_filters[0]['id'] == defaults.id):
            return

        raise UserError(_("There is already a shared filter set as default for %(model)s, delete or change it before setting a new default") % {'model': vals.get('model_id')})
예제 #28
0
    def _get_report_values(self, docids, data=None):
        if not data.get('form'):
            raise UserError(
                _("Form content is missing, this report cannot be printed."))

        target_move = data['form'].get('target_move', 'all')
        sort_selection = data['form'].get('sort_selection', 'date')

        res = {}
        for journal in data['form']['journal_ids']:
            res[journal] = self.with_context(data['form'].get(
                'used_context', {})).lines(target_move, journal,
                                           sort_selection, data)
        return {
            'doc_ids':
            data['form']['journal_ids'],
            'doc_model':
            self.env['account.journal'],
            'data':
            data,
            'docs':
            self.env['account.journal'].browse(data['form']['journal_ids']),
            'time':
            time,
            'lines':
            res,
            'sum_credit':
            self._sum_credit,
            'sum_debit':
            self._sum_debit,
            'get_taxes':
            self._get_taxes,
            'company_id':
            self.env['res.company'].browse(data['form']['company_id'][0]),
        }
예제 #29
0
    def _website_product_id_change(self, order_id, product_id, qty=0):
        order = self.env['sale.order'].sudo().browse(order_id)
        if self._context.get('pricelist') != order.pricelist_id.id:
            self = self.with_context(pricelist=order.pricelist_id.id)

        values = super(SaleOrder, self)._website_product_id_change(order_id, product_id, qty=qty)
        event_ticket_id = None
        if self.env.context.get("event_ticket_id"):
            event_ticket_id = self.env.context.get("event_ticket_id")
        else:
            product = self.env['product.product'].browse(product_id)
            if product.event_ticket_ids:
                event_ticket_id = product.event_ticket_ids[0].id

        if event_ticket_id:
            ticket = self.env['event.event.ticket'].browse(event_ticket_id)
            if product_id != ticket.product_id.id:
                raise UserError(_("The ticket doesn't match with this product."))

            values['product_id'] = ticket.product_id.id
            values['event_id'] = ticket.event_id.id
            values['event_ticket_id'] = ticket.id
            if order.pricelist_id.discount_policy == 'without_discount':
                values['price_unit'] = ticket.price
            else:
                values['price_unit'] = ticket.price_reduce
            values['name'] = ticket.get_ticket_multiline_description_sale()

        # avoid writing related values that end up locking the product record
        values.pop('event_ok', None)

        return values
예제 #30
0
파일: main.py 프로젝트: malakhA/coffice
 def attachment_update(self,
                       attachment,
                       name=None,
                       width=0,
                       height=0,
                       quality=0,
                       copy=False,
                       **kwargs):
     if attachment.type == 'url':
         raise UserError(
             _("You cannot change the quality, the width or the name of an URL attachment."
               ))
     if copy:
         attachment = attachment.copy()
     data = {}
     if name:
         data['name'] = name
     try:
         data['datas'] = tools.image_process(attachment.datas,
                                             size=(width, height),
                                             quality=quality)
     except UserError:
         pass  # not an image
     attachment.write(data)
     return attachment._get_media_info()