Loading member.py +58 −61 Original line number Diff line number Diff line Loading @@ -30,8 +30,7 @@ class Member(Workflow, ModelSQL, ModelView): ], "State", readonly=True) code = fields.Char("Code", select=True, code = fields.Char("Code", select=True, states={ 'readonly': Eval('code_readonly', True), 'required': Eval('state') != 'draft' Loading @@ -40,14 +39,12 @@ class Member(Workflow, ModelSQL, ModelView): help="The internal identifier for the associate.") code_readonly = fields.Function(fields.Boolean("Code Readonly"), 'get_code_readonly') company = fields.Many2One('company.company', "Company", company = fields.Many2One('company.company', "Company", states={'readonly': Eval('state') != 'draft'}, depends=_depends, required=True, help="The association this member belongs to.") party = fields.Many2One('party.party', "Party", help="The association the member belongs to.") party = fields.Many2One('party.party', "Party", states={'readonly': Eval('state') != 'draft'}, depends=_depends, required=True, Loading Loading @@ -84,8 +81,7 @@ class Member(Workflow, ModelSQL, ModelView): 'readonly': Eval('state') != 'running' }, help="The date the member left the association.") memberships = fields.One2Many('association.membership', 'member', memberships = fields.One2Many('association.membership', 'member', "Memberships", domain=[ ('company', '=', Eval('company', -1)) Loading @@ -102,6 +98,7 @@ class Member(Workflow, ModelSQL, ModelView): cls._sql_constraints = [ ('code_uniq', Unique(t, t.code), 'Member code must be unique.'), ] cls._transitions |= {('draft', 'running'), ('running', 'draft'), ('running', 'stopped')} Loading membership.py +72 −35 Original line number Diff line number Diff line Loading @@ -21,20 +21,13 @@ __all__ = [ fee_digit = (16, config.getint('membership', 'fee_decimal', default=4)) fee_amount = fields.Numeric("Fee Amount", fee_digit, required=True) _LINE_STATES = {'readonly': Eval('member_state') != 'draft'} _FEE_STATES = { 'readonly': Bool(Eval('move')) and Eval('fee', Decimal('0.0')) == Decimal('0.0') } _MEMBER_STATES = [ ('draft', "Draft"), ('running', "Running"), ('stopped', "Stopped"), ] _MOVE_STATE_SELECTION = [ _MOVE_STATES = [ ('draft', "Draft"), ('posted', "Posted"), ] Loading @@ -45,7 +38,7 @@ class MembershipType(ModelSQL, ModelView): __name__ = 'association.membership.type' name = fields.Char('Name', size=None, required=True) periods = fields.One2Many('association.membership.period', 'membership', periods = fields.One2Many('association.membership.period', 'membership_type', "Periods", help="The periods that form the basis of the membership type.") journal = fields.Many2One('account.journal', "Journal", required=True, Loading Loading @@ -77,25 +70,29 @@ class Membership(ModelSQL, ModelView): """Membership""" __name__ = 'association.membership' _states = {'readonly': Eval('member_state') != 'draft'} _depends = ['member_state'] member = fields.Many2One('association.member', "Member", states=_LINE_STATES, states=_states, domain=[ ('company', '=', Eval('context', {}).get('company', -1)) ], depends=['member_state', 'company'], depends=_depends + ['company'], ondelete='CASCADE') membership = fields.Many2One('association.membership.type', "Membership", membership_type = fields.Many2One('association.membership.type', "Membership Type", domain=[ ('company', '=', Eval('context', {}).get('company', -1)) ], depends=['member_state', 'company'], states=_LINE_STATES, depends=_depends + ['company'], states=_states, ondelete='RESTRICT') company = fields.Many2One('company.company', "Company", required=True, domain=[ ('id', If(Eval('context', {}).contains('company'), '=', '!='), Eval('context', {}).get('company', -1)), ], select=True, states=_LINE_STATES, depends=['member_state']) ], select=True, states=_states, depends=_depends) start_date = fields.Date("Start Date", domain=[ If( Loading @@ -104,8 +101,8 @@ class Membership(ModelSQL, ModelView): ('start_date', '<=', Eval('end_date')), (), )], depends=['end_date', 'member_state'], states=_LINE_STATES, depends=_depends + ['end_date'], states=_states, help="The date when the membership starts.") end_date = fields.Date("End Date", domain=[ Loading @@ -114,8 +111,8 @@ class Membership(ModelSQL, ModelView): ('end_date', '>=', Eval('start_date')), (), )], depends=['start_date', 'member_state'], states=_LINE_STATES, depends=_depends + ['start_date'], states=_states, help="The date when the membership ends.") member_state = fields.Function(fields.Selection(_MEMBER_STATES, "Member State"), 'on_change_with_member_state') Loading @@ -124,6 +121,39 @@ class Membership(ModelSQL, ModelView): member_leave_date = fields.Function(fields.Date("Member Leave Date"), 'on_change_with_member_leave_date') del _states, _depends @classmethod def validate(cls, memberships): super().validate(memberships) for membership in memberships: membership.check_dates() def check_dates(self): transaction = Transaction() connection = transaction.connection transaction.database.lock(connection, self._table) table = self.__table__() cursor = connection.cursor() 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.membership_type == self.membership_type.id) & (table.id != self.id))) period_id = cursor.fetchone() if period_id: overlapping_period = self.__class__(period_id[0]) raise PeriodDateOverlapError( gettext('association.msg_overlapping_membership', first=self.rec_name, second=overlapping_period.rec_name)) @classmethod def default_company(cls): return Transaction().context.get('company') Loading @@ -148,7 +178,7 @@ class Period(ModelSQL, ModelView): """Membership period""" __name__ = 'association.membership.period' membership = fields.Many2One('association.membership.type', "Membership", membership_type = fields.Many2One('association.membership.type', "Membership Type", required=True, select=True, domain=[ Loading Loading @@ -207,7 +237,7 @@ class Period(ModelSQL, ModelView): & (table.end_date >= self.end_date)) | ((table.start_date >= self.start_date) & (table.end_date <= self.end_date))) & (table.membership == self.membership.id) & (table.membership_type == self.membership_type.id) & (table.id != self.id))) period_id = cursor.fetchone() if period_id: Loading @@ -222,17 +252,22 @@ class Fee(ModelSQL, ModelView): """Membership Fee""" __name__ = 'association.membership.fee' _states = { 'readonly': Bool(Eval('move')) and Eval('fee', Decimal('0.0')) == Decimal('0.0') } member = fields.Many2One('association.member', "Member", required=True, domain=[('state', '=', 'running')], states=_FEE_STATES, states=_states, ondelete='RESTRICT') period = fields.Many2One('association.membership.period', "Period", required=True, ondelete='RESTRICT', states=_FEE_STATES, states=_states, help="The period associated to this fee.") move = fields.Many2One('account.move', "Move", ondelete='RESTRICT', states=_FEE_STATES, states=_states, help="The accounting move associated to this fee.") company = fields.Many2One('company.company', "Company", required=True, select=True, Loading @@ -241,14 +276,16 @@ class Fee(ModelSQL, ModelView): Eval('context', {}).get('company', -1)), ], ondelete='RESTRICT', states=_FEE_STATES) move_state = fields.Function(fields.Selection(_MOVE_STATE_SELECTION, states=_states) move_state = fields.Function(fields.Selection(_MOVE_STATES, "Move State"), 'on_change_with_move_state') paid = fields.Function(fields.Boolean('paid'), 'is_paid') reconciled = fields.Function(fields.Date("Reconciled"), 'get_reconciled') amount = fields.Function(fields.Numeric("Amount", fee_digit), 'on_change_with_amount') del _states @fields.depends('period', '_parent_period.amount') def on_change_with_amount(self, name=None): if self.period: Loading @@ -261,7 +298,7 @@ class Fee(ModelSQL, ModelView): cls._sql_constraints = [ ('code_uniq', Unique(table, table.member, table.period), 'period associated with the member must be unique'), gettext('association.msg_period_unique')) ] cls._buttons.update({ Loading Loading @@ -315,8 +352,8 @@ class Fee(ModelSQL, ModelView): return max(r.date for r in reconciliations) def is_paid(self, name): return (self.reconciled is not None) or ( self.move is None and self.period.amount == Decimal('0.0')) return (self.reconciled is not None or self.move is None and self.period.amount == Decimal('0.0')) def get_move_line(self, amount, amount_second_currency): 'Return counterpart Move Line for the amount' Loading @@ -332,7 +369,7 @@ class Fee(ModelSQL, ModelView): if amount > 0: account = self.member.party.account_receivable else: account = self.period.membership.account_revenue account = self.period.membership_type.account_revenue party = None if account.party_required: Loading Loading @@ -360,8 +397,8 @@ class Fee(ModelSQL, ModelView): self.get_move_line(-self.period.amount, Decimal('0.0')) ] return Move(Period=period_id, journal=self.period.membership.journal, return Move(period=period_id, journal=self.period.membership_type.journal, date=move_date, origin=self, company=self.company, Loading Loading @@ -401,7 +438,7 @@ class Fee(ModelSQL, ModelView): or d.max), ('start_date', '>=', line.start_date or line.member.join_date or d.min), ('membership', '=', line.membership), ('membership_type', '=', line.membership_type), ]) return period Loading Loading @@ -458,7 +495,7 @@ class GenerateFeeStart(ModelView): "Create fees form" __name__ = 'association.membership.fee_create.start' date = fields.Date("Date", help="Generate fees until this date") date = fields.Date("Date", help="Generate fees up to this date.") @classmethod def default_date(cls): Loading message.xml +7 −1 Original line number Diff line number Diff line Loading @@ -16,10 +16,16 @@ this repository contains the full copyright notices and license terms. --> <field name="text">You cannot expel the member "%(member)s" because there are still some unpaid fees.</field> </record> <record model="ir.message" id="msg_period_fee_invalid"> <field name="text">The period "%(period)s" fee amount should have a value greather than zero.</field> <field name="text">TThe fee amount for period "%(period)s" must be greater than or equal to zero.</field> </record> <record model="ir.message" id="msg_party_receivable_missing"> <field name="text">The party "%(party)s" doesn't have an account receivable defined.</field> </record> <record model="ir.message" id="msg_period_unique"> <field name="text">The periods for each member must be unique.</field> </record> <record model="ir.message" id="msg_overlapping_membership"> <field name="text">The membership "%(first)s" overlaps with the period "%(second)s".</field> </record> </data> </tryton> No newline at end of file setup.py +14 −13 Original line number Diff line number Diff line #!/usr/bin/env python3 # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import io import os import re Loading @@ -9,9 +10,9 @@ from setuptools import setup, find_packages def read(fname): return io.open(os.path.join(os.path.dirname(__file__), fname), 'r', encoding='utf-8').read() return io.open( os.path.join(os.path.dirname(__file__), fname), 'r', encoding='utf-8').read() def get_require_version(name): Loading @@ -19,8 +20,8 @@ def get_require_version(name): require = '%s >= %s.%s.dev0, < %s.%s' else: require = '%s >= %s.%s, < %s.%s' require %= (name, major_version, minor_version, major_version, minor_version + 1) require %= (name, major_version, minor_version, major_version, minor_version + 1) return require Loading @@ -36,14 +37,15 @@ major_version = int(major_version) minor_version = int(minor_version) name = 'trytond_association' download_url = 'http://downloads.tryton.org/%s.%s/' % (major_version, minor_version) download_url = 'http://downloads.tryton.org/%s.%s/' % ( major_version, minor_version) if minor_version % 2: version = '%s.%s.dev0' % (major_version, minor_version) download_url = ('hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (name[8:], name, version)) download_url = ( 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % ( name[8:], name, version)) requires = ['python-sql', 'python-stdnum'] requires = ['python-sql'] for dep in info.get('depends', []): if not re.match(r'(ir|res)(\W|$)', dep): requires.append(get_require_version('trytond_%s' % dep)) Loading @@ -54,8 +56,7 @@ dependency_links = [] if minor_version % 2: dependency_links.append('https://trydevpi.tryton.org/') setup( name=name, setup(name=name, version=version, description='Tryton module for association management', long_description=read('README.rst'), Loading tests/scenario_honorary_membership.rst +1 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,7 @@ Create honorary membership:: Add membership to member:: >>> _ = member.memberships.new(membership=honorary) >>> _ = member.memberships.new(membership_type=honorary) >>> member.save() Enroll member:: Loading Loading
member.py +58 −61 Original line number Diff line number Diff line Loading @@ -30,8 +30,7 @@ class Member(Workflow, ModelSQL, ModelView): ], "State", readonly=True) code = fields.Char("Code", select=True, code = fields.Char("Code", select=True, states={ 'readonly': Eval('code_readonly', True), 'required': Eval('state') != 'draft' Loading @@ -40,14 +39,12 @@ class Member(Workflow, ModelSQL, ModelView): help="The internal identifier for the associate.") code_readonly = fields.Function(fields.Boolean("Code Readonly"), 'get_code_readonly') company = fields.Many2One('company.company', "Company", company = fields.Many2One('company.company', "Company", states={'readonly': Eval('state') != 'draft'}, depends=_depends, required=True, help="The association this member belongs to.") party = fields.Many2One('party.party', "Party", help="The association the member belongs to.") party = fields.Many2One('party.party', "Party", states={'readonly': Eval('state') != 'draft'}, depends=_depends, required=True, Loading Loading @@ -84,8 +81,7 @@ class Member(Workflow, ModelSQL, ModelView): 'readonly': Eval('state') != 'running' }, help="The date the member left the association.") memberships = fields.One2Many('association.membership', 'member', memberships = fields.One2Many('association.membership', 'member', "Memberships", domain=[ ('company', '=', Eval('company', -1)) Loading @@ -102,6 +98,7 @@ class Member(Workflow, ModelSQL, ModelView): cls._sql_constraints = [ ('code_uniq', Unique(t, t.code), 'Member code must be unique.'), ] cls._transitions |= {('draft', 'running'), ('running', 'draft'), ('running', 'stopped')} Loading
membership.py +72 −35 Original line number Diff line number Diff line Loading @@ -21,20 +21,13 @@ __all__ = [ fee_digit = (16, config.getint('membership', 'fee_decimal', default=4)) fee_amount = fields.Numeric("Fee Amount", fee_digit, required=True) _LINE_STATES = {'readonly': Eval('member_state') != 'draft'} _FEE_STATES = { 'readonly': Bool(Eval('move')) and Eval('fee', Decimal('0.0')) == Decimal('0.0') } _MEMBER_STATES = [ ('draft', "Draft"), ('running', "Running"), ('stopped', "Stopped"), ] _MOVE_STATE_SELECTION = [ _MOVE_STATES = [ ('draft', "Draft"), ('posted', "Posted"), ] Loading @@ -45,7 +38,7 @@ class MembershipType(ModelSQL, ModelView): __name__ = 'association.membership.type' name = fields.Char('Name', size=None, required=True) periods = fields.One2Many('association.membership.period', 'membership', periods = fields.One2Many('association.membership.period', 'membership_type', "Periods", help="The periods that form the basis of the membership type.") journal = fields.Many2One('account.journal', "Journal", required=True, Loading Loading @@ -77,25 +70,29 @@ class Membership(ModelSQL, ModelView): """Membership""" __name__ = 'association.membership' _states = {'readonly': Eval('member_state') != 'draft'} _depends = ['member_state'] member = fields.Many2One('association.member', "Member", states=_LINE_STATES, states=_states, domain=[ ('company', '=', Eval('context', {}).get('company', -1)) ], depends=['member_state', 'company'], depends=_depends + ['company'], ondelete='CASCADE') membership = fields.Many2One('association.membership.type', "Membership", membership_type = fields.Many2One('association.membership.type', "Membership Type", domain=[ ('company', '=', Eval('context', {}).get('company', -1)) ], depends=['member_state', 'company'], states=_LINE_STATES, depends=_depends + ['company'], states=_states, ondelete='RESTRICT') company = fields.Many2One('company.company', "Company", required=True, domain=[ ('id', If(Eval('context', {}).contains('company'), '=', '!='), Eval('context', {}).get('company', -1)), ], select=True, states=_LINE_STATES, depends=['member_state']) ], select=True, states=_states, depends=_depends) start_date = fields.Date("Start Date", domain=[ If( Loading @@ -104,8 +101,8 @@ class Membership(ModelSQL, ModelView): ('start_date', '<=', Eval('end_date')), (), )], depends=['end_date', 'member_state'], states=_LINE_STATES, depends=_depends + ['end_date'], states=_states, help="The date when the membership starts.") end_date = fields.Date("End Date", domain=[ Loading @@ -114,8 +111,8 @@ class Membership(ModelSQL, ModelView): ('end_date', '>=', Eval('start_date')), (), )], depends=['start_date', 'member_state'], states=_LINE_STATES, depends=_depends + ['start_date'], states=_states, help="The date when the membership ends.") member_state = fields.Function(fields.Selection(_MEMBER_STATES, "Member State"), 'on_change_with_member_state') Loading @@ -124,6 +121,39 @@ class Membership(ModelSQL, ModelView): member_leave_date = fields.Function(fields.Date("Member Leave Date"), 'on_change_with_member_leave_date') del _states, _depends @classmethod def validate(cls, memberships): super().validate(memberships) for membership in memberships: membership.check_dates() def check_dates(self): transaction = Transaction() connection = transaction.connection transaction.database.lock(connection, self._table) table = self.__table__() cursor = connection.cursor() 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.membership_type == self.membership_type.id) & (table.id != self.id))) period_id = cursor.fetchone() if period_id: overlapping_period = self.__class__(period_id[0]) raise PeriodDateOverlapError( gettext('association.msg_overlapping_membership', first=self.rec_name, second=overlapping_period.rec_name)) @classmethod def default_company(cls): return Transaction().context.get('company') Loading @@ -148,7 +178,7 @@ class Period(ModelSQL, ModelView): """Membership period""" __name__ = 'association.membership.period' membership = fields.Many2One('association.membership.type', "Membership", membership_type = fields.Many2One('association.membership.type', "Membership Type", required=True, select=True, domain=[ Loading Loading @@ -207,7 +237,7 @@ class Period(ModelSQL, ModelView): & (table.end_date >= self.end_date)) | ((table.start_date >= self.start_date) & (table.end_date <= self.end_date))) & (table.membership == self.membership.id) & (table.membership_type == self.membership_type.id) & (table.id != self.id))) period_id = cursor.fetchone() if period_id: Loading @@ -222,17 +252,22 @@ class Fee(ModelSQL, ModelView): """Membership Fee""" __name__ = 'association.membership.fee' _states = { 'readonly': Bool(Eval('move')) and Eval('fee', Decimal('0.0')) == Decimal('0.0') } member = fields.Many2One('association.member', "Member", required=True, domain=[('state', '=', 'running')], states=_FEE_STATES, states=_states, ondelete='RESTRICT') period = fields.Many2One('association.membership.period', "Period", required=True, ondelete='RESTRICT', states=_FEE_STATES, states=_states, help="The period associated to this fee.") move = fields.Many2One('account.move', "Move", ondelete='RESTRICT', states=_FEE_STATES, states=_states, help="The accounting move associated to this fee.") company = fields.Many2One('company.company', "Company", required=True, select=True, Loading @@ -241,14 +276,16 @@ class Fee(ModelSQL, ModelView): Eval('context', {}).get('company', -1)), ], ondelete='RESTRICT', states=_FEE_STATES) move_state = fields.Function(fields.Selection(_MOVE_STATE_SELECTION, states=_states) move_state = fields.Function(fields.Selection(_MOVE_STATES, "Move State"), 'on_change_with_move_state') paid = fields.Function(fields.Boolean('paid'), 'is_paid') reconciled = fields.Function(fields.Date("Reconciled"), 'get_reconciled') amount = fields.Function(fields.Numeric("Amount", fee_digit), 'on_change_with_amount') del _states @fields.depends('period', '_parent_period.amount') def on_change_with_amount(self, name=None): if self.period: Loading @@ -261,7 +298,7 @@ class Fee(ModelSQL, ModelView): cls._sql_constraints = [ ('code_uniq', Unique(table, table.member, table.period), 'period associated with the member must be unique'), gettext('association.msg_period_unique')) ] cls._buttons.update({ Loading Loading @@ -315,8 +352,8 @@ class Fee(ModelSQL, ModelView): return max(r.date for r in reconciliations) def is_paid(self, name): return (self.reconciled is not None) or ( self.move is None and self.period.amount == Decimal('0.0')) return (self.reconciled is not None or self.move is None and self.period.amount == Decimal('0.0')) def get_move_line(self, amount, amount_second_currency): 'Return counterpart Move Line for the amount' Loading @@ -332,7 +369,7 @@ class Fee(ModelSQL, ModelView): if amount > 0: account = self.member.party.account_receivable else: account = self.period.membership.account_revenue account = self.period.membership_type.account_revenue party = None if account.party_required: Loading Loading @@ -360,8 +397,8 @@ class Fee(ModelSQL, ModelView): self.get_move_line(-self.period.amount, Decimal('0.0')) ] return Move(Period=period_id, journal=self.period.membership.journal, return Move(period=period_id, journal=self.period.membership_type.journal, date=move_date, origin=self, company=self.company, Loading Loading @@ -401,7 +438,7 @@ class Fee(ModelSQL, ModelView): or d.max), ('start_date', '>=', line.start_date or line.member.join_date or d.min), ('membership', '=', line.membership), ('membership_type', '=', line.membership_type), ]) return period Loading Loading @@ -458,7 +495,7 @@ class GenerateFeeStart(ModelView): "Create fees form" __name__ = 'association.membership.fee_create.start' date = fields.Date("Date", help="Generate fees until this date") date = fields.Date("Date", help="Generate fees up to this date.") @classmethod def default_date(cls): Loading
message.xml +7 −1 Original line number Diff line number Diff line Loading @@ -16,10 +16,16 @@ this repository contains the full copyright notices and license terms. --> <field name="text">You cannot expel the member "%(member)s" because there are still some unpaid fees.</field> </record> <record model="ir.message" id="msg_period_fee_invalid"> <field name="text">The period "%(period)s" fee amount should have a value greather than zero.</field> <field name="text">TThe fee amount for period "%(period)s" must be greater than or equal to zero.</field> </record> <record model="ir.message" id="msg_party_receivable_missing"> <field name="text">The party "%(party)s" doesn't have an account receivable defined.</field> </record> <record model="ir.message" id="msg_period_unique"> <field name="text">The periods for each member must be unique.</field> </record> <record model="ir.message" id="msg_overlapping_membership"> <field name="text">The membership "%(first)s" overlaps with the period "%(second)s".</field> </record> </data> </tryton> No newline at end of file
setup.py +14 −13 Original line number Diff line number Diff line #!/usr/bin/env python3 # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import io import os import re Loading @@ -9,9 +10,9 @@ from setuptools import setup, find_packages def read(fname): return io.open(os.path.join(os.path.dirname(__file__), fname), 'r', encoding='utf-8').read() return io.open( os.path.join(os.path.dirname(__file__), fname), 'r', encoding='utf-8').read() def get_require_version(name): Loading @@ -19,8 +20,8 @@ def get_require_version(name): require = '%s >= %s.%s.dev0, < %s.%s' else: require = '%s >= %s.%s, < %s.%s' require %= (name, major_version, minor_version, major_version, minor_version + 1) require %= (name, major_version, minor_version, major_version, minor_version + 1) return require Loading @@ -36,14 +37,15 @@ major_version = int(major_version) minor_version = int(minor_version) name = 'trytond_association' download_url = 'http://downloads.tryton.org/%s.%s/' % (major_version, minor_version) download_url = 'http://downloads.tryton.org/%s.%s/' % ( major_version, minor_version) if minor_version % 2: version = '%s.%s.dev0' % (major_version, minor_version) download_url = ('hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (name[8:], name, version)) download_url = ( 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % ( name[8:], name, version)) requires = ['python-sql', 'python-stdnum'] requires = ['python-sql'] for dep in info.get('depends', []): if not re.match(r'(ir|res)(\W|$)', dep): requires.append(get_require_version('trytond_%s' % dep)) Loading @@ -54,8 +56,7 @@ dependency_links = [] if minor_version % 2: dependency_links.append('https://trydevpi.tryton.org/') setup( name=name, setup(name=name, version=version, description='Tryton module for association management', long_description=read('README.rst'), Loading
tests/scenario_honorary_membership.rst +1 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,7 @@ Create honorary membership:: Add membership to member:: >>> _ = member.memberships.new(membership=honorary) >>> _ = member.memberships.new(membership_type=honorary) >>> member.save() Enroll member:: Loading