Esempio n. 1
0
    def web_login(self, *args, **kw):
        ensure_db()
        if request.httprequest.method == 'GET' and request.session.uid and request.params.get(
                'redirect'):
            # Redirect if already logged in and redirect param is present
            return http.redirect_with_hash(request.params.get('redirect'))
        providers = self.list_providers()

        response = super(OAuthLogin, self).web_login(*args, **kw)
        if response.is_qweb:
            error = request.params.get('oauth_error')
            if error == '1':
                error = _("Sign up is not allowed on this database.")
            elif error == '2':
                error = _("Access Denied")
            elif error == '3':
                error = _(
                    "You do not have access to this database or your invitation has expired. Please ask for an invitation and be sure to follow the link in your invitation email."
                )
            else:
                error = None

            response.qcontext['providers'] = providers
            if error:
                response.qcontext['error'] = error

        return response
Esempio n. 2
0
    def _onchange_product_id_check_availability(self):
        if not self.product_id or not self.product_uom_qty or not self.product_uom:
            self.product_packaging = False
            return {}
        if self.product_id.type == 'product':
            precision = self.env['decimal.precision'].precision_get(
                'Product Unit of Measure')
            product = self.product_id.with_context(
                warehouse=self.order_id.warehouse_id.id,
                lang=self.order_id.partner_id.lang or self.env.user.lang
                or 'en_US')
            product_qty = self.product_uom._compute_quantity(
                self.product_uom_qty, self.product_id.uom_id)
            if float_compare(product.virtual_available,
                             product_qty,
                             precision_digits=precision) == -1:
                is_available = self._check_routing()
                if not is_available:
                    message =  _('You plan to sell %s %s but you only have %s %s available in %s warehouse.') % \
                            (self.product_uom_qty, self.product_uom.name, product.virtual_available, product.uom_id.name, self.order_id.warehouse_id.name)
                    # We check if some products are available in other warehouses.
                    if float_compare(product.virtual_available,
                                     self.product_id.virtual_available,
                                     precision_digits=precision) == -1:
                        message += _('\nThere are %s %s available accross all warehouses.') % \
                                (self.product_id.virtual_available, product.uom_id.name)

                    warning_mess = {
                        'title': _('Not enough inventory!'),
                        'message': message
                    }
                    return {'warning': warning_mess}
        return {}
Esempio n. 3
0
 def get_abandoned_carts(self):
     self.ensure_one()
     return {
         'name':
         _('Abandoned Carts'),
         'type':
         'ir.actions.act_window',
         'view_type':
         'form',
         'view_mode':
         'tree,form',
         'domain': [('is_abandoned_cart', '=', True)],
         'search_view_id':
         self.env.ref('sale.sale_order_view_search_inherit_sale').id,
         'context': {
             'search_default_team_id': self.id,
             'default_team_id': self.id,
             'search_default_recovery_email': 1,
             'create': False
         },
         'res_model':
         'sale.order',
         'help':
         _('''<p class="oe_view_nocontent_create">
                     You can find all abandoned carts here, i.e. the carts generated by your website's visitors from over an hour ago that haven't been confirmed yet.</p>
                     <p>You should send an email to the customers to encourage them!</p>
                 '''),
     }
Esempio n. 4
0
    def onchange_serial_number(self):
        """ When the user is encoding a move line for a tracked product, we apply some logic to
        help him. This includes:
            - automatically switch `qty_done` to 1.0
            - warn if he has already encoded `lot_name` in another move line
        """
        res = {}
        if self.product_id.tracking == 'serial':
            if not self.qty_done:
                self.qty_done = 1

            message = None
            if self.lot_name or self.lot_id:
                move_lines_to_check = self._get_similar_move_lines() - self
                if self.lot_name:
                    counter = Counter(move_lines_to_check.mapped('lot_name'))
                    if counter.get(
                            self.lot_name) and counter[self.lot_name] > 1:
                        message = _(
                            'You cannot use the same serial number twice. Please correct the serial numbers encoded.'
                        )
                elif self.lot_id:
                    counter = Counter(move_lines_to_check.mapped('lot_id.id'))
                    if counter.get(
                            self.lot_id.id) and counter[self.lot_id.id] > 1:
                        message = _(
                            'You cannot use the same serial number twice. Please correct the serial numbers encoded.'
                        )

            if message:
                res['warning'] = {'title': _('Warning'), 'message': message}
        return res
Esempio n. 5
0
    def _do_payment(self):
        if self.payment_token_id.acquirer_id.capture_manually:
            raise ValidationError(
                _('This feature is not available for payment acquirers set to the "Authorize" mode.\n'
                  'Please use a token from another provider than %s.') %
                self.payment_token_id.acquirer_id.name)
        reference = "P-%s-%s" % (
            self.id, datetime.datetime.now().strftime('%y%m%d_%H%M%S'))
        tx = self.env['payment.transaction'].create({
            'amount':
            self.amount,
            'acquirer_id':
            self.payment_token_id.acquirer_id.id,
            'type':
            'server2server',
            'currency_id':
            self.currency_id.id,
            'reference':
            reference,
            'payment_token_id':
            self.payment_token_id.id,
            'partner_id':
            self.partner_id.id,
            'partner_country_id':
            self.partner_id.country_id.id,
        })

        s2s_result = tx.s2s_do_transaction()

        if not s2s_result or tx.state != 'done':
            raise ValidationError(
                _("Payment transaction failed (%s)") % tx.state_message)

        self.payment_transaction_id = tx
    def asset_compute(self):
        self.ensure_one()
        context = self._context
        created_move_ids = self.env[
            'account.asset.asset'].compute_generated_entries(
                self.date, asset_type=context.get('asset_type'))

        return {
            'name':
            _('Created Asset Moves') if context.get('asset_type') == 'purchase'
            else _('Created Revenue Moves'),
            'view_type':
            'form',
            'view_mode':
            'tree,form',
            'res_model':
            'account.move',
            'view_id':
            False,
            'domain':
            "[('id','in',[" + ','.join(str(id)
                                       for id in created_move_ids) + "])]",
            'type':
            'ir.actions.act_window',
        }
Esempio n. 7
0
    def print_checks(self):
        """ Check that the recordset is valid, set the payments state to sent and call print_checks() """
        # Since this method can be called via a client_action_multi, we need to make sure the received records are what we expect
        self = self.filtered(lambda r: r.payment_method_id.code == 'check_printing' and r.state != 'reconciled')

        if len(self) == 0:
            raise UserError(_("Payments to print as a checks must have 'Check' selected as payment method and "
                              "not have already been reconciled"))
        if any(payment.journal_id != self[0].journal_id for payment in self):
            raise UserError(_("In order to print multiple checks at once, they must belong to the same bank journal."))

        if not self[0].journal_id.check_manual_sequencing:
            # The wizard asks for the number printed on the first pre-printed check
            # so payments are attributed the number of the check the'll be printed on.
            last_printed_check = self.search([
                ('journal_id', '=', self[0].journal_id.id),
                ('check_number', '!=', 0)], order="check_number desc", limit=1)
            next_check_number = last_printed_check and last_printed_check.check_number + 1 or 1
            return {
                'name': _('Print Pre-numbered Checks'),
                'type': 'ir.actions.act_window',
                'res_model': 'print.prenumbered.checks',
                'view_type': 'form',
                'view_mode': 'form',
                'target': 'new',
                'context': {
                    'payment_ids': self.ids,
                    'default_next_check_number': next_check_number,
                }
            }
        else:
            self.filtered(lambda r: r.state == 'draft').post()
            return self.do_print_checks()
Esempio n. 8
0
    def web_auth_reset_password(self, *args, **kw):
        qcontext = self.get_auth_signup_qcontext()

        if not qcontext.get('token') and not qcontext.get(
                'reset_password_enabled'):
            raise werkzeug.exceptions.NotFound()

        if 'error' not in qcontext and request.httprequest.method == 'POST':
            try:
                if qcontext.get('token'):
                    self.do_signup(qcontext)
                    return super(AuthSignupHome, self).web_login(*args, **kw)
                else:
                    login = qcontext.get('login')
                    assert login, _("No login provided.")
                    _logger.info(
                        "Password reset attempt for <%s> by user <%s> from %s",
                        login, request.env.user.login,
                        request.httprequest.remote_addr)
                    request.env['res.users'].sudo().reset_password(login)
                    qcontext['message'] = _(
                        "An email has been sent with credentials to reset your password"
                    )
            except UserError as e:
                qcontext['error'] = e.name or e.value
            except SignupError:
                qcontext['error'] = _("Could not reset your password")
                _logger.exception('error when resetting password')
            except Exception as e:
                qcontext['error'] = str(e)

        response = request.render('auth_signup.reset_password', qcontext)
        response.headers['X-Frame-Options'] = 'DENY'
        return response
Esempio n. 9
0
    def _print_report(self, data):
        res = {}
        data = self.pre_print_report(data)
        data['form'].update(self.read(['period_length'])[0])
        period_length = data['form']['period_length']
        if period_length <= 0:
            raise UserError(_('You must set a period length greater than 0.'))
        if not data['form']['date_from']:
            raise UserError(_('You must set a start date.'))

        start = datetime.strptime(data['form']['date_from'], "%Y-%m-%d")

        for i in range(5)[::-1]:
            stop = start - relativedelta(days=period_length - 1)
            res[str(i)] = {
                'name': (i != 0 and (str(
                    (5 - (i + 1)) * period_length) + '-' + str(
                        (5 - i) * period_length))
                         or ('+' + str(4 * period_length))),
                'stop':
                start.strftime('%Y-%m-%d'),
                'start': (i != 0 and stop.strftime('%Y-%m-%d') or False),
            }
            start = stop - relativedelta(days=1)
        data['form'].update(res)
        return self.env.ref(
            'account.action_report_aged_partner_balance').with_context(
                landscape=True).report_action(self, data=data)
Esempio n. 10
0
    def _confirm_so(self):
        """ Check tx state, confirm the potential SO """
        self.ensure_one()
        if self.sale_order_id.state not in ['draft', 'sent', 'sale']:
            _logger.warning(
                '<%s> transaction STATE INCORRECT for order %s (ID %s, state %s)',
                self.acquirer_id.provider, self.sale_order_id.name,
                self.sale_order_id.id, self.sale_order_id.state)
            return 'pay_sale_invalid_doc_state'
        if not float_compare(self.amount, self.sale_order_id.amount_total,
                             2) == 0:
            _logger.warning(
                '<%s> transaction AMOUNT MISMATCH for order %s (ID %s): expected %r, got %r',
                self.acquirer_id.provider,
                self.sale_order_id.name,
                self.sale_order_id.id,
                self.sale_order_id.amount_total,
                self.amount,
            )
            self.sale_order_id.message_post(
                subject=_("Amount Mismatch (%s)") % self.acquirer_id.provider,
                body=
                _("The sale order was not confirmed despite response from the acquirer (%s): SO amount is %r but acquirer replied with %r."
                  ) % (
                      self.acquirer_id.provider,
                      self.sale_order_id.amount_total,
                      self.amount,
                  ))
            return 'pay_sale_tx_amount'

        if self.state == 'authorized' and self.acquirer_id.capture_manually:
            _logger.info(
                '<%s> transaction authorized, auto-confirming order %s (ID %s)',
                self.acquirer_id.provider, self.sale_order_id.name,
                self.sale_order_id.id)
            if self.sale_order_id.state in ('draft', 'sent'):
                self.sale_order_id.with_context(
                    send_email=True).action_confirm()
        elif self.state == 'done':
            _logger.info(
                '<%s> transaction completed, auto-confirming order %s (ID %s)',
                self.acquirer_id.provider, self.sale_order_id.name,
                self.sale_order_id.id)
            if self.sale_order_id.state in ('draft', 'sent'):
                self.sale_order_id.with_context(
                    send_email=True).action_confirm()
        elif self.state not in ['cancel', 'error'
                                ] and self.sale_order_id.state == 'draft':
            _logger.info(
                '<%s> transaction pending/to confirm manually, sending quote email for order %s (ID %s)',
                self.acquirer_id.provider, self.sale_order_id.name,
                self.sale_order_id.id)
            self.sale_order_id.force_quotation_send()
        else:
            _logger.warning('<%s> transaction MISMATCH for order %s (ID %s)',
                            self.acquirer_id.provider, self.sale_order_id.name,
                            self.sale_order_id.id)
            return 'pay_sale_tx_state'
        return True
Esempio n. 11
0
 def onchange_product_uom(self):
     res = {}
     if not self.product_id or not self.product_uom:
         return res
     if self.product_uom.category_id != self.product_id.uom_id.category_id:
         res['warning'] = {'title': _('Warning'), 'message': _('The Product Unit of Measure you chose has a different category than in the product form.')}
         self.product_uom = self.product_id.uom_id.id
     return res
Esempio n. 12
0
    def _ogone_form_get_tx_from_data(self, data):
        """ Given a data dict coming from ogone, verify it and find the related
        transaction record. Create a payment token if an alias is returned."""
        reference, pay_id, shasign, alias = data.get('orderID'), data.get(
            'PAYID'), data.get('SHASIGN'), data.get('ALIAS')
        if not reference or not pay_id or not shasign:
            error_msg = _(
                'Ogone: received data with missing reference (%s) or pay_id (%s) or shasign (%s)'
            ) % (reference, pay_id, shasign)
            _logger.info(error_msg)
            raise ValidationError(error_msg)

        # find tx -> @TDENOTE use paytid ?
        tx = self.search([('reference', '=', reference)])
        if not tx or len(tx) > 1:
            error_msg = _('Ogone: received data for reference %s') % (
                reference)
            if not tx:
                error_msg += _('; no order found')
            else:
                error_msg += _('; multiple order found')
            _logger.info(error_msg)
            raise ValidationError(error_msg)

        # verify shasign
        shasign_check = tx.acquirer_id._ogone_generate_shasign('out', data)
        if shasign_check.upper() != shasign.upper():
            error_msg = _(
                'Ogone: invalid shasign, received %s, computed %s, for data %s'
            ) % (shasign, shasign_check, data)
            _logger.info(error_msg)
            raise ValidationError(error_msg)

        if not tx.acquirer_reference:
            tx.acquirer_reference = pay_id

        # alias was created on ogone server, store it
        if alias and tx.type == 'form_save':
            Token = self.env['payment.token']
            domain = [('acquirer_ref', '=', alias)]
            cardholder = data.get('CN')
            if not Token.search_count(domain):
                _logger.info('Ogone: saving alias %s for partner %s' %
                             (data.get('CARDNO'), tx.partner_id))
                ref = Token.create({
                    'name':
                    data.get('CARDNO') +
                    (' - ' + cardholder if cardholder else ''),
                    'partner_id':
                    tx.partner_id.id,
                    'acquirer_id':
                    tx.acquirer_id.id,
                    'acquirer_ref':
                    alias
                })
                tx.write({'payment_token_id': ref.id})

        return tx
 def _graph_title_and_key(self):
     if self.type == 'sale':
         return ['', _('Sales: Untaxed Total')]
     elif self.type == 'purchase':
         return ['', _('Purchase: Untaxed Total')]
     elif self.type == 'cash':
         return ['', _('Cash: Balance')]
     elif self.type == 'bank':
         return ['', _('Bank: Balance')]
Esempio n. 14
0
 def unlink(self):
     for record in self:
         if record.move_check:
             if record.asset_id.category_id.type == 'purchase':
                 msg = _("You cannot delete posted depreciation lines.")
             else:
                 msg = _("You cannot delete posted installment lines.")
             raise UserError(msg)
     return super(AccountAssetDepreciationLine, self).unlink()
Esempio n. 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 {}
Esempio n. 16
0
 def unlink(self):
     if any(bool(rec.move_line_ids) for rec in self):
         raise UserError(
             _("You can not delete a payment that is already posted"))
     if any(rec.move_name for rec in self):
         raise UserError(
             _('It is not allowed to delete a payment that already created a journal entry since it would create a gap in the numbering. You should create the journal entry again and cancel it thanks to a regular revert.'
               ))
     return super(account_payment, self).unlink()
Esempio n. 17
0
 def _get_menu_entries(self):
     """ Method returning menu entries to display on the website view of the
     event, possibly depending on some options in inheriting modules. """
     self.ensure_one()
     return [
         (_('Introduction'), False, 'website_event.template_intro'),
         (_('Location'), False, 'website_event.template_location'),
         (_('Register'), '/event/%s/register' % slug(self), False),
     ]
Esempio n. 18
0
 def button_reg_close(self):
     """ Close Registration """
     today = fields.Datetime.now()
     if self.event_id.date_begin <= today and self.event_id.state == 'confirm':
         self.write({'state': 'done', 'date_closed': today})
     elif self.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."))
Esempio n. 19
0
    def done(self):
        pickings = self.mapped('picking_ids').filtered(
            lambda picking: picking.state not in ('cancel', 'done'))
        if any(picking.state not in ('assigned') for picking in pickings):
            raise UserError(
                _('Some pickings are still waiting for goods. Please check or force their availability before setting this batch to done.'
                  ))
        for picking in pickings:
            picking.message_post(
                body=
                "<b>%s:</b> %s <a href=#id=%s&view_type=form&model=stock.picking.batch>%s</a>"
                % (_("Transferred by"), _("Batch Picking"),
                   picking.batch_id.id, picking.batch_id.name))

        picking_to_backorder = self.env['stock.picking']
        picking_without_qty_done = self.env['stock.picking']
        for picking in pickings:
            if all([x.qty_done == 0.0 for x in picking.move_line_ids]):
                # If no lots when needed, raise error
                picking_type = picking.picking_type_id
                if (picking_type.use_create_lots
                        or picking_type.use_existing_lots):
                    for ml in picking.move_line_ids:
                        if ml.product_id.tracking != 'none':
                            raise UserError(
                                _('Some products require lots/serial numbers, so you need to specify those first!'
                                  ))
                # Check if we need to set some qty done.
                picking_without_qty_done |= picking
            elif picking._check_backorder():
                picking_to_backorder |= picking
            else:
                picking.action_done()
        self.write({'state': 'done'})
        if picking_without_qty_done:
            view = self.env.ref('stock.view_immediate_transfer')
            wiz = self.env['stock.immediate.transfer'].create({
                'pick_ids': [(4, p.id) for p in picking_without_qty_done],
                'pick_to_backorder_ids':
                [(4, p.id) for p in picking_to_backorder],
            })
            return {
                'name': _('Immediate Transfer?'),
                'type': 'ir.actions.act_window',
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'stock.immediate.transfer',
                'views': [(view.id, 'form')],
                'view_id': view.id,
                'target': 'new',
                'res_id': wiz.id,
                'context': self.env.context,
            }
        if picking_to_backorder:
            return picking_to_backorder.action_generate_backorder_wizard()
        return True
Esempio n. 20
0
    def default_get(self, fields):
        if len(self.env.context.get('active_ids', list())) > 1:
            raise UserError("You may only return one picking at a time!")
        res = super(ReturnPicking, self).default_get(fields)

        move_dest_exists = False
        product_return_moves = []
        picking = self.env['stock.picking'].browse(
            self.env.context.get('active_id'))
        if picking:
            res.update({'picking_id': picking.id})
            if picking.state != 'done':
                raise UserError(_("You may only return Done pickings"))
            for move in picking.move_lines:
                if move.scrapped:
                    continue
                if move.move_dest_ids:
                    move_dest_exists = True
                quantity = move.product_qty - sum(move.move_dest_ids.filtered(lambda m: m.state in ['partially_available', 'assigned', 'done']).\
                                                  mapped('move_line_ids').mapped('product_qty'))
                quantity = float_round(
                    quantity, precision_rounding=move.product_uom.rounding)
                product_return_moves.append((0, 0, {
                    'product_id':
                    move.product_id.id,
                    'quantity':
                    quantity,
                    'move_id':
                    move.id,
                    'uom_id':
                    move.product_id.uom_id.id
                }))

            if not product_return_moves:
                raise UserError(
                    _("No products to return (only lines in Done state and not fully returned yet can be returned)!"
                      ))
            if 'product_return_moves' in fields:
                res.update({'product_return_moves': product_return_moves})
            if 'move_dest_exists' in fields:
                res.update({'move_dest_exists': move_dest_exists})
            if 'parent_location_id' in fields and picking.location_id.usage == 'internal':
                res.update({
                    'parent_location_id':
                    picking.picking_type_id.warehouse_id and
                    picking.picking_type_id.warehouse_id.view_location_id.id
                    or picking.location_id.location_id.id
                })
            if 'original_location_id' in fields:
                res.update({'original_location_id': picking.location_id.id})
            if 'location_id' in fields:
                location_id = picking.location_id.id
                if picking.picking_type_id.return_picking_type_id.default_location_dest_id.return_location:
                    location_id = picking.picking_type_id.return_picking_type_id.default_location_dest_id.id
                res['location_id'] = location_id
        return res
Esempio n. 21
0
 def _get_menu_entries(self):
     self.ensure_one()
     res = super(Event, self)._get_menu_entries()
     if self.website_track:
         res += [(_('Talks'), '/event/%s/track' % slug(self), False),
                 (_('Agenda'), '/event/%s/agenda' % slug(self), False)]
     if self.website_track_proposal:
         res += [(_('Talk Proposals'),
                  '/event/%s/track_proposal' % slug(self), False)]
     return res
Esempio n. 22
0
 def _get_manufacture_route_id(self):
     manufacture_route = self.env.ref('mrp.route_warehouse0_manufacture',
                                      raise_if_not_found=False)
     if not manufacture_route:
         manufacture_route = self.env['stock.location.route'].search(
             [('name', 'like', _('Manufacture'))], limit=1)
     if not manufacture_route:
         raise exceptions.UserError(
             _('Can\'t find any generic Manufacture route.'))
     return manufacture_route.id
Esempio n. 23
0
 def _onchange_qty_done(self):
     """ When the user is encoding a produce line for a tracked product, we apply some logic to
     help him. This onchange will warn him if he set `qty_done` to a non-supported value.
     """
     res = {}
     if self.product_id.tracking == 'serial':
         if float_compare(self.qty_done, 1.0, precision_rounding=self.move_id.product_id.uom_id.rounding) != 0:
             message = _('You can only process 1.0 %s for products with unique serial number.') % self.product_id.uom_id.name
             res['warning'] = {'title': _('Warning'), 'message': message}
     return res
Esempio n. 24
0
    def sale_pay_form(self,
                      acquirer_id,
                      order_id,
                      save_token=False,
                      access_token=None,
                      **kwargs):
        """ Json method that creates a payment.transaction, used to create a
        transaction when the user clicks on 'pay now' button on the payment
        form.

        :return html: form containing all values related to the acquirer to
                      redirect customers to the acquirer website """
        success_url = kwargs.get('success_url', '/my')

        order_sudo = request.env['sale.order'].sudo().browse(order_id)
        if not order_sudo:
            return False

        try:
            acquirer = request.env['payment.acquirer'].browse(int(acquirer_id))
        except:
            return False

        # we check if the order need to create a payment token
        save_token = save_token or order_sudo._get_payment_type(
        ) == "form_save"

        if request.env.user._is_public():
            save_token = False

        token = request.env['payment.token'].sudo(
        )  # currently no support of payment tokens
        tx = request.env['payment.transaction'].sudo(
        )._check_or_create_sale_tx(
            order_sudo,
            acquirer,
            payment_token=token,
            tx_type='form_save' if save_token else 'form',
        )

        # set the transaction id into the session
        request.session['portal_sale_%s_transaction_id' %
                        order_sudo.id] = tx.id

        return tx.render_sale_button(
            order_sudo,
            success_url,
            submit_txt=_('Pay'),
            render_values={
                'type':
                'form_save' if save_token else 'form',
                'alias_usage':
                _('If we store your payment information on our server, subscription payments will be made automatically.'
                  ),
            })
Esempio n. 25
0
 def _check_write(self):
     """check that the field is created from the menu and not from an database update
        otherwise the database update can crash:"""
     if self.env.context.get('manual'):
         global_state = self._get_global_state()
         if global_state == 'anonymized':
             raise UserError(_("The database is currently anonymized, you cannot create, modify or delete fields."))
         elif global_state == 'unstable':
             raise UserError(_("The database anonymization is currently in an unstable state. Some fields are anonymized,"
                             " while some fields are not anonymized. You should try to solve this problem before trying to create, write or delete fields."))
     return True
Esempio n. 26
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 reconciliable account (see _compute_destination_account_id).
            If invoice_ids is not empty, there will be one reconciliable 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.
        """
        for rec in self:

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

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

            # 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'].with_context(
                ir_sequence_date=rec.payment_date).next_by_code(sequence_code)
            if not rec.name and rec.payment_type != 'transfer':
                raise UserError(
                    _("You have to define a sequence for %s in your company.")
                    % (sequence_code, ))

            # Create the journal entry
            amount = rec.amount * (rec.payment_type in ('outbound', 'transfer')
                                   and 1 or -1)
            move = rec._create_payment_entry(amount)

            # In case of a transfer, the first journal entry created debited the source liquidity account and credited
            # the transfer account. Now we debit the transfer account and credit the destination liquidity account.
            if rec.payment_type == 'transfer':
                transfer_credit_aml = move.line_ids.filtered(
                    lambda r: r.account_id == rec.company_id.
                    transfer_account_id)
                transfer_debit_aml = rec._create_transfer_entry(amount)
                (transfer_credit_aml + transfer_debit_aml).reconcile()

            rec.write({'state': 'posted', 'move_name': move.name})
        return True
Esempio n. 27
0
 def _construct_constraint_msg(self, country_code):
     self.ensure_one()
     vat_no = "'CC##' (CC=Country Code, ##=VAT Number)"
     vat_no = _ref_vat.get(country_code) or vat_no
     if self.env.context.get('company_id'):
         company = self.env['res.company'].browse(self.env.context['company_id'])
     else:
         company = self.env.user.company_id
     if company.vat_check_vies:
         return '\n' + _('The VAT number [%s] for partner [%s] either failed the VIES VAT validation check or did not respect the expected format %s.') % (self.vat, self.name, vat_no)
     return '\n' + _('The VAT number [%s] for partner [%s] does not seem to be valid. \nNote: the expected format is %s') % (self.vat, self.name, vat_no)
Esempio n. 28
0
 def _compute_last_done_picking(self):
     # TDE TODO: true multi
     tristates = []
     for picking in self.env['stock.picking'].search([('picking_type_id', '=', self.id), ('state', '=', 'done')], order='date_done desc', limit=10):
         if picking.date_done > picking.date:
             tristates.insert(0, {'tooltip': picking.name or '' + ": " + _('Late'), 'value': -1})
         elif picking.backorder_id:
             tristates.insert(0, {'tooltip': picking.name or '' + ": " + _('Backorder exists'), 'value': 0})
         else:
             tristates.insert(0, {'tooltip': picking.name or '' + ": " + _('OK'), 'value': 1})
     self.last_done_picking = json.dumps(tristates)
Esempio n. 29
0
 def _check_pattern(self):
     p = self.pattern.replace("\\\\", "X").replace("\{", "X").replace("\}", "X")
     findall = re.findall("[{]|[}]", p) # p does not contain escaped { or }
     if len(findall) == 2: 
         if not re.search("[{][N]*[D]*[}]", p):
             raise ValidationError(_("There is a syntax error in the barcode pattern ") + self.pattern + _(": braces can only contain N's followed by D's."))
         elif re.search("[{][}]", p):
             raise ValidationError(_("There is a syntax error in the barcode pattern ") + self.pattern + _(": empty braces."))
     elif len(findall) != 0:
         raise ValidationError(_("There is a syntax error in the barcode pattern ") + self.pattern + _(": a rule can only contain one pair of braces."))
     elif p == '*':
         raise ValidationError(_(" '*' is not a valid Regex Barcode Pattern. Did you mean '.*' ?"))
Esempio n. 30
0
 def _get_default_category_id(self):
     if self._context.get('categ_id') or self._context.get('default_categ_id'):
         return self._context.get('categ_id') or self._context.get('default_categ_id')
     category = self.env.ref('product.product_category_all', raise_if_not_found=False)
     if not category:
         category = self.env['product.category'].search([], limit=1)
     if category:
         return category.id
     else:
         err_msg = _('You must define at least one product category in order to be able to create products.')
         redir_msg = _('Go to Internal Categories')
         raise RedirectWarning(err_msg, self.env.ref('product.product_category_action_form').id, redir_msg)