Beispiel #1
0
    def update_status(self, new_status):
        if new_status == self.status:
            return
        transition = (self.status, new_status)
        if transition not in self.__class__._transitions:
            raise BadRequest(
                gettext('electronic_signature.msg_unauthorized_transition',
                        provider_id=self.provider_id,
                        provider=self.provider_credential.provider
                        if self.provider_credential else '',
                        status=new_status))
        if self.status != new_status:
            # the transition writes the status on the signature
            getattr(self.__class__, 'set_status_%s' % new_status)([self])

            # now that the status is updated in database, we can notify
            if new_status in ('expired', 'canceled'):
                self.notify_signature_failed()
            elif new_status == 'completed':
                self.notify_signature_completed()
Beispiel #2
0
 def get(self, _lock=False):
     '''
     Return the next sequence value
     '''
     cls = self.__class__
     # bypass rules on sequences
     with Transaction().set_context(user=False, _check_access=False):
         with Transaction().set_user(0):
             try:
                 sequence = cls(self.id)
             except TypeError:
                 raise MissingError(gettext('ir.msg_sequence_missing'))
             if _lock:
                 self.lock()
             date = Transaction().context.get('date')
             return '%s%s%s' % (
                 cls._process(sequence.prefix, date=date),
                 cls._get_sequence(sequence),
                 cls._process(sequence.suffix, date=date),
                 )
Beispiel #3
0
    def find(cls, date=None, exception=True):
        pool = Pool()
        Lang = pool.get('ir.lang')
        Date = pool.get('ir.date')

        if not date:
            date = Date.today()
        workyears = cls.search([
            ('start_date', '<=', date),
            ('end_date', '>=', date),
            ], order=[('start_date', 'DESC')], limit=1)
        if not workyears:
            if exception:
                lang = Lang.get()
                formatted = lang.strftime(date)
                raise UserError(gettext(
                    'lims.msg_no_workyear_date', date=formatted))
            else:
                return None
        return workyears[0].id
Beispiel #4
0
 def write(cls, *args):
     pool = Pool()
     Warning = pool.get('res.user.warning')
     actions = iter(args)
     for templates, values in zip(actions, actions):
         if not values.get("purchase_uom"):
             continue
         for template in templates:
             if not template.purchase_uom:
                 continue
             if template.purchase_uom.id == values["purchase_uom"]:
                 continue
             for product in template.products:
                 if not product.product_suppliers:
                     continue
                 name = '%s@product_template' % template.id
                 if Warning.check(name):
                     raise PurchaseUOMWarning(
                         name, gettext('purchase.msg_change_purchase_uom'))
     super(Template, cls).write(*args)
Beispiel #5
0
 def encode(element):
     for attr in ('states', 'domain', 'spell'):
         if not element.get(attr):
             continue
         try:
             value = PYSONDecoder().decode(element.get(attr))
             validates.get(attr, lambda a: True)(value)
         except Exception as e:
             error_log = '%s: <%s %s="%s"/>' % (
                 e, element.get('id') or element.get('name'), attr,
                 element.get(attr))
             logger.error(
                 'Invalid XML view %s:\n%s\n%s',
                 view.rec_name, error_log, xml)
             raise XMLError(
                 gettext(
                     'ir.msg_view_invalid_xml', name=view.rec_name),
                 error_log) from e
     for child in element:
         encode(child)
Beispiel #6
0
    def check_deposit(cls, invoices):
        to_check = set()
        for invoice in invoices:
            for line in invoice.lines:
                if line.type != 'line':
                    continue
                if line.account.type.deposit:
                    if ((invoice.type.endswith('invoice')
                            and line.amount < 0)
                            or (invoice.type.endswith('credit_note')
                                and line.amount > 0)):
                        sign = 1 if invoice.type.startswith('in') else -1
                        to_check.add((invoice.party, line.account, sign))

        for party, account, sign in to_check:
            if not party.check_deposit(account, sign):
                raise DepositError(
                    gettext('account_deposit.msg_deposit_not_enough',
                        account=account.rec_name,
                        party=party.rec_name))
Beispiel #7
0
 def post(cls, statements):
     pool = Pool()
     Lang = pool.get('ir.lang')
     StatementLine = pool.get('account.statement.line')
     for statement in statements:
         for origin in statement.origins:
             if origin.pending_amount:
                 lang = Lang.get()
                 amount = lang.currency(
                     origin.pending_amount, statement.journal.currency)
                 raise StatementPostError(
                     gettext('account_statement'
                         '.msg_statement_post_pending_amount',
                         statement=statement.rec_name,
                         amount=amount,
                         origin=origin.rec_name))
     # Write state to skip statement test on Move.post
     cls.write(statements, {'state': 'posted'})
     lines = [l for s in statements for l in s.lines]
     StatementLine.post_move(lines)
Beispiel #8
0
 def _login_password(cls, login, parameters):
     if 'password' not in parameters:
         msg = gettext('res.msg_user_password', login=login)
         raise LoginException('password', msg, type='password')
     user_id, password_hash, password_reset = cls._get_login(login)
     if user_id and password_hash:
         password = parameters['password']
         valid, new_hash = cls.check_password(password, password_hash)
         if valid:
             if new_hash:
                 logger.info("Update password hash for %s", user_id)
                 with Transaction().new_transaction() as transaction:
                     with transaction.set_user(0):
                         cls.write([cls(user_id)], {
                             'password_hash': new_hash,
                         })
             return user_id
     elif user_id and password_reset:
         if password_reset == parameters['password']:
             return user_id
Beispiel #9
0
 def check_identifier_types(self, field_names=None):
     pool = Pool()
     Identifier = pool.get('party.identifier')
     if field_names and 'identifier_types' not in field_names:
         return
     if self.identifier_types:
         identifier_types = [None, ''] + list(self.identifier_types)
         identifiers = Identifier.search([
                 ('type', 'not in', identifier_types),
                 ], limit=1, order=[])
         if identifiers:
             identifier, = identifiers
             selection = self.fields_get(
                 ['identifier_types'])['identifier_types']['selection']
             selection = dict(selection)
             raise AccessError(gettext(
                     'party.msg_identifier_type_remove',
                     type=selection.get(identifier.type, identifier.type),
                     identifier=identifier.rec_name,
                     ))
 def check_uniqueness(cls, orders):
     """
     Ensure uniqueness of order points. I.E that there is no several
     order point for the same location, the same product and the
     same company.
     """
     query = ['OR']
     for op in orders:
         field = cls._type2field(op.type)
         arg = [
             'AND',
             ('product', '=', op.product.id),
             (field, '=', getattr(op, field).id),
             ('id', '!=', op.id),
             ('company', '=', op.company.id),
         ]
         query.append(arg)
     if cls.search(query):
         raise OrderPointValidationError(
             gettext('stock_supply.msg_order_point_unique'))
Beispiel #11
0
 def deactivate(cls, modules):
     pool = Pool()
     Module = pool.get('ir.module')
     Dependency = pool.get('ir.module.dependency')
     module_table = Module.__table__()
     dep_table = Dependency.__table__()
     cursor = Transaction().connection.cursor()
     for module in modules:
         cursor.execute(*dep_table.join(module_table,
                 condition=(dep_table.module == module_table.id)
                 ).select(module_table.state, module_table.name,
                 where=(dep_table.name == module.name)
                 & NotIn(
                     module_table.state, ['not activated', 'to remove'])))
         res = cursor.fetchall()
         if res:
             raise DeactivateDependencyError(
                 gettext('ir.msg_module_deactivate_dependency'),
                 '\n'.join('\t%s: %s' % (x[0], x[1]) for x in res))
     cls.write(modules, {'state': 'to remove'})
Beispiel #12
0
    def transition_start(self):
        pool = Pool()
        Request = pool.get('purchase.request')
        Warning = pool.get('res.user.warning')

        requests = Request.browse(Transaction().context['active_ids'])

        reqs = [r for r in requests if r.state in {'draft', 'quotation'}]
        if reqs:
            for r in reqs:
                if r.state == 'quotation':
                    if Warning.check(str(r)):
                        raise PreviousQuotation(
                            str(r),
                            gettext(
                                'purchase_request_quotation'
                                '.msg_previous_quotation',
                                request=r.rec_name))
            return 'ask_suppliers'
        return 'end'
Beispiel #13
0
 def write(cls, *args):
     pool = Pool()
     Move = pool.get('account.move')
     actions = iter(args)
     for fiscalyears, values in zip(actions, actions):
         if values.get('post_move_sequence'):
             for fiscalyear in fiscalyears:
                 if (fiscalyear.post_move_sequence
                         and fiscalyear.post_move_sequence.id !=
                         values['post_move_sequence']):
                     if Move.search([
                         ('period.fiscalyear', '=', fiscalyear.id),
                         ('state', '=', 'posted'),
                     ]):
                         raise AccessError(
                             gettext(
                                 'account.'
                                 'msg_change_fiscalyear_post_move_sequence',
                                 fiscalyear=fiscalyear.rec_name))
     super(FiscalYear, cls).write(*args)
Beispiel #14
0
 def check_type_for_moves(self):
     """ Check locations with moves have types compatible with moves. """
     invalid_move_types = ['warehouse', 'view']
     Move = Pool().get('stock.move')
     if self.type in invalid_move_types:
         # Use root to compute for all companies
         with Transaction().set_user(0):
             moves = Move.search([
                 [
                     'OR',
                     ('to_location', '=', self.id),
                     ('from_location', '=', self.id),
                 ],
                 ('state', 'not in', ['staging', 'draft']),
             ])
         if moves:
             raise LocationValidationError(
                 gettext('stock.msg_location_invalid_type_for_moves',
                         location=self.rec_name,
                         type=self.type_string))
Beispiel #15
0
    def reopen(cls, fiscalyears):
        '''
        Re-open a fiscal year
        '''
        Deferral = Pool().get('account.account.deferral')

        for fiscalyear in fiscalyears:
            if cls.search([
                ('start_date', '>=', fiscalyear.end_date),
                ('state', '!=', 'open'),
                ('company', '=', fiscalyear.company.id),
            ]):
                raise FiscalYearReOpenError(
                    gettext('account.msg_reopen_fiscalyear_later',
                            fiscalyear=fiscalyear.rec_name))

            deferrals = Deferral.search([
                ('fiscalyear', '=', fiscalyear.id),
            ])
            Deferral.delete(deferrals)
Beispiel #16
0
        def wrapper(cls, records, *args, **kwargs):
            pool = Pool()
            ModelAccess = pool.get('ir.model.access')
            Button = pool.get('ir.model.button')
            ButtonClick = pool.get('ir.model.button.click')
            User = pool.get('res.user')

            transaction = Transaction()
            check_access = transaction.context.get('_check_access')

            assert len(records) == len(set(records)), "Duplicate records"

            if (transaction.user != 0) and check_access:
                ModelAccess.check(cls.__name__, 'read')
                groups = set(User.get_groups())
                button_groups = Button.get_groups(cls.__name__,
                    func.__name__)
                if button_groups:
                    if not groups & button_groups:
                        raise AccessButtonError(
                            gettext('ir.msg_access_button_error',
                                button=func.__name__,
                                model=cls.__name__))
                else:
                    ModelAccess.check(cls.__name__, 'write')

            with Transaction().set_context(_check_access=False):
                if (transaction.user != 0) and check_access:
                    button_rules = Button.get_rules(
                        cls.__name__, func.__name__)
                    if button_rules:
                        clicks = ButtonClick.register(
                            cls.__name__, func.__name__, records)
                        records = [r for r in records
                            if all(br.test(r, clicks.get(r.id, []))
                                for br in button_rules)]
                # Reset click after filtering in case the button also has rules
                names = Button.get_reset(cls.__name__, func.__name__)
                if names:
                    ButtonClick.reset(cls.__name__, names, records)
                return func(cls, records, *args, **kwargs)
Beispiel #17
0
    def close(cls, fiscalyears):
        '''
        Close a fiscal year
        '''
        pool = Pool()
        Period = pool.get('account.period')
        Account = pool.get('account.account')
        Deferral = pool.get('account.account.deferral')

        # Prevent create new fiscal year or period
        cls.lock()
        Period.lock()

        deferrals = []
        for fiscalyear in fiscalyears:
            if cls.search([
                ('end_date', '<=', fiscalyear.start_date),
                ('state', '=', 'open'),
                ('company', '=', fiscalyear.company.id),
            ]):
                raise FiscalYearCloseError(
                    gettext('account.msg_close_fiscalyear_earlier',
                            fiscalyear=fiscalyear.rec_name))

            periods = Period.search([
                ('fiscalyear', '=', fiscalyear.id),
            ])
            Period.close(periods)

            with Transaction().set_context(fiscalyear=fiscalyear.id,
                                           date=None,
                                           cumulate=True,
                                           journal=None):
                accounts = Account.search([
                    ('company', '=', fiscalyear.company.id),
                ])
                for account in accounts:
                    deferral = fiscalyear.get_deferral(account)
                    if deferral:
                        deferrals.append(deferral)
        Deferral.save(deferrals)
Beispiel #18
0
 def check_dates(self):
     cursor = Transaction().connection.cursor()
     table = self.__table__()
     cursor.execute(
         *table.select(table.id,
                       where=(((table.start_date <= self.start_date) &
                               (table.end_date >= self.start_date)) | (
                                   (table.start_date <= self.end_date) &
                                   (table.end_date >= self.end_date)) | (
                                       (table.start_date >= self.start_date)
                                       & (table.end_date <= self.end_date)))
                       & (table.id != self.id)))
     second_id = cursor.fetchone()
     if second_id:
         second = self.__class__(second_id[0])
         raise UserError(
             gettext(
                 'lims.msg_workyear_overlaps',
                 first=self.rec_name,
                 second=second.rec_name,
             ))
Beispiel #19
0
 def check_unique(cls, numbers, field_names=None):
     if field_names and not (field_names & {'number', 'coupon'}):
         return
     duplicates = []
     for sub_numbers in grouped_slice(numbers):
         domain = ['OR']
         for number in sub_numbers:
             domain.append([
                 ('number', '=', number.number),
                 ('id', '!=', number.id),
                 ('coupon.promotion.company', '=',
                  number.coupon.promotion.company.id),
             ])
         duplicates.extend(cls.search(domain))
     if duplicates:
         numbers = ', '.join(n.number for n in duplicates[:5])
         if len(duplicates) > 5:
             numbers += '...'
         raise DuplicateError(
             gettext('sale_promotion_coupon.msg_duplicate_numbers',
                     numbers=numbers))
Beispiel #20
0
    def check_over_shipment(self):
        pool = Pool()
        Configuration = pool.get('sale.configuration')
        Warning = pool.get('res.user.warning')
        config = Configuration(1)

        if self.quantity >= 0:
            shipment_type = 'out'
        else:
            shipment_type = 'in'
        shipped_quantity = self._get_shipped_quantity(shipment_type)
        tolerance = config.sale_over_shipment_tolerance
        if tolerance is not None:
            maximal_quantity = abs(self.quantity * tolerance)
            if shipped_quantity > maximal_quantity:
                name = 'over_shipment_sale_line_%d' % self.id
                if Warning.check(name):
                    raise OverShipmentWarning(
                        name,
                        gettext('sale_shipment_tolerance.msg_over_shipment',
                                line=self.rec_name))
    def done(cls, productions):
        pool = Pool()
        Warning = pool.get('res.user.warning')

        def pending_purchase(production):
            return any(l.purchase_state in {'draft', 'quotation'}
                       for l in production.purchase_lines)

        pendings = list(filter(pending_purchase, productions))
        if pendings:
            names = ', '.join(p.rec_name for p in productions[:5])
            if len(pendings) > 5:
                names += '...'
            warning_name = '%s.pending_purchase.done' % hashlib.md5(
                str(pendings).encode('utf-8')).hexdigest()
            if Warning.check(warning_name):
                raise PurchaseWarning(
                    warning_name,
                    gettext('production_outsourcing.msg_pending_purchase_done',
                            productions=names))
        super(Production, cls).done(productions)
Beispiel #22
0
 def wrapper(self):
     account = func(self)
     if not account:
         account = self.get_account(field_name + '_used')
     # Allow empty values on on_change
     if not account and not Transaction().readonly:
         Model = self.__class__
         field = field_name
         if field_string:
             if getattr(self, field_string, None):
                 Model = getattr(self, field_string).__class__
             else:
                 field = field_string
         field = (
             Model.fields_get([field])[field]['string'])
         raise AccountError(
             gettext('account_product.msg_missing_account',
                 field=field,
                 name=self.rec_name))
     if account:
         return account.current()
Beispiel #23
0
 def default_start(self, fields):
     pool = Pool()
     Sale = pool.get('sale.sale')
     User = pool.get('res.user')
     sale = Sale(Transaction().context['active_id'])
     user = User(Transaction().user)
     sale_device = sale.sale_device or user.sale_device or False
     if user.id != 0 and not sale_device:
         raise UserError(gettext('sale_payment.not_sale_device'))
     return {
         'journal':
         sale_device.journal.id if sale_device.journal else None,
         'journals': [j.id for j in sale_device.journals],
         'payment_amount':
         sale.total_amount -
         sale.paid_amount if sale.paid_amount else sale.total_amount,
         'currency_digits':
         sale.currency_digits,
         'party':
         sale.party.id,
     }
Beispiel #24
0
    def generate_edi_file(cls, shipments):
        pool = Pool()
        Configuration = pool.get('stock.configuration')
        Warning = pool.get('res.user.warning')

        done_edi_shipment = Transaction().context.get(
            'done_edi_shipment', False)
        if done_edi_shipment:
            configuration = Configuration(1)
            if not configuration.automatic_edi_shipment_out:
                return

        for shipment in shipments:
            if shipment.is_edi:
                if done_edi_shipment:
                    warning_name = '%s.send_edi_shipment' % shipment
                    if Warning.check(warning_name):
                        raise UserWarning(warning_name, gettext(
                                'stock_shipment_out_edi.msg_send_edi_shipment',
                                shipment=shipment.number))
                shipment.generate_edi()
Beispiel #25
0
    def post(cls, moves):
        pool = Pool()
        BankReconciliation = pool.get('cash_bank.reconciliation')
        reconciliations = {}  # Key: account, value: last reconc. date
        for move in moves:
            for line in move.lines:
                if line.account.id not in reconciliations:
                    last_date = \
                        BankReconciliation.last_cash_bank_reconciliation_date(
                            line.account)
                    if last_date is None:
                        continue
                    reconciliations[line.account.id] = last_date

                last_date = reconciliations[line.account.id]
                if last_date and move.date <= last_date:
                    raise UserError(
                        gettext('cash_bank_reconciliation.acc_invalid_move',
                                account=line.account.rec_name))

        super(Move, cls).post(moves)
Beispiel #26
0
    def get_move(self):
        '''
        Return Move instance for the inventory line
        '''
        pool = Pool()
        Move = pool.get('stock.move')
        Uom = pool.get('product.uom')

        qty = self.quantity
        if qty is None:
            if self.inventory.empty_quantity is None:
                raise InventoryValidationError(
                    gettext('stock.msg_inventory_missing_empty_quantity',
                        inventory=self.inventory.rec_name))
            if self.inventory.empty_quantity == 'keep':
                return
            else:
                qty = 0.0

        delta_qty = Uom.compute_qty(self.uom,
            self.expected_quantity - qty,
            self.uom)
        if delta_qty == 0.0:
            return
        from_location = self.inventory.location
        to_location = self.inventory.lost_found
        if delta_qty < 0:
            (from_location, to_location, delta_qty) = \
                (to_location, from_location, -delta_qty)

        return Move(
            from_location=from_location,
            to_location=to_location,
            quantity=delta_qty,
            product=self.product,
            uom=self.uom,
            company=self.inventory.company,
            effective_date=self.inventory.date,
            origin=self,
            )
    def create_moves(cls, shipments):
        pool = Pool()
        Move = pool.get('stock.move')
        CatalogLine = pool.get('stock.shipment.internal.catalog_line')

        to_create = []
        to_delete = []
        same_from_to_locations = set()
        for shipment in shipments:
            if shipment.state != 'draft' or not shipment.catalog_lines:
                continue
            to_delete += [m for m in shipment.moves
                    if (m.state in ('draft', 'cancel')
                    and (m.origin and m.origin.__name__ == CatalogLine.__name__))]
            move_lines_with_quantity = [line for line in shipment.catalog_lines
                if line.quantity > 0]
            for line in move_lines_with_quantity:
                move = Move()
                move.shipment = shipment
                move.company = shipment.company
                move.from_location = line.catalogue.location
                move.to_location = shipment.to_location
                if move.from_location == move.to_location:
                    same_from_to_locations.add(move.from_location.rec_name)
                    break
                move.product = line.product
                move.on_change_product()
                move.quantity = line.quantity
                move.origin = line
                to_create.append(move)
        if same_from_to_locations:
            raise UserError(gettext('intern_catalogue.msg_same_from_to_locations',
                    locations=','.join(list(same_from_to_locations))))

        if to_delete:
            Move.draft(to_delete)
            Move.delete(to_delete)

        if to_create:
            Move.create([x._save_values for x in to_create])
Beispiel #28
0
    def test_gettext_with_translation(self):
        "gettext returns the translated text"
        pool = Pool()
        Lang = pool.get('ir.lang')
        Translation = pool.get('ir.translation')
        ModelData = pool.get('ir.model.data')

        lang, = Lang.search([('code', '!=', 'en')], limit=1)
        Translation.create([{
                    'name': 'ir.message,text',
                    'lang': lang.code,
                    'type': 'model',
                    'res_id': ModelData.get_id('tests', 'msg_test'),
                    'src': 'Message',
                    'value': 'Translated Message',
                    'module': 'tests',
                    'fuzzy': False,
                    }])

        message = gettext('tests.msg_test', lang.code)

        self.assertEqual(message, 'Translated Message')
Beispiel #29
0
    def parseVariable(self):
        self.skipWhitespace()
        var = ''
        while self.hasNext():
            char = self.peek()
            if char.lower() in '_abcdefghijklmnopqrstuvwxyz0123456789':
                var += char
                self._index += 1
            else:
                break

        value = self._vars.get(var, None)
        if value is None:
            raise UserError(
                gettext('lims.msg_unrecognized_variable', variable=var))
        if value == '':
            return float(0)
        try:
            value = float(value)
        except (ValueError):
            return float(0)
        return value
Beispiel #30
0
    def post(cls, invoices):
        '''
        Check up invoices that requires bank account because its payment type,
        has one
        '''
        to_save = []
        for invoice in invoices:
            account_bank = (invoice.payment_type
                            and invoice.payment_type.account_bank or 'none')
            if (invoice.payment_type and account_bank != 'none'
                    and not invoice.bank_account):
                invoice._get_bank_account()
                if not invoice.bank_account:
                    raise UserError(
                        gettext('account_bank.invoice_without_bank_account',
                                invoice=invoice.rec_name,
                                payment_type=invoice.payment_type.rec_name))

                to_save.append(invoice)
        if to_save:
            cls.save(to_save)
        super(Invoice, cls).post(invoices)