Commit 79ecff23 authored by Luca Cristaldi's avatar Luca Cristaldi
Browse files

Merge files into association

And fix  party code
parent 4d721a7d
Loading
Loading
Loading
Loading
+12 −13
Original line number Diff line number Diff line
@@ -2,8 +2,7 @@
# this repository contains the full copyright notices and license terms.
from trytond.pool import Pool
from . import account
from . import member
from . import membership
from . import association
from . import configuration
from . import ir

@@ -13,22 +12,22 @@ __all__ = ['register']
def register():
    Pool.register(
        account.Move,
        association.Member,
        association.PrintMembersBookStart,
        association.MembershipType,
        association.Period,
        association.Fee,
        association.Membership,
        association.GenerateFeeStart,
        configuration.Configuration,
        configuration.MemberSequence,
        ir.Cron,
        member.Member,
        member.PrintMembersBookStart,
        membership.MembershipType,
        membership.Period,
        membership.Fee,
        membership.Membership,
        membership.GenerateFeeStart,
        module='association', type_='model')
    Pool.register(
        member.MembersBookWizard,
        membership.PostFee,
        membership.GenerateFee,
        association.MembersBookWizard,
        association.PostFee,
        association.GenerateFee,
        module='association', type_='wizard')
    Pool.register(
        member.MembersBookReport,
        association.MembersBookReport,
        module='association', type_='report')
+236 −7
Original line number Diff line number Diff line
@@ -3,19 +3,25 @@
from decimal import Decimal
from trytond.config import config
from trytond.i18n import gettext
from trytond.model import ModelSQL, ModelView, Unique, fields
from trytond.pool import Pool
from trytond.pyson import And, Eval, If, Bool
from trytond.model import Workflow, ModelView, ModelSQL, fields, Unique
from trytond.model.exceptions import AccessError
from trytond.pool import Pool
from trytond.pyson import Eval, If, Bool, And
from trytond.report import Report
from trytond.tools import lstrip_wildcard
from trytond.transaction import Transaction
from trytond.wizard import StateTransition, Wizard, StateView, Button
from trytond.wizard import (Wizard, StateView, Button, StateReport,
                            StateTransition)

from .exceptions import (PeriodDateOverlapError, AmountLessThanZeroError,
                         PartyAccountPayableRequiredError)
                         PartyAccountPayableRequiredError,
                         MemberUnpaidFeeError)


__all__ = [
    'Membership', 'Period', 'Fee', 'MembershipType', 'PostFee', 'GenerateFee',
    'GenerateFeeStart'
    'Member', 'MembersBookWizard', 'PrintMembersBookStart',
    'MembersBookReport', 'Membership', 'Period', 'Fee', 'MembershipType',
    'PostFee', 'GenerateFee', 'GenerateFeeStart'
]

fee_digit = (16, config.getint('membership', 'fee_decimal', default=4))
@@ -33,6 +39,229 @@ _MOVE_STATES = [
]


class Member(Workflow, ModelSQL, ModelView):
    'Member'
    __name__ = "association.member"

    _states = {'readonly': Eval('state') != 'draft'}
    _depends = ['state']

    state = fields.Selection(_MEMBER_STATES, "State", readonly=True)
    code = fields.Char("Code", select=True,
        states={
            'readonly': Eval('code_readonly', True),
            'required': Eval('state') != 'draft'
            },
        depends=_depends + ['code_readonly'],
        help="The internal identifier for the associate.")
    code_readonly = fields.Function(fields.Boolean("Code Readonly"),
                                    'get_code_readonly')
    company = fields.Many2One('company.company', "Company",
        states={'readonly': Eval('state') != 'draft'},
        depends=_depends,
        required=True,
        help="The association the member belongs to.")
    party = fields.Many2One('party.party', "Party",
        states={'readonly': Eval('state') != 'draft'},
        depends=_depends,
        required=True,
        help="The party that represents the member.")
    join_date = fields.Date("Join Date",
        states={
            'readonly':
            (Eval('state') != 'draft') | Eval('join_date'),
            'required':
            Eval('state') != 'draft'
        },
        domain=[
            If(
                (Eval('join_date')) & (Eval('leave_date')),
                ('join_date', '<=', Eval('leave_date')),
                (),
            )
        ],
        depends=_depends + ['leave_date'],
        help="The date the member joined the association.")
    leave_date = fields.Date("Leave Date",
        domain=[
            If(
                (Eval('join_date')) &
                (Eval('leave_date')),
                ('leave_date', '>=', Eval('join_date')),
                (),
            )
        ],
        depends=_depends + ['join_date'],
        states={
            'invisible': Eval('state') == 'draft',
            'required': Eval('state') == 'stopped',
            'readonly': Eval('state') != 'running'
        },
        help="The date the member left the association.")
    memberships = fields.One2Many('association.membership', 'member',
        "Memberships",
        domain=[
            ('company', '=', Eval('company', -1))
            ],
        depends=_depends + ['company'],
        states=_states)

    del _states, _depends

    @classmethod
    def __setup__(cls):
        super().__setup__()
        t = cls.__table__()
        cls._sql_constraints = [
            ('code_uniq', Unique(t, t.code), 'Member code must be unique.'),
        ]

        cls._transitions |= {('draft', 'running'), ('running', 'draft'),
                             ('running', 'stopped')}

        cls._buttons.update({
            'draft': {
                'invisible': Eval('state').in_(['draft', 'stopped']),
                'depends': ['state'],
            },
            'run': {
                'invisible': Eval('state').in_(['stopped', 'running']),
                'depends': ['state'],
            },
            'stop': {
                'invisible': Eval('state').in_(['draft', 'stopped']),
                'depends': ['state'],
            },
        })

    def get_code_readonly(self, name):
        return True

    @classmethod
    def _new_code(cls, **pattern):
        pool = Pool()
        Sequence = pool.get('ir.sequence')
        Configuration = pool.get('association.configuration')
        config = Configuration(1)
        sequence = config.get_multivalue('member_sequence', **pattern)
        if sequence:
            return Sequence.get_id(sequence.id)

    def get_rec_name(self, name):
        return self.party.rec_name

    @classmethod
    def search_rec_name(cls, name, clause):
        if clause[1].startswith('!') or clause[1].startswith('not '):
            bool_op = 'AND'
        else:
            bool_op = 'OR'
        code_value = clause[2]
        if clause[1].endswith('like'):
            code_value = lstrip_wildcard(clause[2])
        return [
            bool_op,
            ('code', clause[1], code_value) + tuple(clause[3:]),
            ('party', ) + tuple(clause[1:]),
        ]

    @classmethod
    def copy(cls, members, default=None):
        if default is None:
            default = {}
        else:
            default = default.copy()
        default.setdefault('code', None)
        default.setdefault('leave_date', None)
        return super().copy(members, default=default)

    @classmethod
    def default_state(cls):
        return 'draft'

    @classmethod
    def default_company(cls):
        return Transaction().context.get('company')

    @classmethod
    def default_code_readonly(cls, **pattern):
        Configuration = Pool().get('association.configuration')
        config = Configuration(1)
        return bool(config.get_multivalue('member_sequence', **pattern))

    @classmethod
    @ModelView.button
    @Workflow.transition('draft')
    def draft(cls, members):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('running')
    def run(cls, members):
        for member in members:
            if not member.code:
                member.code = cls._new_code()
        cls.save(members)

    @classmethod
    @ModelView.button
    @Workflow.transition('stopped')
    def stop(cls, members):
        pool = Pool()
        Fee = pool.get('association.membership.fee')
        pending_fees = Fee.search([('member', 'in', members)])
        if not all(x.paid for x in pending_fees):
            raise MemberUnpaidFeeError(
                gettext('association.msg_unpaid_fee',
                        member=", ".join([x.rec_name for x in members])))


class MembersBookReport(Report):
    'Members Book report'
    __name__ = 'association.member_print'

    @classmethod
    def get_context(cls, records, data):
        pool = Pool()
        Member = pool.get('association.member')
        Company = pool.get('company.company')
        clause = [('state', '!=', 'draft'), ('company', '=', data['company'])]
        context = super().get_context(records, data)
        members = Member.search(clause)
        context["members"] = members
        context["company"] = Company(data['company'])
        return context


class PrintMembersBookStart(ModelView):
    'Print Members Book'
    __name__ = 'association.member.print_member_book.start'
    company = fields.Many2One('company.company', 'Company', required=True)

    @staticmethod
    def default_company():
        return Transaction().context.get('company')


class MembersBookWizard(Wizard):
    'Print member book'
    __name__ = 'association.member.print_member_book'
    start = StateView(
        'association.member.print_member_book.start',
        'association.print_member_book_start_view_from', [
            Button('Cancel', 'end', 'tryton-cancel'),
            Button('Print', 'print_', 'tryton-print', default=True)
        ])
    print_ = StateReport('association.member_print')

    def do_print_(self, action):
        data = {
            'company': self.start.company.id,
        }
        return action, data


class MembershipType(ModelSQL, ModelView):
    """Membership Type"""
    __name__ = 'association.membership.type'
+181 −0
Original line number Diff line number Diff line
@@ -3,6 +3,187 @@
this repository contains the full copyright notices and license terms. -->
<tryton>
    <data depends="">
        <!-- Icons -->
        <record model="ir.ui.icon" id="association_icon">
            <field name="name">tryton-association</field>
            <field name="path">icons/tryton-association.svg</field>
        </record>
        <!-- Groups -->
        <record model="res.group" id="group_association">
            <field name="name">Association</field>
        </record>
        <record model="res.group" id="group_association_admin">
            <field name="name">Association Administrator</field>
        </record>
        <record model="res.group" id="group_member_approval">
            <field name="name">Member Approval</field>
        </record>
        <!-- Grant administation privileges to 'admin' -->
        <record model="res.user-res.group" id="user_admin_group_association">
            <field name="user" ref="res.user_admin" />
            <field name="group" ref="group_association" />
        </record>
        <record model="res.user-res.group" id="user_admin_group_association_admin">
            <field name="user" ref="res.user_admin" />
            <field name="group" ref="group_association_admin" />
        </record>
        <record model="res.user-res.group" id="user_admin_group_member_approval">
            <field name="user" ref="res.user_admin" />
            <field name="group" ref="group_member_approval" />
        </record>
        <menuitem name="Association" sequence="0" id="menu_association" icon="tryton-association" />
        <menuitem name="Configuration" parent="menu_association" id="menu_configuration" sequence="0" icon="tryton-settings" />
        <record model="ir.ui.menu-res.group" id="menu_configuration_group_association_admin">
            <field name="menu" ref="menu_configuration" />
            <field name="group" ref="group_association_admin" />
        </record>
        <record model="ir.ui.view" id="members_view_tree">
            <field name="model">association.member</field>
            <field name="type">tree</field>
            <field name="name">members_tree</field>
        </record>
        <record model="ir.ui.view" id="members_view_form">
            <field name="model">association.member</field>
            <field name="type">form</field>
            <field name="name">members_form</field>
        </record>
        <record model="ir.action.act_window" id="act_members_form">
            <field name="name">Members</field>
            <field name="res_model">association.member</field>
        </record>
        <record model="ir.action.act_window.view" id="act_members_form_view1">
            <field name="sequence" eval="10" />
            <field name="view" ref="members_view_tree" />
            <field name="act_window" ref="act_members_form" />
        </record>
        <record model="ir.action.act_window.view" id="act_members_form_view2">
            <field name="sequence" eval="20" />
            <field name="view" ref="members_view_form" />
            <field name="act_window" ref="act_members_form" />
        </record>
        <record model="ir.action.act_window.domain" id="act_members_form_domain_draft">
            <field name="name">Draft</field>
            <field name="sequence" eval="10" />
            <field name="domain" eval="[('state', '=', 'draft'), ('company', '=', Eval('context', {}).get('company', -1))]" pyson="1" />
            <field name="count" eval="True" />
            <field name="act_window" ref="act_members_form" />
        </record>
        <record model="ir.action.act_window.domain" id="act_members_form_domain_accepted">
            <field name="name">Running</field>
            <field name="sequence" eval="30" />
            <field name="domain" eval="[('state', '=', 'running'), ('company', '=', Eval('context', {}).get('company', -1))]" pyson="1" />
            <field name="count" eval="True" />
            <field name="act_window" ref="act_members_form" />
        </record>
        <record model="ir.action.act_window.domain" id="act_members_form_domain_expelled">
            <field name="name">Stopped</field>
            <field name="sequence" eval="40" />
            <field name="domain" eval="[('state', '=', 'stopped'), ('company', '=', Eval('context', {}).get('company', -1))]" pyson="1" />
            <field name="count" eval="True" />
            <field name="act_window" ref="act_members_form" />
        </record>
        <record model="ir.action.act_window.domain" id="act_members_form_domain_all">
            <field name="name">All</field>
            <field name="sequence" eval="40" />
            <field name="domain" eval="[('state', '!=', 'draft'), ('company', '=', Eval('context', {}).get('company', -1))]" pyson="1" />
            <field name="count" eval="False" />
            <field name="act_window" ref="act_members_form" />
        </record>
        <menuitem name="Members" sequence="1" parent="menu_association" id="menu_members" action="act_members_form" />
        <record model="ir.model.button" id="member_draft_button">
            <field name="name">draft</field>
            <field name="string">Draft</field>
            <field name="model" search="[('model', '=', 'association.member')]" />
        </record>
        <record model="ir.model.button" id="member_run_button">
            <field name="name">run</field>
            <field name="string">Run</field>
            <field name="model" search="[('model', '=', 'association.member')]" />
        </record>
        <record model="ir.model.button" id="member_stop_button">
            <field name="name">stop</field>
            <field name="string">Stop</field>
            <field name="model" search="[('model', '=', 'association.member')]" />
        </record>
        <record model="ir.model.access" id="access_member">
            <field name="model" search="[('model', '=', 'association.member')]" />
            <field name="perm_read" eval="True" />
            <field name="perm_write" eval="True" />
            <field name="perm_create" eval="True" />
            <field name="perm_delete" eval="True" />
        </record>
        <record model="ir.model.access" id="access_member_admin">
            <field name="model" search="[('model', '=', 'association.member')]" />
            <field name="group" ref="group_association_admin" />
            <field name="perm_read" eval="True" />
            <field name="perm_write" eval="True" />
            <field name="perm_create" eval="True" />
            <field name="perm_delete" eval="True" />
        </record>
        <record model="ir.model.button-res.group" id="member_run_button_group_member_approval">
            <field name="button" ref="member_run_button" />
            <field name="group" ref="group_member_approval" />
        </record>
        <record model="ir.model.button-res.group" id="member_draft_button_group_member_approval">
            <field name="button" ref="member_draft_button" />
            <field name="group" ref="group_member_approval" />
        </record>
        <record model="ir.model.button-res.group" id="member_approve_stop_group_member_approval">
            <field name="button" ref="member_stop_button" />
            <field name="group" ref="group_member_approval" />
        </record>
        <record model="ir.model.button-res.group" id="member_run_button_group_association_admin">
            <field name="button" ref="member_run_button" />
            <field name="group" ref="group_association_admin" />
        </record>
        <record model="ir.model.button-res.group" id="member_draft_button_group_association_admin">
            <field name="button" ref="member_draft_button" />
            <field name="group" ref="group_association_admin" />
        </record>
        <record model="ir.model.button-res.group" id="member_approve_stop_group_association_admin">
            <field name="button" ref="member_stop_button" />
            <field name="group" ref="group_association_admin" />
        </record>
        <!-- Sequence -->
        <record model="ir.sequence.type" id="sequence_type_member">
            <field name="name">Member</field>
            <field name="code">association.member</field>
        </record>
        <record model="ir.sequence.type-res.group" id="sequence_type_member_group_admin">
            <field name="sequence_type" ref="sequence_type_member" />
            <field name="group" ref="res.group_admin" />
        </record>
        <record model="ir.sequence.type-res.group" id="sequence_type_member_group_association_admin">
            <field name="sequence_type" ref="sequence_type_member" />
            <field name="group" ref="group_association_admin" />
        </record>
        <record model="ir.sequence" id="sequence_member">
            <field name="name">Member</field>
            <field name="code">association.member</field>
        </record>
        <!-- Report -->
        <record model="ir.action.report" id="report_members_book">
            <field name="name">Member Book</field>
            <field name="model">association.member</field>
            <field name="report_name">association.member_print</field>
            <field name="report">association/memberbook.fodt</field>
        </record>
        <record model="ir.action.keyword" id="report_members_book_keyword">
            <field name="keyword">form_print</field>
            <field name="model">association.member,-1</field>
            <field name="action" ref="report_members_book"/>
        </record>
        <!-- Wizard -->
        <record model="ir.ui.view" id="print_member_book_start_view_from">
            <field name="model">association.member.print_member_book.start</field>
            <field name="type">form</field>
            <field name="name">members_book_start_form</field>
        </record>
        <record model="ir.action.wizard" id="wizard_print_member_book">
            <field name="name">Print Member Book</field>
            <field name="wiz_name">association.member.print_member_book</field>
        </record>
        <menuitem parent="menu_association" sequence="80" action="wizard_print_member_book" id="menu_wizard_print_member_book" icon="tryton-print"/>
        <!-- Membership Type-->
        <record model="ir.ui.view" id="view_membership_type_tree">
            <field name="model">association.membership.type</field>
+2 −4
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ class Configuration(
    """Association Configuration"""
    __name__ = 'association.configuration'
    member_sequence = fields.MultiValue(
        fields.Many2One('ir.sequence', "Member Sequence", required=True,
        fields.Many2One('ir.sequence', "Member Sequence",
            domain=[
                ('company', 'in',
                    [Eval('context', {}).get('company', -1), None]),
@@ -29,12 +29,10 @@ class Configuration(
            cls.multivalue_model('member_sequence'),
            'default_member_sequence', lambda: None)()


class MemberSequence(ModelSQL, CompanyValueMixin):
    """Member Configuration Sequence"""
    __name__ = 'association.configuration.member_sequence'
    member_sequence = fields.Many2One('ir.sequence', "Member Sequence",
        required=True,
        domain=[
            ('company', 'in',
            [Eval('company', -1), None]),

member.py

deleted100644 → 0
+0 −245

File deleted.

Preview size limit exceeded, changes collapsed.

Loading