Commit e885f059 authored by Luca Cristaldi's avatar Luca Cristaldi
Browse files

style changes and some more

parent 79745bf3
Loading
Loading
Loading
Loading
+58 −61
Original line number Diff line number Diff line
@@ -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'
@@ -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,
@@ -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))
@@ -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')}

+72 −35
Original line number Diff line number Diff line
@@ -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"),
]
@@ -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,
@@ -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(
@@ -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=[
@@ -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')
@@ -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')
@@ -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=[
@@ -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:
@@ -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,
@@ -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:
@@ -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({
@@ -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'
@@ -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:
@@ -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,
@@ -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

@@ -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):
+7 −1
Original line number Diff line number Diff line
@@ -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
+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
@@ -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):
@@ -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


@@ -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))
@@ -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'),
+1 −1
Original line number Diff line number Diff line
@@ -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