Esempio n. 1
0
class SubdivisionType(DeactivableMixin, ModelSQL, ModelView):
    "Address Subdivision Type"
    __name__ = 'party.address.subdivision_type'
    country_code = fields.Char("Country Code", size=2, required=True)
    types = fields.MultiSelection('get_subdivision_types', "Subdivision Types")
    _get_types_cache = Cache('party.address.subdivision_type.get_types')

    @classmethod
    def __setup__(cls):
        super().__setup__()
        t = cls.__table__()
        cls._sql_constraints = [
            ('country_code_unique',
             Exclude(t, (t.country_code, Equal),
                     where=t.active == Literal(True)),
             'party.msg_address_subdivision_country_code_unique')
        ]
        cls._order.insert(0, ('country_code', 'ASC NULLS LAST'))

    @classmethod
    def get_subdivision_types(cls):
        pool = Pool()
        Subdivision = pool.get('country.subdivision')
        return Subdivision.fields_get(['type'])['type']['selection']

    @classmethod
    def create(cls, *args, **kwargs):
        records = super().create(*args, **kwargs)
        cls._get_types_cache.clear()
        return records

    @classmethod
    def write(cls, *args, **kwargs):
        super().write(*args, **kwargs)
        cls._get_types_cache.clear()

    @classmethod
    def delete(cls, *args, **kwargs):
        super().delete(*args, **kwargs)
        cls._get_types_cache.clear()

    @classmethod
    def get_types(cls, country):
        key = country.code if country else None
        types = cls._get_types_cache.get(key)
        if types is not None:
            return list(types)

        records = cls.search([
            ('country_code', '=', country.code if country else None),
        ])
        if records:
            record, = records
            types = record.types
        else:
            types = []

        cls._get_types_cache.set(key, types)
        return types
Esempio n. 2
0
class ResourceMixin(ResourceAccessMixin, ModelStorage, ModelView):

    copy_to_resources = fields.MultiSelection(
        'get_copy_to_resources',
        "Copy to Resources",
        states={
            'invisible': ~Eval('copy_to_resources_visible'),
        },
        depends=['copy_to_resources_visible'])
    copy_to_resources_visible = fields.Function(
        fields.Boolean("Copy to Resources Visible"),
        'on_change_with_copy_to_resources_visible')
    last_user = fields.Function(
        fields.Char('Last User', states={
            'invisible': ~Eval('last_user'),
        }), 'get_last_user')
    last_modification = fields.Function(
        fields.DateTime('Last Modification',
                        states={
                            'invisible': ~Eval('last_modification'),
                        }), 'get_last_modification')

    @classmethod
    def __setup__(cls):
        super(ResourceMixin, cls).__setup__()
        cls._order.insert(0, ('last_modification', 'DESC'))
        cls.resource.required = True

    @fields.depends('resource')
    def get_copy_to_resources(self):
        pool = Pool()
        Model = pool.get('ir.model')
        resources = []
        if isinstance(self.resource, ResourceCopyMixin):
            models = self.resource.get_resources_to_copy(self.__name__)
            if models:
                models = Model.search([
                    ('model', 'in', models),
                ])
                resources.extend((m.model, m.name) for m in models)
        return resources

    @fields.depends(methods=['get_copy_to_resources'])
    def on_change_with_copy_to_resources_visible(self, name=None):
        return bool(self.get_copy_to_resources())

    def get_last_user(self, name):
        return (self.write_uid.rec_name
                if self.write_uid else self.create_uid.rec_name)

    def get_last_modification(self, name):
        return (self.write_date if self.write_date else
                self.create_date).replace(microsecond=0)

    @staticmethod
    def order_last_modification(tables):
        table, _ = tables[None]
        return [Coalesce(table.write_date, table.create_date)]
Esempio n. 3
0
class Template(metaclass=PoolMeta):
    __name__ = 'product.template'

    lot_required = fields.MultiSelection(
        [
            ('supplier', "Supplier"),
            ('customer', "Customer"),
            ('lost_found', "Lost and Found"),
            ('storage', "Storage"),
            ('production', "Production"),
        ],
        "Lot Required",
        help='The type of location for which lot is required.',
        states={
            'invisible': ~Eval('type').in_(['goods', 'assets']),
        },
        depends=['type'])

    @classmethod
    def __register__(cls, module):
        connection = Transaction().connection
        cursor = connection.cursor()

        super().__register__(module)

        table_h = cls.__table_handler__(module)
        template_lot_type_table_name = config.get(
            'table',
            'product.template-stock.lot.type',
            default='product.template-stock.lot.type'.replace('.', '_'))
        lot_type_table_name = config.get('table',
                                         'stock.lot.type',
                                         default='stock.lot.type'.replace(
                                             '.', '_'))

        # Migration from 5.2: fill lot_required
        if (table_h.table_exist(template_lot_type_table_name)
                and table_h.table_exist(lot_type_table_name)):
            table = cls.__table__()
            template_lot_type = Table(template_lot_type_table_name)
            lot_type = Table(lot_type_table_name)

            cursor_select = connection.cursor()
            cursor_select.execute(*template_lot_type.select(
                template_lot_type.template,
                distinct_on=template_lot_type.template))
            for template_id, in cursor_select:
                cursor.execute(*template_lot_type.join(
                    lot_type, condition=template_lot_type.type == lot_type.id
                ).select(lot_type.code,
                         where=template_lot_type.template == template_id))
                value = cls.lot_required.sql_format([t for t, in cursor])
                cursor.execute(*table.update([table.lot_required], [value],
                                             where=table.id == template_id))
            table_h.drop_table('product.template-stock.lot.type',
                               template_lot_type_table_name)
            table_h.drop_table('stock.lot.type', lot_type_table_name)
Esempio n. 4
0
class ModelStorageEvalEnvironment(ModelStorage_):
    "Model for EvalEnvironment"
    __name__ = 'test.modelstorage.eval_environment'
    char = fields.Char("Name")
    reference = fields.Reference("Reference", [
        ('test.modelstorage.eval_environment', "Reference"),
    ])
    multiselection = fields.MultiSelection([
        ('value1', "Value1"),
        ('value2', "Value2"),
    ], "MultiSelection")
    many2one = fields.Many2One('test.modelstorage.eval_environment',
                               "Many2One")
    one2many = fields.One2Many('test.modelstorage.eval_environment',
                               'many2one', "One2Many")
Esempio n. 5
0
class MultiSelection(ModelSQL):
    'MultiSelection'
    __name__ = 'test.multi_selection'
    selects = fields.MultiSelection([
        ('foo', "Foo"),
        ('bar', "Bar"),
        ('foobar', "FooBar"),
    ], "Selections")
    selects_string = selects.translated('selects')
    dyn_selects = fields.MultiSelection('get_dyn_selection',
                                        "Dynamic Selections")
    static_selects = fields.MultiSelection('get_static_selection',
                                           "Static Selectsions")

    @fields.depends('selects')
    def get_dyn_selection(self):
        if self.selects and 'foo' in self.selects:
            return [('foo', "Foo"), ('foobar', "FooBar")]
        else:
            return [('bar', "Bar"), ('baz', "Baz")]

    @classmethod
    def get_static_selection(cls):
        return cls.selects.selection
Esempio n. 6
0
class ModelViewChangedValues(ModelView):
    'ModelView Changed Values'
    __name__ = 'test.modelview.changed_values'
    name = fields.Char('Name')
    target = fields.Many2One('test.modelview.changed_values.target', 'Target')
    stored_target = fields.Many2One(
        'test.modelview.changed_values.stored_target', "Stored Target")
    ref_target = fields.Reference('Target Reference', [
        ('test.modelview.changed_values.target', 'Target'),
    ])
    targets = fields.One2Many('test.modelview.changed_values.target', 'parent',
                              'Targets')
    m2m_targets = fields.Many2Many('test.modelview.changed_values.target',
                                   None, None, 'Targets')
    multiselection = fields.MultiSelection([
        ('a', 'A'),
        ('b', 'B'),
    ], "MultiSelection")
    dictionary = fields.Dict('test.modelview.changed_values.dictionary',
                             "Dictionary")
Esempio n. 7
0
class WorkStatus(DeactivableMixin, sequence_ordered(), ModelSQL, ModelView):
    'Work Status'
    __name__ = 'project.work.status'

    _get_default_status_cache = Cache('project_work_status.get_default_status')
    _get_window_domains_cache = Cache('project_work_status.get_window_domains')

    types = fields.MultiSelection(
        'get_types', "Types",
        help="The type of works which can use this status.")
    name = fields.Char("Name", required=True, translate=True)
    progress = fields.Float(
        "Progress",
        domain=['OR',
            ('progress', '=', None),
            [
                ('progress', '>=', 0),
                ('progress', '<=', 1),
                ],
            ],
        help="The minimum progress required for this status.")
    default = fields.Boolean(
        "Default",
        help="Check to use as default status for the type.")
    count = fields.Boolean(
        "Count",
        help="Check to show the number of works in this status.")

    @classmethod
    def get_types(cls):
        pool = Pool()
        Work = pool.get('project.work')
        return Work.fields_get(['type'])['type']['selection']

    @classmethod
    def get_default_status(cls, type_=None):
        if type_ is None:
            return None
        status = cls._get_default_status_cache.get(type_, -1)
        if status != -1:
            return status
        records = cls.search([
                ('types', 'in', type_),
                ('default', '=', True)
                ], limit=1)
        if records:
            status = records[0].id
        else:
            status = None
        cls._get_default_status_cache.set(type, status)
        return status

    @classmethod
    def create(cls, vlist):
        cls._get_default_status_cache.clear()
        cls._get_window_domains_cache.clear()
        return super().create(vlist)

    @classmethod
    def write(cls, *args):
        super().write(*args)
        cls._get_default_status_cache.clear()
        cls._get_window_domains_cache.clear()

    @classmethod
    def delete(cls, status):
        cls._get_default_status_cache.clear()
        cls._get_window_domains_cache.clear()
        super().delete(status)

    @classmethod
    def get_window_domains(cls, action):
        pool = Pool()
        Data = pool.get('ir.model.data')
        if action.id == Data.get_id('project', 'act_project_tree'):
            return cls._get_window_domains([x[0] for x in cls.get_types()])
        elif action.id == Data.get_id('project', 'act_project_form'):
            return cls._get_window_domains(['project'])
        elif action.id == Data.get_id('project', 'act_task_form'):
            return cls._get_window_domains(['task'])
        else:
            return []

    @classmethod
    def _get_window_domains(cls, types):
        key = tuple(sorted(types))
        domains = cls._get_window_domains_cache.get(key)
        if domains is not None:
            return domains
        encoder = PYSONEncoder()
        domains = []
        for status in cls.search([('types', 'in', types)]):
            domain = encoder.encode([('status', '=', status.id)])
            domains.append((status.name, domain, status.count))
        if domains:
            domains.append(
                (gettext('project.msg_domain_all'), '[]', False))
        cls._get_window_domains_cache.set(key, domains)
        return domains
Esempio n. 8
0
class Configuration(ModelSingleton, ModelSQL, ModelView, MultiValueMixin):
    'Party Configuration'
    __name__ = 'party.configuration'

    party_sequence = fields.MultiValue(party_sequence)
    party_lang = fields.MultiValue(party_lang)
    identifier_types = fields.MultiSelection(
        IDENTIFIER_TYPES,
        "Identifier Types",
        help="Defines which identifier types are available.\n"
        "Leave empty for all of them.")

    @classmethod
    def default_party_sequence(cls, **pattern):
        pool = Pool()
        ModelData = pool.get('ir.model.data')
        try:
            return ModelData.get_id('party', 'sequence_party')
        except KeyError:
            return None

    def get_identifier_types(self):
        selection = self.fields_get(['identifier_types'
                                     ])['identifier_types']['selection']
        if self.identifier_types:
            selection = [(k, v) for k, v in selection
                         if k in self.identifier_types]
        return selection

    @classmethod
    def create(cls, vlist):
        records = super().create(vlist)
        ModelView._fields_view_get_cache.clear()
        return records

    @classmethod
    def write(cls, *args):
        super().write(*args)
        ModelView._fields_view_get_cache.clear()

    @classmethod
    def delete(cls, records):
        super().delete(records)
        ModelView._fields_view_get_cache.clear()

    @classmethod
    def validate(cls, records):
        super().validate(records)
        cls(1).check_identifier_types()

    def check_identifier_types(self):
        pool = Pool()
        Identifier = pool.get('party.identifier')
        if self.identifier_types:
            identifiers = Identifier.search([
                ('type', 'not in', [None, ''] + self.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,
                    ))
Esempio n. 9
0
class Address(DeactivableMixin, sequence_ordered(), ModelSQL, ModelView):
    "Address"
    __name__ = 'party.address'
    party = fields.Many2One('party.party',
                            'Party',
                            required=True,
                            ondelete='CASCADE',
                            select=True,
                            states={
                                'readonly':
                                If(~Eval('active'), True,
                                   Eval('id', 0) > 0),
                            },
                            depends=['active', 'id'])
    party_name = fields.Char(
        "Party Name",
        states=STATES,
        depends=DEPENDS,
        help="If filled, replace the name of the party for address formatting")
    name = fields.Char("Building Name", states=STATES, depends=DEPENDS)
    street = fields.Text("Street", states=STATES, depends=DEPENDS)
    zip = fields.Char('Zip', states=STATES, depends=DEPENDS)
    city = fields.Char('City', states=STATES, depends=DEPENDS)
    country = fields.Many2One('country.country',
                              'Country',
                              states=STATES,
                              depends=DEPENDS)
    subdivision_types = fields.Function(
        fields.MultiSelection('get_subdivision_types', "Subdivision Types"),
        'on_change_with_subdivision_types')
    subdivision = fields.Many2One(
        "country.subdivision",
        'Subdivision',
        domain=[
            ('country', '=', Eval('country', -1)),
            If(Eval('subdivision_types', []),
               ('type', 'in', Eval('subdivision_types', [])), ()),
        ],
        states=STATES,
        depends=['active', 'country', 'subdivision_types'])
    full_address = fields.Function(fields.Text('Full Address'),
                                   'get_full_address')

    @classmethod
    def __setup__(cls):
        super(Address, cls).__setup__()
        cls._order.insert(0, ('party', 'ASC'))
        cls.__rpc__.update(
            autocomplete_zip=RPC(instantiate=0, cache=dict(days=1)),
            autocomplete_city=RPC(instantiate=0, cache=dict(days=1)),
        )

    @classmethod
    def __register__(cls, module_name):
        cursor = Transaction().connection.cursor()
        sql_table = cls.__table__()

        super(Address, cls).__register__(module_name)

        table = cls.__table_handler__(module_name)

        # Migration from 4.0: remove streetbis
        if table.column_exist('streetbis'):
            value = Concat(Coalesce(sql_table.street, ''),
                           Concat('\n', Coalesce(sql_table.streetbis, '')))
            cursor.execute(*sql_table.update([sql_table.street], [value]))
            table.drop_column('streetbis')

    _autocomplete_limit = 100

    @fields.depends('country', 'subdivision')
    def _autocomplete_domain(self):
        domain = []
        if self.country:
            domain.append(('country', '=', self.country.id))
        if self.subdivision:
            domain.append([
                'OR',
                ('subdivision', 'child_of', [self.subdivision.id], 'parent'),
                ('subdivision', '=', None),
            ])
        return domain

    def _autocomplete_search(self, domain, name):
        pool = Pool()
        Zip = pool.get('country.zip')
        if domain:
            records = Zip.search(domain, limit=self._autocomplete_limit)
            if len(records) < self._autocomplete_limit:
                return sorted({getattr(z, name) for z in records})
        return []

    @fields.depends('city', methods=['_autocomplete_domain'])
    def autocomplete_zip(self):
        domain = self._autocomplete_domain()
        if self.city:
            domain.append(('city', 'ilike', '%%%s%%' % self.city))
        return self._autocomplete_search(domain, 'zip')

    @fields.depends('zip', methods=['_autocomplete_domain'])
    def autocomplete_city(self):
        domain = self._autocomplete_domain()
        if self.zip:
            domain.append(('zip', 'ilike', '%s%%' % self.zip))
        return self._autocomplete_search(domain, 'city')

    def get_full_address(self, name):
        pool = Pool()
        AddressFormat = pool.get('party.address.format')
        full_address = Template(AddressFormat.get_format(self)).substitute(
            **self._get_address_substitutions())
        return '\n'.join(
            filter(None, (x.strip() for x in full_address.splitlines())))

    def _get_address_substitutions(self):
        context = Transaction().context
        subdivision_code = ''
        if getattr(self, 'subdivision', None):
            subdivision_code = self.subdivision.code or ''
            if '-' in subdivision_code:
                subdivision_code = subdivision_code.split('-', 1)[1]
        substitutions = {
            'party_name':
            '',
            'attn':
            '',
            'name':
            getattr(self, 'name', None) or '',
            'street':
            getattr(self, 'street', None) or '',
            'zip':
            getattr(self, 'zip', None) or '',
            'city':
            getattr(self, 'city', None) or '',
            'subdivision': (self.subdivision.name if getattr(
                self, 'subdivision', None) else ''),
            'subdivision_code':
            subdivision_code,
            'country':
            (self.country.name if getattr(self, 'country', None) else ''),
            'country_code': (self.country.code or '' if getattr(
                self, 'country', None) else ''),
        }
        if context.get('address_from_country') == getattr(self, 'country', ''):
            substitutions['country'] = ''
        if context.get('address_with_party', False):
            substitutions['party_name'] = self.party_full_name
        if context.get('address_attention_party', False):
            substitutions['attn'] = (
                context['address_attention_party'].full_name)
        for key, value in list(substitutions.items()):
            substitutions[key.upper()] = value.upper()
        return substitutions

    @property
    def party_full_name(self):
        name = ''
        if self.party_name:
            name = self.party_name
        elif self.party:
            name = self.party.full_name
        return name

    def get_rec_name(self, name):
        party = self.party_full_name
        if self.street:
            street = self.street.splitlines()[0]
        else:
            street = None
        if self.country:
            country = self.country.code
        else:
            country = None
        return ', '.join(
            filter(None,
                   [party, self.name, street, self.zip, self.city, country]))

    @classmethod
    def search_rec_name(cls, name, clause):
        if clause[1].startswith('!') or clause[1].startswith('not '):
            bool_op = 'AND'
        else:
            bool_op = 'OR'
        return [
            bool_op,
            ('party', ) + tuple(clause[1:]),
            ('name', ) + tuple(clause[1:]),
            ('street', ) + tuple(clause[1:]),
            ('zip', ) + tuple(clause[1:]),
            ('city', ) + tuple(clause[1:]),
            ('country', ) + tuple(clause[1:]),
        ]

    @classmethod
    def write(cls, *args):
        actions = iter(args)
        for addresses, values in zip(actions, actions):
            if 'party' in values:
                for address in addresses:
                    if address.party.id != values['party']:
                        raise AccessError(
                            gettext('party.msg_address_change_party',
                                    address=address.rec_name))
        super(Address, cls).write(*args)

    @fields.depends('subdivision', 'country')
    def on_change_country(self):
        if (self.subdivision and self.subdivision.country != self.country):
            self.subdivision = None

    @classmethod
    def get_subdivision_types(cls):
        pool = Pool()
        Subdivision = pool.get('country.subdivision')
        return Subdivision.fields_get(['type'])['type']['selection']

    @fields.depends('country')
    def on_change_with_subdivision_types(self, name=None):
        pool = Pool()
        Types = pool.get('party.address.subdivision_type')
        return Types.get_types(self.country)
Esempio n. 10
0
class LabWorkYear(ModelSQL, ModelView, CompanyMultiValueMixin):
    'Work Year'
    __name__ = 'lims.lab.workyear'
    _rec_name = 'code'

    code = fields.Char('Code', required=True)
    start_date = fields.Date('Start date', required=True)
    end_date = fields.Date('End date', required=True)
    entry_sequence = fields.MultiValue(
        fields.Many2One('ir.sequence',
                        'Entry Sequence',
                        required=True,
                        domain=[
                            ('sequence_type', '=', Id('lims',
                                                      'seq_type_entry')),
                            ('company', 'in',
                             [Eval('context', {}).get('company', -1), None]),
                        ]))
    sample_sequence = fields.MultiValue(
        fields.Many2One('ir.sequence',
                        'Sample Sequence',
                        required=True,
                        domain=[
                            ('sequence_type', '=', Id('lims',
                                                      'seq_type_sample')),
                            ('company', 'in',
                             [Eval('context', {}).get('company', -1), None]),
                        ]))
    service_sequence = fields.MultiValue(
        fields.Many2One('ir.sequence',
                        'Service Sequence',
                        required=True,
                        domain=[
                            ('sequence_type', '=',
                             Id('lims', 'seq_type_service')),
                            ('company', 'in',
                             [Eval('context', {}).get('company', -1), None]),
                        ]))
    results_report_sequence = fields.MultiValue(
        fields.Many2One('ir.sequence',
                        'Results Report Sequence',
                        required=True,
                        domain=[
                            ('sequence_type', '=',
                             Id('lims', 'seq_type_results_report')),
                            ('company', 'in',
                             [Eval('context', {}).get('company', -1), None]),
                        ]))
    sequences = fields.One2Many('lims.lab.workyear.sequence', 'workyear',
                                'Sequences')
    default_entry_control = fields.Many2One('lims.entry',
                                            'Default entry control')
    workdays = fields.MultiSelection([
        (0, 'Monday'),
        (1, 'Tuesday'),
        (2, 'Wednesday'),
        (3, 'Thursday'),
        (4, 'Friday'),
        (5, 'Saturday'),
        (6, 'Sunday'),
    ],
                                     'Working days',
                                     sort=False)
    holidays = fields.One2Many('lims.lab.workyear.holiday', 'workyear',
                               'Holidays')

    @classmethod
    def __setup__(cls):
        super().__setup__()
        cls._order.insert(0, ('start_date', 'ASC'))

    @classmethod
    def multivalue_model(cls, field):
        pool = Pool()
        if field in sequence_names:
            return pool.get('lims.lab.workyear.sequence')
        return super().multivalue_model(field)

    @classmethod
    def default_entry_sequence(cls, **pattern):
        return cls.multivalue_model('entry_sequence').default_entry_sequence()

    @classmethod
    def default_sample_sequence(cls, **pattern):
        return cls.multivalue_model(
            'sample_sequence').default_sample_sequence()

    @classmethod
    def default_service_sequence(cls, **pattern):
        return cls.multivalue_model(
            'service_sequence').default_service_sequence()

    @staticmethod
    def default_workdays():
        return (0, 1, 2, 3, 4)

    @classmethod
    def validate(cls, years):
        super().validate(years)
        for year in years:
            year.check_dates()

    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,
                ))

    @classmethod
    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

    def get_sequence(self, type):
        sequence = getattr(self, type + '_sequence')
        if sequence:
            return sequence

    def get_target_date(self, start_date, days):
        total_days = days + 1  # plus 1 because start_date is included
        ruleset = rrule.rruleset()

        min_time = datetime.min.time()
        for h in self.holidays:
            ruleset.exdate(datetime.combine(h.date, min_time))

        count = total_days
        ruleset.rrule(
            rrule.rrule(rrule.DAILY,
                        byweekday=self.workdays,
                        dtstart=start_date,
                        count=count))
        while (ruleset.count() < total_days):  # because holidays subtract days
            count += 1
            ruleset.rrule(
                rrule.rrule(rrule.DAILY,
                            byweekday=self.workdays,
                            dtstart=start_date,
                            count=count))

        return ruleset[-1].date()
Esempio n. 11
0
class MultiSelectionRequired(ModelSQL):
    "MultiSelection Required"
    __name__ = 'test.multi_selection_required'
    selects = fields.MultiSelection([('foo', "Foo"), ('bar', "Bar")],
                                    "Selects",
                                    required=True)
Esempio n. 12
0
class Template(metaclass=PoolMeta):
    __name__ = 'product.template'

    lot_required = fields.MultiSelection(
        [
            ('supplier', "Supplier"),
            ('customer', "Customer"),
            ('lost_found', "Lost and Found"),
            ('storage', "Storage"),
            ('production', "Production"),
        ],
        "Lot Required",
        help='The type of location for which lot is required.',
        states={
            'invisible': ~Eval('type').in_(['goods', 'assets']),
        })
    lot_sequence = fields.Many2One(
        'ir.sequence',
        "Lot Sequence",
        domain=[
            ('sequence_type', '=', Id('stock_lot', 'sequence_type_stock_lot')),
        ],
        states={
            'invisible': ~Eval('type').in_(['goods', 'assets']),
        },
        help="The sequence used to automatically number lots.")

    @classmethod
    def __register__(cls, module):
        connection = Transaction().connection
        cursor = connection.cursor()

        super().__register__(module)

        table_h = cls.__table_handler__(module)
        template_lot_type_table_name = config.get(
            'table',
            'product.template-stock.lot.type',
            default='product.template-stock.lot.type'.replace('.', '_'))
        lot_type_table_name = config.get('table',
                                         'stock.lot.type',
                                         default='stock.lot.type'.replace(
                                             '.', '_'))

        # Migration from 5.2: fill lot_required
        if (table_h.table_exist(template_lot_type_table_name)
                and table_h.table_exist(lot_type_table_name)):
            table = cls.__table__()
            template_lot_type = Table(template_lot_type_table_name)
            lot_type = Table(lot_type_table_name)

            cursor_select = connection.cursor()
            cursor_select.execute(*template_lot_type.select(
                template_lot_type.template,
                distinct_on=template_lot_type.template))
            for template_id, in cursor_select:
                cursor.execute(*template_lot_type.join(
                    lot_type, condition=template_lot_type.type == lot_type.id
                ).select(lot_type.code,
                         where=template_lot_type.template == template_id))
                value = cls.lot_required.sql_format([t for t, in cursor])
                cursor.execute(*table.update([table.lot_required], [value],
                                             where=table.id == template_id))
            table_h.drop_table('product.template-stock.lot.type',
                               template_lot_type_table_name)
            table_h.drop_table('stock.lot.type', lot_type_table_name)

    @classmethod
    def default_lot_sequence(cls, **pattern):
        pool = Pool()
        Configuration = pool.get('product.configuration')
        sequence = Configuration(1).get_multivalue('default_lot_sequence',
                                                   **pattern)
        return sequence.id if sequence else None
Esempio n. 13
0
class PerformVisitAddress(ModelView):
    "Perform Visit Address"
    __name__ = 'sale.direct.visit.perform.address'

    new_address = fields.Boolean("New Address")

    address = fields.Many2One('party.address',
                              "Address",
                              states={
                                  'invisible': Eval('new_address', False),
                              },
                              depends=['new_address'])

    _states = {
        'invisible': ~Eval('new_address'),
    }
    _depends = ['new_address']

    name = fields.Char("Building Name",
                       states={
                           'invisible': ~Eval('new_address', False),
                           'required': Eval('new_address', False),
                       },
                       depends=_depends)
    street = fields.Text("Street", states=_states, depends=_depends)
    postal_code = fields.Char("Postal Code", states=_states, depends=_depends)
    city = fields.Char("City", states=_states, depends=_depends)
    country = fields.Many2One('country.country',
                              "Country",
                              states=_states,
                              depends=_depends)
    subdivision_types = fields.Function(
        fields.MultiSelection('get_subdivision_types',
                              "Subdivision Types",
                              states=_states,
                              depends=_depends),
        'on_change_with_subdivision_types')
    subdivision = fields.Many2One(
        'country.subdivision',
        "Subdivision",
        domain=[
            ('country', '=', Eval('country', -1)),
            If(Eval('subdivision_types', []),
               ('type', 'in', Eval('subdivision_types', [])), ()),
        ],
        states=_states,
        depends=_depends + ['country', 'subdivision_types'])

    del _states, _depends

    @fields.depends('subdivision', 'country')
    def on_change_country(self):
        if (self.subdivision and self.subdivision.country != self.country):
            self.subdivision = None

    @classmethod
    def get_subdivision_types(cls):
        pool = Pool()
        Subdivision = pool.get('country.subdivision')
        return Subdivision.fields_get(['type'])['type']['selection']

    @fields.depends('country')
    def on_change_with_subdivision_types(self, name=None):
        pool = Pool()
        Types = pool.get('party.address.subdivision_type')
        return Types.get_types(self.country)