Exemple #1
0
class StaffList(ModelSQL, ModelView):
    'Staff list'
    _name = 'ekd.company.staff_list'
    _description = __doc__

    company = fields.Many2One('company.company', 'Company', required=True)
    staff = fields.Many2One('ekd.company.staff', 'Staff list')
    department = fields.Many2One('ekd.company.department', 'Department')
    name = fields.Char('Name', size=None, required=True)
    job_function = fields.Many2One('ekd.company.job_function', 'Job function')
    category = fields.Many2One('ekd.company.employee.category', 'Category')
    start_date = fields.Date('Start Date')
    end_date = fields.Date('End Date')
    regular = fields.Boolean('Regular appointment')
    free_rate = fields.Function(fields.Float('Free of bets', digits=(3, 3)),
                                'get_free_rate')
    #schedule = fields.Many2One('ekd.timesheet.schedule', 'Schedule')
    payroll = fields.Selection([('hourly', 'Hourly rates'),
                                ('dayly', 'Daily rate'),
                                ('monthly', 'Monthly salary')],
                               'Accounting payroll')
    rate_payroll = fields.Function(
        fields.Numeric('Rate payroll', digits=(16, 2)), 'get_rate_payroll')
    time_management = fields.Selection([('in_day', 'In Day'),
                                        ('in_hour', 'In Hour')],
                                       'Time management')
    work_rate = fields.Float('Number of bets', digits=(3, 3))
    personal = fields.One2Many('ekd.company.employee.account', 'staff_list',
                               'Employee')
    payroll = fields.One2Many('ekd.company.staff_list.payroll', 'staff_list',
                              'Payroll')
    active = fields.Boolean('Active')
    note = fields.Text('Note')
    state = fields.Selection([
        ('draft', 'Draft'),
        ('active', 'Active'),
        ('archive', 'Archive'),
    ],
                             'State',
                             readonly=True,
                             required=True,
                             select=1)

    #def __init__(self):
    #    super(StaffList, self).__init__()

    def default_company(self):
        return Transaction().context.get('company') or False

    def get_free_rate(self, ids, name):
        res = {}.fromkeys(ids, 0.0)
        for line in self.browse(ids):
            res[line.id] = line.work_rate
            for employee in line.personal:
                res[line.id] -= employee.work_rate

    def get_rate_payroll(self, ids, name):
        res = {}.fromkeys(ids, Decimal('0.0'))
        for line in self.browse(ids):
            for rate_payroll in line.payroll:
                res[line.id] += rate_payroll.rate
Exemple #2
0
class Date(ModelSQL):
    'Date'
    __name__ = 'test.date'
    date = fields.Date(string='Date', help='Test date', required=False)
Exemple #3
0
class Work(sequence_ordered(), tree(separator='\\'), ModelSQL, ModelView):
    'Work Effort'
    __name__ = 'project.work'
    name = fields.Char('Name', required=True, select=True)
    type = fields.Selection([('project', 'Project'), ('task', 'Task')],
                            'Type',
                            required=True,
                            select=True)
    company = fields.Many2One('company.company',
                              'Company',
                              required=True,
                              select=True)
    party = fields.Many2One('party.party',
                            'Party',
                            states={
                                'invisible': Eval('type') != 'project',
                            },
                            depends=['type'])
    party_address = fields.Many2One('party.address',
                                    'Contact Address',
                                    domain=[('party', '=', Eval('party'))],
                                    states={
                                        'invisible': Eval('type') != 'project',
                                    },
                                    depends=['party', 'type'])
    timesheet_works = fields.One2Many('timesheet.work',
                                      'origin',
                                      'Timesheet Works',
                                      readonly=True,
                                      size=1)
    timesheet_available = fields.Function(
        fields.Boolean('Available on timesheets'),
        'get_timesheet_available',
        setter='set_timesheet_available')
    timesheet_start_date = fields.Function(fields.Date(
        'Timesheet Start',
        states={
            'invisible': ~Eval('timesheet_available'),
        },
        depends=['timesheet_available']),
                                           'get_timesheet_date',
                                           setter='set_timesheet_date')
    timesheet_end_date = fields.Function(fields.Date(
        'Timesheet End',
        states={
            'invisible': ~Eval('timesheet_available'),
        },
        depends=['timesheet_available']),
                                         'get_timesheet_date',
                                         setter='set_timesheet_date')
    timesheet_duration = fields.Function(
        fields.TimeDelta(
            'Duration',
            'company_work_time',
            help="Total time spent on this work and the sub-works."),
        'get_total')
    effort_duration = fields.TimeDelta('Effort',
                                       'company_work_time',
                                       help="Estimated Effort for this work.")
    total_effort = fields.Function(
        fields.TimeDelta(
            'Total Effort',
            'company_work_time',
            help="Estimated total effort for this work and the sub-works."),
        'get_total')
    progress = fields.Float('Progress',
                            domain=[
                                'OR',
                                ('progress', '=', None),
                                [
                                    ('progress', '>=', 0),
                                    ('progress', '<=', 1),
                                ],
                            ],
                            help='Estimated progress for this work.')
    total_progress = fields.Function(
        fields.Float(
            'Total Progress',
            digits=(16, 4),
            help='Estimated total progress for this work and the sub-works.',
            states={
                'invisible': Eval('total_progress', None) == None,
            }), 'get_total')
    comment = fields.Text('Comment')
    parent = fields.Many2One('project.work',
                             'Parent',
                             left='left',
                             right='right',
                             ondelete='RESTRICT',
                             domain=[
                                 ('company', '=', Eval('company', -1)),
                             ],
                             depends=['company'])
    left = fields.Integer('Left', required=True, select=True)
    right = fields.Integer('Right', required=True, select=True)
    children = fields.One2Many('project.work',
                               'parent',
                               'Children',
                               domain=[
                                   ('company', '=', Eval('company', -1)),
                               ],
                               depends=['company'])
    state = fields.Selection([
        ('opened', 'Opened'),
        ('done', 'Done'),
    ],
                             'State',
                             required=True,
                             select=True)

    @staticmethod
    def default_type():
        return 'task'

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

    @staticmethod
    def default_state():
        return 'opened'

    @classmethod
    def default_left(cls):
        return 0

    @classmethod
    def default_right(cls):
        return 0

    @classmethod
    def __register__(cls, module_name):
        TimesheetWork = Pool().get('timesheet.work')
        cursor = Transaction().connection.cursor()
        table_project_work = cls.__table_handler__(module_name)
        project = cls.__table__()
        timesheet = TimesheetWork.__table__()

        work_exist = table_project_work.column_exist('work')
        add_parent = (not table_project_work.column_exist('parent')
                      and work_exist)
        add_company = (not table_project_work.column_exist('company')
                       and work_exist)
        add_name = (not table_project_work.column_exist('name') and work_exist)

        super(Work, cls).__register__(module_name)

        # Migration from 3.4: change effort into timedelta effort_duration
        if table_project_work.column_exist('effort'):
            cursor.execute(*project.select(
                project.id, project.effort, where=project.effort != Null))
            for id_, effort in cursor.fetchall():
                duration = datetime.timedelta(hours=effort)
                cursor.execute(
                    *project.update([project.effort_duration], [duration],
                                    where=project.id == id_))
            table_project_work.drop_column('effort')

        # Migration from 3.6: add parent, company, drop required on work,
        # fill name
        if add_parent:
            second_project = cls.__table__()
            query = project.join(
                timesheet, condition=project.work == timesheet.id).join(
                    second_project,
                    condition=timesheet.parent == second_project.work).select(
                        project.id, second_project.id)
            cursor.execute(*query)
            for id_, parent in cursor.fetchall():
                cursor.execute(*project.update([project.parent], [parent],
                                               where=project.id == id_))
            cls._rebuild_tree('parent', None, 0)
        if add_company:
            cursor.execute(*project.join(
                timesheet, condition=project.work == timesheet.id).select(
                    project.id, timesheet.company))
            for id_, company in cursor.fetchall():
                cursor.execute(*project.update([project.company], [company],
                                               where=project.id == id_))
        table_project_work.not_null_action('work', action='remove')
        if add_name:
            cursor.execute(*project.join(
                timesheet, condition=project.work == timesheet.id).select(
                    project.id, timesheet.name))
            for id_, name in cursor.fetchall():
                cursor.execute(*project.update([project.name], [name],
                                               where=project.id == id_))

        # Migration from 4.0: remove work
        if work_exist:
            table_project_work.drop_constraint('work_uniq')
            update = Transaction().connection.cursor()
            cursor.execute(*project.select(
                project.id, project.work, where=project.work != Null))
            for project_id, work_id in cursor:
                update.execute(*timesheet.update(
                    [timesheet.origin, timesheet.name],
                    ['%s,%s' % (cls.__name__, project_id), Null],
                    where=timesheet.id == work_id))
            table_project_work.drop_column('work')

    @classmethod
    def index_set_field(cls, name):
        index = super(Work, cls).index_set_field(name)
        if name in {'timesheet_start_date', 'timesheet_end_date'}:
            index = cls.index_set_field('timesheet_available') + 1
        return index

    @classmethod
    def validate(cls, works):
        super(Work, cls).validate(works)
        for work in works:
            work.check_state()

    def check_state(self):
        if (self.state == 'opened'
                and (self.parent and self.parent.state == 'done')):
            raise WorkValidationError(
                gettext('project.msg_work_invalid_parent_state',
                        child=self.rec_name,
                        parent=self.parent.rec_name))
        if self.state == 'done':
            for child in self.children:
                if child.state == 'opened':
                    raise WorkValidationError(
                        gettext('project.msg_work_invalid_children_state',
                                parent=self.rec_name,
                                child=child.rec_name))

    @property
    def effort_hours(self):
        if not self.effort_duration:
            return 0
        return self.effort_duration.total_seconds() / 60 / 60

    @property
    def total_effort_hours(self):
        if not self.total_effort:
            return 0
        return self.total_effort.total_seconds() / 60 / 60

    @property
    def timesheet_duration_hours(self):
        if not self.timesheet_duration:
            return 0
        return self.timesheet_duration.total_seconds() / 60 / 60

    @classmethod
    def default_timesheet_available(cls):
        return False

    def get_timesheet_available(self, name):
        return bool(self.timesheet_works)

    @classmethod
    def set_timesheet_available(cls, projects, name, value):
        pool = Pool()
        Timesheet = pool.get('timesheet.work')

        to_create = []
        to_delete = []
        for project in projects:
            if not project.timesheet_works and value:
                to_create.append({
                    'origin': str(project),
                    'company': project.company.id,
                })
            elif project.timesheet_works and not value:
                to_delete.extend(project.timesheet_works)

        if to_create:
            Timesheet.create(to_create)
        if to_delete:
            Timesheet.delete(to_delete)

    def get_timesheet_date(self, name):
        if self.timesheet_works:
            func = {
                'timesheet_start_date': min,
                'timesheet_end_date': max,
            }[name]
            return func(getattr(w, name) for w in self.timesheet_works)

    @classmethod
    def set_timesheet_date(cls, projects, name, value):
        pool = Pool()
        Timesheet = pool.get('timesheet.work')
        timesheets = [w for p in projects for w in p.timesheet_works]
        if timesheets:
            Timesheet.write(timesheets, {
                name: value,
            })

    @classmethod
    def sum_tree(cls, works, values, parents):
        result = values.copy()
        works = set((w.id for w in works))
        leafs = works - set(parents.values())
        while leafs:
            for work in leafs:
                works.remove(work)
                parent = parents.get(work)
                if parent in result:
                    result[parent] += result[work]
            next_leafs = set(works)
            for work in works:
                parent = parents.get(work)
                if not parent:
                    continue
                if parent in next_leafs and parent in works:
                    next_leafs.remove(parent)
            leafs = next_leafs
        return result

    @classmethod
    def get_total(cls, works, names):
        cursor = Transaction().connection.cursor()
        table = cls.__table__()

        works = cls.search([
            ('parent', 'child_of', [w.id for w in works]),
        ])
        work_ids = [w.id for w in works]
        parents = {}
        for sub_ids in grouped_slice(work_ids):
            where = reduce_ids(table.id, sub_ids)
            cursor.execute(*table.select(table.id, table.parent, where=where))
            parents.update(cursor.fetchall())

        if 'total_progress' in names and 'total_effort' not in names:
            names = list(names)
            names.append('total_effort')

        result = {}
        for name in names:
            values = getattr(cls, '_get_%s' % name)(works)
            result[name] = cls.sum_tree(works, values, parents)

        if 'total_progress' in names:
            digits = cls.total_progress.digits[1]
            total_progress = result['total_progress']
            total_effort = result['total_effort']
            for work in works:
                if total_effort[work.id]:
                    total_progress[work.id] = round(
                        total_progress[work.id] /
                        (total_effort[work.id].total_seconds() / 60 / 60),
                        digits)
                else:
                    total_effort[work.id] = None
        return result

    @classmethod
    def _get_total_effort(cls, works):
        return {w.id: w.effort_duration or datetime.timedelta() for w in works}

    @classmethod
    def _get_timesheet_duration(cls, works):
        durations = {}
        for work in works:
            value = datetime.timedelta()
            for timesheet_work in work.timesheet_works:
                if timesheet_work.duration:
                    value += timesheet_work.duration
            durations[work.id] = value
        return durations

    @classmethod
    def _get_total_progress(cls, works):
        return {w.id: w.effort_hours * (w.progress or 0) for w in works}

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

    @classmethod
    def delete(cls, project_works):
        TimesheetWork = Pool().get('timesheet.work')

        # Get the timesheet works linked to the project works
        timesheet_works = [
            w for pw in project_works for w in pw.timesheet_works
        ]

        super(Work, cls).delete(project_works)

        if timesheet_works:
            with Transaction().set_context(_check_access=False):
                TimesheetWork.delete(timesheet_works)

    @classmethod
    def search_global(cls, text):
        for record, rec_name, icon in super(Work, cls).search_global(text):
            icon = icon or 'tryton-project'
            yield record, rec_name, icon
Exemple #4
0
class Paciente(Persona):
    'Paciente'
    _name = 'cefiro.paciente'
    _description = __doc__

    sexo = fields.Selection([('M', 'Masculino'), ('F', 'Femenino'),
                             ('I', u'No contesta/Otro')], 'Sexo')
    nacimiento = fields.Date('Fecha de Nacimiento')
    edad = fields.Function(
        fields.Char('Edad'), 'get_edad'
    )  #fields.Integer('Edad') #Habría que relacionarlo con la fecha de nacimiento y hacerlo de sólo lectura
    telefono = fields.Char(
        u'Teléfono fijo'
    )  #Char por si hay telefonos internacionales, u otros símbolos
    celular = fields.Char(
        u'Teléfono celular')  #Char por si hay códigos que no sean números
    #
    lista = fields.Many2One('cefiro.lista', 'Lista de espera')
    #
    convenioSAPPA = fields.Selection([('f', 'Funcionario'), ('c', u'Cónyuge'),
                                      ('p', u'Padre/Madre'), ('h', u'Hijo/a')],
                                     u'Relación para el convenio')
    lugarTrabajo = fields.Char('Lugar de trabajo')
    funcionario = fields.Char(
        u'Número de funcionario')  #Lo pongo char por si hay letras
    #
    atencionMedica = fields.Selection([('msp', u'MSP/ASSE'),
                                       ('mut', 'Mutualista')],
                                      u'Tipo de Atención Médica')
    mutualista = fields.Char('Nombre de la Mutualista')
    #
    fechaIngresoExpediente = fields.Date('Fecha de ingreso del expediente')
    motivo = fields.Text('Motivo de Consulta')
    observaciones = fields.Text('Observaciones')
    #
    horarioPref = fields.Char('Horario de Preferencia')
    psicologo = fields.Many2One('cefiro.psicologo', u'Psicólogo')
    consultas = fields.Many2Many('cefiro.encuentro', 'persona', 'evento',
                                 'Consultas')
    #
    #Formularios entregados para el SAPPA
    form_OQ45T1 = fields.Boolean(u'OQ45-T1')
    form_OQ45T2 = fields.Boolean(u'OQ45-T2')
    form_EncuestaSatisfaccion = fields.Boolean(u'Encuesta de Satisfacción')
    form_EcuestaSatPExtProfesional = fields.Boolean(
        u'Encuesta de Satisfacción - Prof. Externo : Profesional')
    form_EncuestaSatPExtPaciente = fields.Boolean(
        u'Encuesta de Satisfacción - Prof. Externo: Paciente')
    #
    profExternoDerivacion = fields.Boolean('Derivado a profesional externo')
    profExternoNombre = fields.Char('Nombre del profesional externo')
    profExternoFecha = fields.Date(u'Fecha de derivación')

    #Cálculo de la edad
    def get_edad(self, ids, name):
        #usu = User()
        #usu.create([('name','pruebalala'),('login','loolololo')])
        ahora = date.today()
        res = {}
        for pac in self.browse(ids):
            edadtemp = relativedelta(ahora, pac.nacimiento)
            res[pac.id] = str(edadtemp.years) + u' años'
        return res
Exemple #5
0
class AparRepresentationForm(Workflow, ModelSQL, ModelView):
    'APAR Representation Form'

    __name__ = 'apar.representation'

    mail = fields.Boolean('Mail')
    representation_id = fields.Char('Representation Number', readonly=True)
    raised_by = fields.Many2One('company.employee', 'Employee', readonly=True)
    subject = fields.Char(
        'Subject',
        states={
            'readonly': ~Eval('state').in_(['draft']),
        },
        depends=['state'],
    )
    text = fields.Text(
        'Details',
        states={
            'readonly': ~Eval('state').in_(['draft']),
        },
        depends=['state'],
    )
    raised_on = fields.Date('Raised On', readonly=True)
    state = fields.Selection(
        [('draft', 'Draft'), ('reporting_officer', 'Reporting Officer'),
         ('reviewing_officer', 'Reviewing Officer'), ('hod', 'HOD'),
         ('accepting_authority', 'Accepting Authority'),
         ('acr_cell', 'ACR Cell'),
         ('submitted_to_acr_cell', 'Submitted to ACR Cell'),
         ('director', 'Director'), ('closed', 'Closed')],
        'Status',
        readonly=True)
    comments_reporting = fields.Text(
        'Comments by Reporting Officer',
        states={
            'readonly': ~Eval('state').in_(['reporting_officer']),
        },
        depends=['state'],
    )
    comments_reviewing = fields.Text(
        'Comments by Reviewing Officer',
        states={
            'readonly': ~Eval('state').in_(['reviewing_officer']),
        },
        depends=['state'],
    )
    comments_accepting = fields.Text(
        'Comments by Accepting Authority',
        states={
            'readonly': ~Eval('state').in_(['accepting_authority']),
        },
        depends=['state'],
    )
    comments_hod = fields.Text(
        'Comments by HoD',
        states={
            'readonly': ~Eval('state').in_(['hod']),
        },
        depends=['state'],
    )
    comments_director = fields.Text(
        'Comments by Director',
        states={
            'readonly': ~Eval('state').in_(['director']),
        },
        depends=['state'],
    )
    present_score = fields.Integer('Present Score')
    score = fields.Integer('Final Score')
    signatures = fields.One2Many('apar.representation.signatures',
                                 'representation', 'Signatures')

    @classmethod
    def __setup__(cls):
        super().__setup__()
        cls._buttons.update({
            "submit": {
                'invisible': ~Eval('state').in_(['draft']),
                'depends': ['state']
            },
            "forward_to_reporting": {
                'invisible': ~Eval('state').in_(['submitted_to_acr_cell']),
                'depends': ['state']
            },
            "forward_to_reviewing": {
                'invisible': ~Eval('state').in_(['reporting_officer']),
                'depends': ['state']
            },
            "forward_to_accepting": {
                'invisible': ~Eval('state').in_(['reviewing_officer']),
                'depends': ['state']
            },
            "forward_to_HoD": {
                'invisible': ~Eval('state').in_(['accepting_authority']),
                'depends': ['state']
            },
            "forward_to_acr": {
                'invisible': ~Eval('state').in_(['hod']),
                'depends': ['state']
            },
            "forward_to_director": {
                'invisible': ~Eval('state').in_(['acr_cell']),
                'depends': ['state']
            },
            "close": {
                'invisible': ~Eval('state').in_(['director']),
                'depends': ['state']
            }
        })

        cls._transitions |= set((
            ('draft', 'submitted_to_acr_cell'),
            ('submitted_to_acr_cell', 'reporting_officer'),
            ('reporting_officer', 'reviewing_officer'),
            ('reviewing_officer', 'accepting_authority'),
            ('accepting_authority', 'hod'),
            ('hod', 'acr_cell'),
            ('acr_cell', 'director'),
            ('director', 'closed'),
            ('closed', 'closed'),
        ))

    @staticmethod
    def default_state():
        return 'draft'

    def form_signature(self):

        pool = Pool()
        sign_obj = pool.get('apar.representation.signatures')
        User = pool.get('res.user')
        user = User(Transaction().user)

        employee = user.employee
        place = 'Delhi'

        vals = {
            'signed_by_user': user.id,
            'signed_by_employee': employee.id if employee else None,
            'designation': employee.designation.id if employee else None,
            'signed_on': pool.get('ir.date').today(),
            'place': place,
            'representation': self.id
        }

        sign_obj.create([vals])

    @classmethod
    @ModelView.button
    @Workflow.transition('submitted_to_acr_cell')
    def submit(self, records):
        for record in records:
            record.form_signature()

    @classmethod
    @ModelView.button
    @Workflow.transition('reporting_officer')
    def forward_to_reporting(self, records):
        for record in records:
            record.form_signature()

    @classmethod
    @ModelView.button
    @Workflow.transition('reviewing_officer')
    def forward_to_reviewing(self, records):
        for record in records:
            record.form_signature()

    @classmethod
    @ModelView.button
    @Workflow.transition('accepting_authority')
    def forward_to_accepting(self, records):
        for record in records:
            record.form_signature()

    @classmethod
    @ModelView.button
    @Workflow.transition('hod')
    def forward_to_HoD(self, records):
        for record in records:
            record.form_signature()

    @classmethod
    @ModelView.button
    @Workflow.transition('acr_cell')
    def forward_to_acr(self, records):
        for record in records:
            record.form_signature()

    @classmethod
    @ModelView.button
    @Workflow.transition('director')
    def forward_to_director(self, records):
        # TODO: Confirm from the user
        #  if he is sure that he wants to sign the document.
        for record in records:
            record.form_signature()

    @classmethod
    @ModelView.button
    @Workflow.transition('closed')
    def close(self, records):
        for record in records:
            record.form_signature()
Exemple #6
0
class QuotationLine(ModelSQL, ModelView):
    "Purchase Request For Quotation Line"
    __name__ = 'purchase.request.quotation.line'

    supplier = fields.Function(fields.Many2One('party.party', 'Supplier'),
                               'get_supplier')
    supply_date = fields.Date('Supply Date',
                              help="When it should be delivered.")
    product = fields.Function(fields.Many2One('product.product', 'Product'),
                              'get_product',
                              searcher='search_product')
    description = fields.Text('Description',
                              states={'required': ~Eval('product')},
                              depends=['product'])
    quantity = fields.Float('Quantity',
                            digits=(16, Eval('unit_digits', 2)),
                            required=True,
                            depends=['unit_digits'])
    unit = fields.Many2One(
        'product.uom',
        'Unit',
        ondelete='RESTRICT',
        states={
            'required': Bool(Eval('product')),
        },
        domain=[
            If(Bool(Eval('product_uom_category')),
               ('category', '=', Eval('product_uom_category')),
               ('category', '!=', -1)),
        ],
        depends=['product', 'product_uom_category'])
    unit_digits = fields.Function(fields.Integer('Unit Digits'),
                                  'on_change_with_unit_digits')
    product_uom_category = fields.Function(
        fields.Many2One('product.uom.category', 'Product Uom Category'),
        'on_change_with_product_uom_category')
    unit_price = fields.Numeric('Unit Price', digits=price_digits)
    currency = fields.Many2One('currency.currency',
                               'Currency',
                               states={
                                   'required': Bool(Eval('unit_price')),
                               },
                               depends=['unit_price'])
    currency_digits = fields.Function(fields.Integer('Currency Digits'),
                                      'on_change_with_currency_digits')
    request = fields.Many2One(
        'purchase.request',
        'Request',
        ondelete='CASCADE',
        select=True,
        required=True,
        domain=[
            If(
                Eval('quotation_state') == 'draft',
                ('state', 'in', ['draft', 'quotation', 'received']),
                (),
            ),
        ],
        states={'readonly': Eval('quotation_state') != 'draft'},
        depends=['quotation_state'],
        help="The request which this line belongs to.")
    quotation = fields.Many2One('purchase.request.quotation',
                                'Quotation',
                                ondelete='CASCADE',
                                required=True,
                                domain=[
                                    ('supplier', '=', Eval('supplier')),
                                ],
                                depends=['supplier'])
    quotation_state = fields.Function(fields.Selection('get_quotation_state',
                                                       'Quotation State'),
                                      'on_change_with_quotation_state',
                                      searcher='search_quotation_state')

    @staticmethod
    def order_quotation_state(tables):
        pool = Pool()
        Quotation = pool.get('purchase.request.quotation')
        quotation_line, _ = tables[None]
        quotation = Quotation.__table__()
        tables['purchase.request.quotation'] = {
            None: (quotation, quotation_line.quotation == quotation.id),
        }
        return [
            Case((quotation.state == 'received', 0), else_=1), quotation.state
        ]

    def get_supplier(self, name):
        if self.quotation and self.quotation.supplier:
            return self.quotation.supplier.id

    @fields.depends('request', '_parent_request.product',
                    '_parent_request.description', '_parent_request.quantity',
                    '_parent_request.uom', '_parent_request.company.currency',
                    '_parent_request.supply_date')
    def on_change_request(self):
        if self.request:
            self.product = self.request.product
            self.description = self.request.description
            self.quantity = self.request.quantity
            self.unit = self.request.uom
            if self.request.company:
                self.currency = self.request.company.currency
            self.supply_date = self.request.supply_date or datetime.date.max

    @fields.depends('unit')
    def on_change_with_unit_digits(self, name=None):
        if self.unit:
            return self.unit.digits
        return None

    @fields.depends('product')
    def on_change_with_product_uom_category(self, name=None):
        if self.product:
            return self.product.default_uom_category.id

    @fields.depends('currency')
    def on_change_with_currency_digits(self, name=None):
        if self.currency:
            return self.currency.digits
        return None

    @classmethod
    def get_quotation_state(cls):
        pool = Pool()
        Quotation = pool.get('purchase.request.quotation')
        return (Quotation.fields_get(['state'])['state']['selection'])

    @fields.depends('quotation', '_parent_quotation.state')
    def on_change_with_quotation_state(self, name=None):
        pool = Pool()
        Quotation = pool.get('purchase.request.quotation')
        if self.quotation:
            return self.quotation.state
        return Quotation.default_state()

    @classmethod
    def search_quotation_state(cls, name, clause):
        return [('quotation.state', ) + tuple(clause[1:])]

    def get_rec_name(self, name):
        return '%s - %s' % (self.quotation.rec_name, self.supplier.rec_name)

    @classmethod
    def search_rec_name(cls, name, clause):
        names = clause[2].split(' - ', 1)
        res = [('quotation', clause[1], names[0])]
        if len(names) != 1 and names[1]:
            res.append(('supplier', clause[1], names[1]))
        return res

    @classmethod
    def delete(cls, quotationlines):
        pool = Pool()
        Request = pool.get('purchase.request')
        requests = [l.request for l in quotationlines]
        super(QuotationLine, cls).delete(quotationlines)
        Request.update_state(requests)

    def get_product(self, name):
        if self.request and self.request.product:
            return self.request.product.id

    @classmethod
    def search_product(cls, name, clause):
        return [('request.' + clause[0], ) + tuple(clause[1:])]
Exemple #7
0
class Period(Workflow, ModelSQL, ModelView):
    'Stock Period'
    __name__ = 'stock.period'
    date = fields.Date('Date', required=True, states={
            'readonly': Eval('state') == 'closed',
            }, depends=['state'])
    company = fields.Many2One('company.company', 'Company', required=True,
        domain=[
            ('id', If(Eval('context', {}).contains('company'), '=', '!='),
                Eval('context', {}).get('company', -1)),
            ])
    caches = fields.One2Many('stock.period.cache', 'period', 'Caches',
        readonly=True)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('closed', 'Closed'),
        ], 'State', select=True, readonly=True)

    @classmethod
    def __setup__(cls):
        super(Period, cls).__setup__()
        cls._error_messages.update({
                'close_period_future_today': ('You can not close a period '
                    'in the future or today.'),
                'close_period_assigned_move': (
                    'You can not close a period when '
                    'there still are assigned moves.'),
                })
        cls._transitions |= set((
                ('draft', 'closed'),
                ('closed', 'draft'),
                ))
        cls._buttons.update({
                'draft': {
                    'invisible': Eval('state') == 'draft',
                    'depends': ['state'],
                    },
                'close': {
                    'invisible': Eval('state') == 'closed',
                    'depends': ['state'],
                    },
                })

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

    @staticmethod
    def default_state():
        return 'draft'

    @staticmethod
    def groupings():
        return [('product',)]

    @staticmethod
    def get_cache(grouping):
        pool = Pool()
        if all(g == 'product' or g.startswith('product.') for g in grouping):
            return pool.get('stock.period.cache')

    def get_rec_name(self, name):
        return str(self.date)

    @classmethod
    @ModelView.button
    @Workflow.transition('draft')
    def draft(cls, periods):
        for grouping in cls.groupings():
            Cache = cls.get_cache(grouping)
            caches = []
            for sub_periods in grouped_slice(periods):
                caches.append(Cache.search([
                            ('period', 'in',
                                [p.id for p in sub_periods]),
                            ], order=[]))
            Cache.delete(list(chain(*caches)))

    @classmethod
    @ModelView.button
    @Workflow.transition('closed')
    def close(cls, periods):
        pool = Pool()
        Product = pool.get('product.product')
        Location = pool.get('stock.location')
        Move = pool.get('stock.move')
        Date = pool.get('ir.date')
        transaction = Transaction()
        connection = transaction.connection
        database = transaction.database

        # XXX: A move in the period could be inserted before the lock
        # from a different transaction. It will not be taken in the pbl
        # computation but it is quite rare because only past periods are
        # closed.
        database.lock(connection, Move._table)
        if database.has_select_for():
            move = Move.__table__()
            query = move.select(Literal(1), for_=For('UPDATE', nowait=True))
            with connection.cursor() as cursor:
                cursor.execute(*query)

        locations = Location.search([
                ('type', 'not in', ['warehouse', 'view']),
                ], order=[])
        today = Date.today()

        recent_date = max(period.date for period in periods)
        if recent_date >= today:
            cls.raise_user_error('close_period_future_today')
        if Move.search([
                    ('state', '=', 'assigned'),
                    ['OR', [
                            ('effective_date', '=', None),
                            ('planned_date', '<=', recent_date),
                            ],
                        ('effective_date', '<=', recent_date),
                        ]]):
            cls.raise_user_error('close_period_assigned_move')

        for grouping in cls.groupings():
            Cache = cls.get_cache(grouping)
            to_create = []
            for period in periods:
                with Transaction().set_context(
                        stock_date_end=period.date,
                        stock_date_start=None,
                        stock_assign=False,
                        forecast=False,
                        stock_destinations=None,
                        ):
                    pbl = Product.products_by_location(
                        [l.id for l in locations], grouping=grouping)
                for key, quantity in pbl.items():
                    values = {
                        'location': key[0],
                        'period': period.id,
                        'internal_quantity': quantity,
                        }
                    for i, field in enumerate(grouping, 1):
                        values[field] = key[i]
                    to_create.append(values)
            if to_create:
                Cache.create(to_create)
Exemple #8
0
class InternalApply(ModelView):
    'Internal Apply'

    __name__ = 'hrp_internal_delivery.internal_apply'
    _rec_name = 'number'

    number = fields.Char('Number', size=None, select=True)
    type = fields.Selection(
        [
            ('00', u'常规药请领单'),
            ('06', u'直送药请领单'),
            ('2017', u' '),
        ],
        'Type', select=True, required=True, states={
            'readonly': Bool(Eval('moves'))})

    starts = fields.Selection([
        ('00', u'西药'),
        ('01', u'中成药'),
        ('02', u'中草药'),
        ('03', u'颗粒中'),
        ('04', u'原料药'),
        ('05', u'敷药'),
        ('07', u'同位素'),
    ], 'Starts', sort=False, select=True, states={
        'invisible': Equal(Eval('type'), '2017')
    }, )

    medicine = fields.Selection([
        ('00', u''),
        ('2', u'临采'),
        ('02', u'精一'),
        ('03', u'麻醉'),
    ], 'medicine', select=True,
        # states={
        #     'invisible':~Equal(Eval('starts'),'00')| Equal(Eval('type'),'06')
        #     },
    )
    special = fields.Selection([
        ('00', u'直送'),
    ], 'special', select=True
        , states={
            'readonly': Equal(Eval('type'), '06'),
            'invisible': ~Equal(Eval('type'), '06'),
        },
        depends=['type'],
    )
    planned_date = fields.Date('Planned Date', readonly=True)

    moves = fields.One2Many('hrp_internal_delivery.test_apply', 'parents', 'Moves')
    from_location = fields.Many2One('stock.location', 'from_location', readonly=True)
    to_location = fields.Many2One('stock.location', 'to_location', readonly=True)
    warehouse_to_location = fields.Many2One('stock.location', 'warehouse_to_location', select=True)

    # change_state = fields.Boolean('change_state',select=True)#更改请领状态

    @staticmethod
    def default_type():
        return '2017'

    @staticmethod
    def default_from_location():
        Config = Pool().get('purchase.configuration')
        config = Config(1)
        return config.warehouse.storage_location.id  # 默认为中心药房

    @staticmethod
    def default_to_location():
        UserId = Pool().get('hrp_internal_delivery.test_straight')
        return UserId.get_user_id()

    @staticmethod
    def default_planned_date():
        Date = Pool().get('ir.date')
        today = str(Date.today())
        return today

    @fields.depends('type')
    def on_change_type(self):
        if self.type == '06':
            self.special = '00'
        else:
            pass

    @fields.depends('starts', 'moves', 'special', 'to_location', 'medicine')
    def on_change_starts(self):
        Product = Pool().get('product.product')
        Date = Pool().get('ir.date')
        MOVE = Pool().get('hrp_new_product.new_product')
        list = []
        if self.special == None:
            locals = self.to_location
            if self.medicine == None:
                mmm = MOVE.search([
                    ('interim', 'in', ['1', '00']),
                    ('drug_type', '=', self.starts),
                    ('is_direct_sending', '=', False),
                    ('to_location', '=', locals),
                ])
            else:
                if self.medicine == '2':
                    mmm = MOVE.search([
                        ('drug_type', '=', self.starts),
                        ('is_direct_sending', '=', False),
                        ('to_location', '=', locals),
                        ('interim', 'in', ['2', '01']),
                    ])
                else:
                    mmm = MOVE.search([
                        ('drug_type', '=', self.starts),
                        ('is_direct_sending', '=', False),
                        ('to_location', '=', locals),
                        ('interim', '=', self.medicine),
                    ])
            for i in mmm:
                dict = {}
                dict['code'] = i.code
                dict['product'] = i.product.id
                dict['product_name'] = i.product.name
                dict['drug_specifications'] = i.drug_specifications
                dict['company'] = i.uom
                dict['a_charge'] = i.a_charge
                with Transaction().set_context(stock_date_end=Date.today()):
                    quantities = Product.products_by_location([locals], [i.product.id], with_childs=True)
                if quantities.values():
                    stock_level = [v for v in quantities.values()][0]
                else:
                    stock_level = 0.0
                dict['stock_level'] = str(stock_level)
                outpatient_ = str(i.outpatient_7days)
                dict['outpatient_7days'] = outpatient_.ljust(5, ' ')
                stock_levels = float(i.outpatient_7days) - stock_level
                if stock_levels <= 0:
                    dict['odd_numbers'] = '0.0'
                else:
                    dict['odd_numbers'] = str(stock_levels)
                dict['is_direct_sending'] = i.is_direct_sending
                dict['lot'] = i.lot
                dict['is_collar'] = False
                dict['party'] = i.party
                dict['unit_price'] = i.unit_price
                list.append(dict)
            self.moves = list
        if self.special == '00':
            locals = self.to_location
            mmm = MOVE.search([
                ('drug_type', '=', self.starts),
                ('is_direct_sending', '=', True),
                ('to_location', '=', locals),
            ])
            for i in mmm:
                dict = {}
                dict['code'] = i.code
                dict['product'] = i.product.id
                dict['product_name'] = i.product.name
                dict['drug_specifications'] = i.drug_specifications
                dict['company'] = i.uom
                dict['odd_numbers'] = i.odd_numbers
                dict['a_charge'] = i.a_charge
                with Transaction().set_context(stock_date_end=Date.today()):
                    quantities = Product.products_by_location([locals], [i.product.id], with_childs=True)
                if quantities.values():
                    stock_level = [v for v in quantities.values()][0]
                else:
                    stock_level = 0.0
                dict['stock_level'] = str(stock_level)
                if i.outpatient_7days == 0:
                    dict['outpatient_7days'] = '0.0'
                else:
                    dict['outpatient_7days'] = str(i.outpatient_7days)
                stock_levels = i.outpatient_7days - stock_level
                if stock_levels <= 0:
                    dict['odd_numbers'] = '0.0'
                else:
                    dict['odd_numbers'] = stock_levels
                dict['is_direct_sending'] = i.is_direct_sending
                dict['lot'] = i.lot
                dict['is_collar'] = i.is_collar
                dict['party'] = i.party
                dict['unit_price'] = i.unit_price
                list.append(dict)
            self.moves = list

    # 西药特殊,精神一,麻醉
    @fields.depends('medicine', 'moves', 'starts', 'special', 'to_location')
    def on_change_medicine(self):
        Product = Pool().get('product.product')
        Date = Pool().get('ir.date')
        MOVE = Pool().get('hrp_new_product.new_product')
        list = []
        locals = self.to_location
        if self.special == None:
            search_move = MOVE.search([
                ('is_direct_sending', '=', False),
                ('interim', '=', self.medicine),
                ('drug_type', '=', self.starts),
                ('to_location', '=', locals),
            ])
            for i in search_move:
                dict = {}
                dict['code'] = i.code
                dict['product'] = i.product.id
                dict['product_name'] = i.product.name
                dict['drug_specifications'] = i.drug_specifications
                dict['company'] = i.uom
                dict['a_charge'] = i.a_charge
                with Transaction().set_context(stock_date_end=Date.today()):
                    quantities = Product.products_by_location([locals], [i.product.id], with_childs=True)
                if quantities.values():
                    stock_level = [v for v in quantities.values()][0]
                else:
                    stock_level = 0.0
                dict['stock_level'] = str(stock_level)
                Ljust = str(i.outpatient_7days)
                dict['outpatient_7days'] = Ljust.ljust(5, ' ')
                stock_levels = float(i.outpatient_7days) - stock_level
                if stock_levels <= 0:
                    dict['odd_numbers'] = '0.0'
                else:
                    dict['odd_numbers'] = str(stock_levels)
                dict['is_direct_sending'] = i.is_direct_sending
                dict['lot'] = i.lot
                dict['is_collar'] = i.is_collar
                dict['party'] = i.party
                dict['unit_price'] = i.unit_price
                list.append(dict)
        if self.starts == None:
            pass
        if self.special == '00':
            locals = self.to_location
            search_move = MOVE.search([
                ('drug_type', '=', self.starts),
                ('interim', '=', self.medicine),
                ('is_direct_sending', '=', True),
                ('to_location', '=', locals),
            ])
            for i in search_move:
                dict = {}
                dict['code'] = i.code
                dict['product'] = i.product.id
                dict['product_name'] = i.product.name
                dict['drug_specifications'] = i.drug_specifications
                dict['company'] = i.uom
                dict['odd_numbers'] = i.odd_numbers
                dict['a_charge'] = i.a_charge
                with Transaction().set_context(stock_date_end=Date.today()):
                    quantities = Product.products_by_location([locals], [i.product.id], with_childs=True)
                if quantities.values():
                    stock_level = [v for v in quantities.values()][0]
                else:
                    stock_level = 0.0
                dict['stock_level'] = str(stock_level)
                dict['outpatient_7days'] = i.outpatient_7days
                stock_levels = i.outpatient_7days - stock_level
                if stock_levels <= 0:
                    dict['odd_numbers'] = '0.0'
                else:
                    dict['odd_numbers'] = stock_levels
                dict['is_direct_sending'] = i.is_direct_sending
                dict['lot'] = i.lot
                dict['is_collar'] = i.is_collar
                dict['party'] = i.party
                dict['unit_price'] = i.unit_price
                list.append(dict)
        self.moves = list

    @staticmethod
    def default_actives():
        return '00'

    @staticmethod
    def default_company():
        return Transaction().context.get('company')
Exemple #9
0
class Formulario(ModelSQL, ModelView):
    'Formulario'
    _name = 'cefiro.formulario'
    _description = __doc__
    _rec_name = 'fecha'
    #	name = fields.Char('Nombre del paciente')

    #Paciente Asociado y datos autocompletados. Implementar esto. Tema de las edades (el paciente tiene una edad actual, y va yendo a consultas con distintas edades).
    paciente = fields.Many2One('cefiro.paciente', 'Paciente')

    #Tipo de consulta
    fecha = fields.Date('Fecha de consulta inicial', required=True)
    tipoConsulta = fields.Selection([('esp', u'Consulta espontánea'),
                                     ('tra', u'Traído'),
                                     ('ori', u'Consulta por orientación'),
                                     ('der', 'Derivado')], 'Tipo de Consulta')
    derivador = fields.Selection([('med', u'Especialidad Médica'),
                                  ('psiq', 'Psiquiatra'),
                                  ('edu', u'Institución Educativa'),
                                  ('otra', 'Otra')], 'Derivado por')
    derivEspec = fields.Char('Especifique')

    #Motivo de consulta
    motivoPaciente1 = fields.Char(u'Motivo según el paciente (1)')
    motivoPaciente1Cod = fields.Char(u'Código')
    motivoPaciente2 = fields.Char(u'Motivo según el paciente (2)')
    motivoPaciente2Cod = fields.Char(u'Código')
    motivoPaciente3 = fields.Char(u'Motivo según el paciente (3)')
    motivoPaciente3Cod = fields.Char(u'Código')

    motivoAcompa1 = fields.Char(u'Motivo según el Acompañante (1)')
    motivoAcompa1Cod = fields.Char(u'Código')
    motivoAcompa2 = fields.Char(u'Motivo según el Acompañante (2)')
    motivoAcompa2Cod = fields.Char(u'Código')
    motivoAcompa3 = fields.Char(u'Motivo según el Acompañante (3)')
    motivoAcompa3Cod = fields.Char(u'Código')

    motivoPsico1 = fields.Char(u'Motivo según el Psicólogo (1)')
    motivoPsico1Cod = fields.Char(u'Código')
    motivoPsico2 = fields.Char(u'Motivo según el Psicólogo (2)')
    motivoPsico2Cod = fields.Char(u'Código')
    motivoPsico3 = fields.Char(u'Motivo según el Psicólogo (3)')
    motivoPsico3Cod = fields.Char(u'Código')

    motivoComplementaria = fields.Text(u'Descripción Comlpementaria')

    #Datos personales extra
    lugarNacimiento = fields.Char('Lugar de Nacimiento')

    #Vivienda y Trabajo
    tipoVivienda = fields.Selection([('casa', 'la casa'),
                                     ('calle', 'la calle'),
                                     ('inst', u'institución protectora'),
                                     ('car', 'privado de libertad')],
                                    'Vive en')
    #convive = fields.One2Many() Hay que hacer uno para familiares posibles. Por ahora va un Selection.
    convive = fields.Selection([('solo', 'Vive solo'), ('madre', 'Madre'),
                                ('padre', 'Padre'), ('madra', 'Madrastra'),
                                ('padra', 'Padrastro'), ('her', 'Hermano'),
                                ('pare', 'Pareja'), ('hijo', 'Hijo'),
                                ('otros', 'Otros')], u'Con quién convive')
    situacionCony = fields.Selection(
        [('sol', u'Soltero/a'),
         ('casado', u'Casado/a (incluye separado/a sin divorcio)'),
         ('divor', u'Divorciado/a'), ('viudo', u'Viudo/a'),
         ('ulibre', u'Unión libre'),
         ('slibre', u'Separado de unión libre')], 'Estado Conyugal')

    vivHabitaTot = fields.Integer('Habitaciones totales')
    vivHabitaDor = fields.Integer('Dormitorios')
    vivBanos = fields.Integer(u'Cantidad de Baños')
    vivBanoComp = fields.Boolean(u'Baño compartido')
    vivBanoTipo = fields.Selection(
        [('red', 'Red general'), ('fosa', u'Fosa séptica o pozo negro'),
         ('otro', u'Otro (hueco en suelo, superficie)')],
        u'Tipo de instalación sanitaria')

    trabSituacion = fields.Selection([('trab', 'Trabaja'),
                                      ('bus', 'Busca por primera vez'),
                                      ('no', 'No trabaja'),
                                      ('pas', u'Pasantía'),
                                      ('pens', 'Pensionista'),
                                      ('jub', 'Jubilado')],
                                     u'Situación Laboral')
    trabMulti = fields.Boolean('Multiempleo')
    trabHoras = fields.Integer('Horas Totales')
    trabHorasPrin = fields.Integer('Horas Trabajo Principal')
    trabInicio = fields.Integer('Edad de inicio de trabajo')
    trabInfantil = fields.Boolean('Trabajo infantil')
    trabJuvenil = fields.Boolean('Trabajo juvenil')
    trabLegal = fields.Boolean('Trabajo legalizado')
    trabInsalubre = fields.Boolean('Trabajo insalubre')
    trabTipoRel = fields.Selection([('pub', u'Empleado Público'),
                                    ('priv', 'Empleado Privado'),
                                    ('indep', 'Empleado Independiente'),
                                    ('otro', 'Otro')], u'Tipo de Relación')
    trabObs = fields.Text('Observaciones')

    trabPadre = fields.Selection([('trab', 'Trabaja'),
                                  ('bus', 'Busca por primera vez'),
                                  ('no', 'No trabaja'), ('pas', u'Pasantía'),
                                  ('pens', 'Pensionista'),
                                  ('jub', 'Jubilado')],
                                 u'Situación Laboral del Padre')
    trabMadre = fields.Selection([('trab', 'Trabaja'),
                                  ('bus', 'Busca por primera vez'),
                                  ('no', 'No trabaja'), ('pas', u'Pasantía'),
                                  ('pens', 'Pensionista'),
                                  ('jub', 'Jubilado')],
                                 u'Situación Laboral de la Madre')
    trabPareja = fields.Selection([('trab', 'Trabaja'),
                                   ('bus', 'Busca por primera vez'),
                                   ('no', 'No trabaja'), ('pas', u'Pasantía'),
                                   ('pens', 'Pensionista'),
                                   ('jub', 'Jubilado')],
                                  u'Situación Laboral de la Pareja')

    #Educación
    eduFormalNivel = fields.Selection([('no', 'No escolarizado'),
                                       ('priInc', 'Primaria Incompleta'),
                                       ('pri', 'Primaria Completa'),
                                       ('secInc', 'Secundaria Incompleta'),
                                       ('sec', 'Secundaria Completa'),
                                       ('tercInc', 'Terciaria Incompleta'),
                                       ('terc', 'Terciaria Completa'),
                                       ('uniInc', 'Universitaria Incompleta'),
                                       ('uni', 'Universitaria Completa')],
                                      u'Nivel de Educación Formal')
    eduFormalNivelMax = fields.Integer(
        u'Máximo año aprobado (en caso de no haber completado lo último que estudió)'
    )

    eduCentrosPrimaria = fields.Char(u'Centros en los que estudió')
    eduPubliPrimaria = fields.Selection([('publi', u'Pública'),
                                         ('priv', 'Privada')],
                                        u'Tipo de institución')
    eduDifPrimaria = fields.Boolean(u'Presentó dificultades de aprendizaje')
    eduDifTipoPrimaria = fields.Char(u'Tipo de dificultad que presentó')
    eduRepePrimaria = fields.Integer(
        u'Cantidad de años repetidos (si no hay dejar vacío)')
    eduRepeCausaPrimaria = fields.Char(u'Causa de la repetición de años')
    eduDeserPrimaria = fields.Boolean(u'Deserción o Exclusión')

    eduCentrosSecundaria = fields.Char(u'Centros en los que estudió')
    eduPubliSecundaria = fields.Selection([('publi', u'Pública'),
                                           ('priv', 'Privada')],
                                          u'Tipo de institución')
    eduDifSecundaria = fields.Boolean(u'Presentó dificultades de aprendizaje')
    eduDifTipoSecundaria = fields.Char(u'Tipo de dificultad que presentó')
    eduRepeSecundaria = fields.Integer(
        u'Cantidad de años repetidos (si no hay dejar vacío)')
    eduRepeCausaSecundaria = fields.Char(u'Causa de la repetición de años')
    eduDeserSecundaria = fields.Boolean(u'Deserción o Exclusión')

    eduCentrosTerciaria = fields.Char(u'Centros en los que estudió')
    eduPubliTerciaria = fields.Selection([('publi', u'Pública'),
                                          ('priv', 'Privada')],
                                         u'Tipo de institución')

    eduCentrosUniv = fields.Char(u'Centros en los que estudió')
    eduPubliUniv = fields.Selection([('publi', u'Pública'),
                                     ('priv', 'Privada')],
                                    u'Tipo de institución')

    eduNoForCurso1 = fields.Char('Curso')
    eduNoForCentro1 = fields.Char('Centro')
    eduNoForPubli1 = fields.Selection([('publi', u'Pública'),
                                       ('priv', 'Privada')],
                                      u'Tipo de institución')
    eduNoForAsis1 = fields.Selection([('actual', 'Asiste'),
                                      ('pasado', u'Asistió')], 'Momento')

    eduNoForCurso2 = fields.Char('Curso')
    eduNoForCentro2 = fields.Char('Centro')
    eduNoForPubli2 = fields.Selection([('publi', u'Pública'),
                                       ('priv', 'Privada')],
                                      u'Tipo de institución')
    eduNoForAsis2 = fields.Selection([('actual', 'Asiste'),
                                      ('pasado', u'Asistió')], 'Momento')

    eduNoForCurso3 = fields.Char('Curso')
    eduNoForCentro3 = fields.Char('Centro')
    eduNoForPubli3 = fields.Selection([('publi', u'Pública'),
                                       ('priv', 'Privada')],
                                      u'Tipo de institución')
    eduNoForAsis3 = fields.Selection([('actual', 'Asiste'),
                                      ('pasado', u'Asistió')], 'Momento')

    eduPadre = fields.Selection([('no', 'No escolarizado'),
                                 ('priInc', 'Primaria Incompleta'),
                                 ('pri', 'Primaria Completa'),
                                 ('secInc', 'Secundaria Incompleta'),
                                 ('sec', 'Secundaria Completa'),
                                 ('tercInc', 'Terciaria Incompleta'),
                                 ('terc', 'Terciaria Completa'),
                                 ('uniInc', 'Universitaria Incompleta'),
                                 ('uni', 'Universitaria Completa')],
                                u'Nivel de Educación Formal del Padre')

    eduMadre = fields.Selection([('no', 'No escolarizado'),
                                 ('priInc', 'Primaria Incompleta'),
                                 ('pri', 'Primaria Completa'),
                                 ('secInc', 'Secundaria Incompleta'),
                                 ('sec', 'Secundaria Completa'),
                                 ('tercInc', 'Terciaria Incompleta'),
                                 ('terc', 'Terciaria Completa'),
                                 ('uniInc', 'Universitaria Incompleta'),
                                 ('uni', 'Universitaria Completa')],
                                u'Nivel de Educación Formal de la Madre')

    eduPareja = fields.Selection([('no', 'No escolarizado'),
                                  ('priInc', 'Primaria Incompleta'),
                                  ('pri', 'Primaria Completa'),
                                  ('secInc', 'Secundaria Incompleta'),
                                  ('sec', 'Secundaria Completa'),
                                  ('tercInc', 'Terciaria Incompleta'),
                                  ('terc', 'Terciaria Completa'),
                                  ('uniInc', 'Universitaria Incompleta'),
                                  ('uni', 'Universitaria Completa')],
                                 u'Nivel de Educación Formal de la Pareja')

    #Antecedentes
    antPedagogica = fields.Selection([('conc', u'Concluida'),
                                      ('aba', 'Abandonada'),
                                      ('cur', 'En Curso')],
                                     u'Intervención Pedagógica')
    antPedagogicaPocas = fields.Boolean('Menos de 3 consultas')
    antPedagogicaMeses = fields.Integer(u'Duración en meses')
    antPedagogicaMedicacion = fields.Boolean(u'Medicación')
    antPedagogicaMedTipo = fields.Selection([('ansiolitico', u'Ansiolíticos'),
                                             ('antidepre', 'Antidepresivos'),
                                             ('neurolep', u'Neurolépticos'),
                                             ('otro', 'Otros')],
                                            u'Tipo de Medicación')
    antPedagogicaObs = fields.Char(u'Motivo y Obs.')

    antMedica = fields.Selection([('conc', u'Concluida'),
                                  ('aba', 'Abandonada'), ('cur', 'En Curso')],
                                 u'Intervención Médica')
    antMedicaPocas = fields.Boolean('Menos de 3 consultas')
    antMedicaMeses = fields.Integer(u'Duración en meses')
    antMedicaMedicacion = fields.Boolean(u'Medicación')
    antMedicaMedTipo = fields.Selection([('ansiolitico', u'Ansiolíticos'),
                                         ('antidepre', 'Antidepresivos'),
                                         ('neurolep', u'Neurolépticos'),
                                         ('otro', 'Otros')],
                                        u'Tipo de Medicación')
    antMedicaObs = fields.Char(u'Motivo y Obs.')

    antPsicologica = fields.Selection([('conc', u'Concluida'),
                                       ('aba', 'Abandonada'),
                                       ('cur', 'En Curso')],
                                      u'Intervención Psicológica')
    antPsicologicaPocas = fields.Boolean('Menos de 3 consultas')
    antPsicologicaMeses = fields.Integer(u'Duración en meses')
    antPsicologicaMedicacion = fields.Boolean(u'Medicación')
    antPsicologicaMedTipo = fields.Selection([('ansiolitico', u'Ansiolíticos'),
                                              ('antidepre', 'Antidepresivos'),
                                              ('neurolep', u'Neurolépticos'),
                                              ('otro', 'Otros')],
                                             u'Tipo de Medicación')
    antPsicologicaObs = fields.Char(u'Motivo y Obs.')

    antPsiquiatrica = fields.Selection([('conc', u'Concluida'),
                                        ('aba', 'Abandonada'),
                                        ('cur', 'En Curso')],
                                       u'Intervención Psiquiátrica')
    antPsiquiatricaPocas = fields.Boolean('Menos de 3 consultas')
    antPsiquiatricaMeses = fields.Integer(u'Duración en meses')
    antPsiquiatricaMedicacion = fields.Boolean(u'Medicación')
    antPsiquiatricaMedTipo = fields.Selection(
        [('ansiolitico', u'Ansiolíticos'), ('antidepre', 'Antidepresivos'),
         ('neurolep', u'Neurolépticos'),
         ('otro', 'Otros')], u'Tipo de Medicación')
    antPsiquiatricaObs = fields.Char(u'Motivo y Obs.')

    antPsiqInter = fields.Selection([('conc', u'Concluida'),
                                     ('aba', 'Abandonada'),
                                     ('cur', 'En Curso')],
                                    u'Internación Psiquiátrica')
    antPsiqInterPocas = fields.Boolean('Menos de 3 consultas')
    antPsiqInterMeses = fields.Integer(u'Duración en meses')
    antPsiqInterMedicacion = fields.Boolean(u'Medicación')
    antPsiqInterMedTipo = fields.Selection([('ansiolitico', u'Ansiolíticos'),
                                            ('antidepre', 'Antidepresivos'),
                                            ('neurolep', u'Neurolépticos'),
                                            ('otro', 'Otros')],
                                           u'Tipo de Medicación')
    antPsiqInterObs = fields.Char(u'Motivo y Obs.')

    antIntOtra = fields.Selection([('conc', u'Concluida'),
                                   ('aba', 'Abandonada'), ('cur', 'En Curso')],
                                  u'Otra')
    antIntOtraPocas = fields.Boolean('Menos de 3 consultas')
    antIntOtraMeses = fields.Integer(u'Duración en meses')
    antIntOtraMedicacion = fields.Boolean(u'Medicación')
    antIntOtraMedTipo = fields.Selection([('ansiolitico', u'Ansiolíticos'),
                                          ('antidepre', 'Antidepresivos'),
                                          ('neurolep', u'Neurolépticos'),
                                          ('otro', 'Otros')],
                                         u'Tipo de Medicación')
    antIntOtraObs = fields.Char(u'Motivo y Obs.')

    antDisca = fields.Boolean(u'Tiene algún tipo de discapacidad')
    antDiscaTipo = fields.Char('Tipo')
    antAyudaTec = fields.Boolean(u'Utiliza algún tipo de ayuda técnica')
    antAyudaTecLentes = fields.Boolean(u'Lentes')
    antAyudaTecBaston = fields.Boolean(u'Bastón')
    antAyudaTecAudifono = fields.Boolean(u'Audífono')
    antAyudaTecOtro = fields.Boolean(u'Otro')
    antAyudaTecObs = fields.Char('Obs.')

    antPrestacion = fields.Boolean(
        u'Beneficiario de prestación por discapacidad')
    antPrestPension = fields.Boolean(u'Pensión no contributiva')
    antPrestJubil = fields.Boolean(u'Jubilación por incapacidad')
    antPrestAsigDoble = fields.Boolean(u'Asignación doble')
    antPrestAyuda = fields.Boolean(u'Ayuda especial')
    antPrestEquidad = fields.Boolean(u'Plan de equidad')

    antCeguera = fields.Boolean(u'Ceguera y/o dism. de visión')
    antSordera = fields.Boolean(u'Sordera / hipoacusia')
    antMotriz = fields.Boolean(u'Ceguera y/o dism. de visión')
    antDependencia = fields.Boolean(u'Dependencia de otra persona')

    antAsma = fields.Boolean(u'Asma')
    antEpilepsia = fields.Boolean(u'Epilepsia')
    antDiabetes = fields.Boolean(u'Diabetes')
    antTiroides = fields.Boolean(u'Enf. Tiroidea')
    antCancer = fields.Boolean(u'Cáncer')
    antVIH = fields.Boolean(u'VIH/SIDA')
    antOsteo = fields.Boolean(u'Pat. Osteoarticular')
    antCardio = fields.Boolean(u'Enf. Cardiovascular')

    antAccidente1Edad = fields.Integer('Edad')
    antAccidente1Tipo = fields.Char('Tipo')
    antAccidente2Edad = fields.Integer('Edad')
    antAccidente2Tipo = fields.Char('Tipo')
    antCirugia1Edad = fields.Integer('Edad')
    antCirugia1Tipo = fields.Char('Tipo')
    antCirugia2Edad = fields.Integer('Edad')
    antCirugia2Tipo = fields.Char('Tipo')

    antAutoeliminCant = fields.Integer(
        u'Cantidad de intentos de autoeliminación')
    antAutoelim1Edad = fields.Integer('Edad')
    antAutoelim1Tipo = fields.Char('Tipo')
    antAutoelim2Edad = fields.Integer('Edad')
    antAutoelim2Tipo = fields.Char('Tipo')

    #Violencia y Uso de Sustancias
    tvioDanoPsico = u'¿Su pareja o alguien importante para usted le ha causado daño emocional o psicológico en forma repetida?\n (Por ej.: por medio de alguna de las siguientes situaciones: insultos, maltrato a sus hijos, hacerlo/a\n sentir avergonzado/a o humillado/a desprecio por las tareas que usted realiza, destrucción de objetos\n de amigos o parientes, otras.)'
    vioDanoPsico = fields.Selection([('si', u'Sí'), ('no', 'No'),
                                     ('nc', 'No desea contestar')],
                                    tvioDanoPsico)
    vioDanoPsicoQuien = fields.Char(u'¿Quién/es lo hizo/cieron?')
    vioDanoPsicoNino = fields.Boolean(u'Niño/a')
    vioDanoPsicoAdoles = fields.Boolean(u'Adolescente')
    vioDanoPsicoJoven = fields.Boolean(u'Joven')
    vioDanoPsicoAdulto = fields.Boolean(u'Adulto/a')
    vioDanoPsicoMayor = fields.Boolean(u'Mayor de 65')
    vioDanoPsicoEmbarazo = fields.Boolean(u'Embarazo/postparto')
    vioDanoPsicoActual = fields.Selection([('si', u'Sí'), ('no', 'No'),
                                           ('nc', 'No desea contestar')],
                                          u'¿Sucede actualmente?')

    tvioDanoFisico = u'¿Su pareja o alguien importante para usted le ha causado daño físico grave al menos una vez, o le ha hecho agresiones menores en forma reiterada?\n (Por ej.: empujones, golpe de puños, quemaduras, zamarreos, mordeduras, ahorcamiento, pellizcos, palizas, golpes con objetos,\n tirón de pelo, patadas, daño con armas, cachetadas, otra forma.)'
    vioDanoFisico = fields.Selection([('si', u'Sí'), ('no', 'No'),
                                      ('nc', 'No desea contestar')],
                                     tvioDanoFisico)
    vioDanoFisicoQuien = fields.Char(u'¿Quién/es lo hizo/cieron?')
    vioDanoFisicoNino = fields.Boolean(u'Niño/a')
    vioDanoFisicoAdoles = fields.Boolean(u'Adolescente')
    vioDanoFisicoJoven = fields.Boolean(u'Joven')
    vioDanoFisicoAdulto = fields.Boolean(u'Adulto/a')
    vioDanoFisicoMayor = fields.Boolean(u'Mayor de 65')
    vioDanoFisicoEmbarazo = fields.Boolean(u'Embarazo/postparto')
    vioDanoFisicoActual = fields.Selection([('si', u'Sí'), ('no', 'No'),
                                            ('nc', 'No desea contestar')],
                                           u'¿Sucede actualmente?')

    tvioDanoSexual = u'¿Cuando usted era niño/a recuerda haber sido tocado/a de manera inapropiada por alguien o haber tenido relaciones o contacto sexual?'
    vioDanoSexual = fields.Selection([('si', u'Sí'), ('no', 'No'),
                                      ('nc', 'No desea contestar')],
                                     tvioDanoSexual)
    vioDanoSexualQuien = fields.Char(u'¿Quién/es lo hizo/cieron?')

    tvioViola = u'¿Alguna vez en su vida ha sido obligado/a a tener relaciones o contacto sexual?\n (Por ej.: empleo de la fuerza física, de intimidación o amenaza para mantener relaciones sexuales no deseadas.)'
    vioViola = fields.Selection([('si', u'Sí'), ('no', 'No'),
                                 ('nc', 'No desea contestar')], tvioViola)
    vioViolaQuien = fields.Char(u'¿Quién/es lo hizo/cieron?')
    vioViolaNino = fields.Boolean(u'Niño/a')
    vioViolaAdoles = fields.Boolean(u'Adolescente')
    vioViolaJoven = fields.Boolean(u'Joven')
    vioViolaAdulto = fields.Boolean(u'Adulto/a')
    vioViolaMayor = fields.Boolean(u'Mayor de 65')
    vioViolaEmbarazo = fields.Boolean(u'Embarazo/postparto')
    vioViolaActual = fields.Selection([('si', u'Sí'), ('no', 'No'),
                                       ('nc', 'No desea contestar')],
                                      u'¿Sucede actualmente?')

    vioPensamiento = fields.Selection([
        ('si', u'Sí'), ('no', 'No'), ('nc', 'No desea contestar')
    ], u'Hoy, en su casa, ¿piensa usted que podría sufrir alguna de las situaciones antes nombradas?'
                                      )

    tsustAlcohol = u'Durante los últimos 30 días, ¿con qué frecuencia usted bebió al menos 4 medidas de cualquier\n clase de bebida con alcohol en un mismo día?'
    sustAlcohol = fields.Selection(
        [('nunca', 'Nunca'), ('unames', 'Una vez al mes'),
         ('dosmes', '2 o 3 veces al mes'),
         ('unasemana', 'Una vez a la semana'),
         ('dossemana', u'2 dóas a la semana o más')], tsustAlcohol)
    tsustCigarro = u'Durante los últimos 30 días, ¿con qué frecuencia usted fumó cigarrillos, tabaco o pipa?'
    sustCigarro = fields.Selection(
        [('nunca', 'Nunca'), ('unames', 'Una vez al mes'),
         ('dosmes', '2 o 3 veces al mes'),
         ('unasemana', 'Una vez a la semana'),
         ('dossemana', u'2 dóas a la semana o más')], tsustCigarro)
    tsustMedicamento = u'Durante los últimos 30 días, ¿con qué frecuencia usted usó algunos de los siguientes medicamentos \n POR SU CUENTA (esto es sin una receta de su médico o en cantidades mayores a las recetadas)?\n Medicamentos para el dolor como tramadol o morfina, estimulantes como ritalina, tranquilizantes como Lexotán.'
    sustMedicamento = fields.Selection(
        [('nunca', 'Nunca'), ('unames', 'Una vez al mes'),
         ('dosmes', '2 o 3 veces al mes'),
         ('unasemana', 'Una vez a la semana'),
         ('dossemana', u'2 dóas a la semana o más')], tsustMedicamento)
    tsustDroga = u'Durante los últimos 30 días, ¿con qué frecuencia usted usó algunas de las siguientes sustancias:\n Marihuana, Cocaína, Pasta Base, Crack, Estimulantes como éxtasis, Halucinógenos como hongos o LSD,\n Heroína, Inhalantes como pegamento?'
    sustDroga = fields.Selection([('nunca', 'Nunca'),
                                  ('unames', 'Una vez al mes'),
                                  ('dosmes', '2 o 3 veces al mes'),
                                  ('unasemana', 'Una vez a la semana'),
                                  ('dossemana', u'2 dóas a la semana o más')],
                                 tsustDroga)
Exemple #10
0
class OrthancStudy(ModelSQL, ModelView):
    """Orthanc study"""

    __name__ = "gnuhealth.orthanc.study"

    patient = fields.Many2One("gnuhealth.orthanc.patient", "Patient", readonly=True)
    uuid = fields.Char("UUID", readonly=True, required=True)
    description = fields.Char("Description", readonly=True)
    date = fields.Date("Date", readonly=True)
    ident = fields.Char("ID", readonly=True)
    institution = fields.Char(
        "Institution", readonly=True, help="Imaging center where study was undertaken"
    )
    ref_phys = fields.Char("Referring Physician", readonly=True)
    req_phys = fields.Char("Requesting Physician", readonly=True)
    server = fields.Many2One("gnuhealth.orthanc.config", "Server", readonly=True)
    link = fields.Function(
        fields.Char("URL", help="Link to study in Orthanc Explorer"), "get_link"
    )
    imaging_test = fields.Many2One("gnuhealth.imaging.test.result", "Test")

    def get_link(self, name):
        pre = "".join([self.server.domain.rstrip("/"), "/"])
        add = "app/explorer.html#study?uuid={}".format(self.uuid)
        return urljoin(pre, add)

    @classmethod
    def __setup__(cls):
        super().__setup__()
        t = cls.__table__()
        cls._sql_constraints = [
            (
                "uuid_unique",
                Unique(t, t.server, t.uuid),
                "UUID must be unique for a given server",
            )
        ]

    def get_rec_name(self, name):
        return ": ".join((self.ident or self.uuid, self.description or ""))

    @staticmethod
    def get_info_from_dicom(studies):
        """Extract information for writing to database"""

        data = []

        for study in studies:
            try:
                date = datetime.strptime(
                    study["MainDicomTags"]["StudyDate"], "%Y%m%d"
                ).date()
            except:
                date = None
            try:
                description = study["MainDicomTags"]["RequestedProcedureDescription"]
            except:
                description = None
            data.append(
                {
                    "parent_patient": study["ParentPatient"],
                    "uuid": study["ID"],
                    "description": description,
                    "date": date,
                    "ident": study.get("MainDicomTags").get("StudyID"),
                    "institution": study.get("MainDicomTags").get("InstitutionName"),
                    "ref_phys": study.get("MainDicomTags").get(
                        "ReferringPhysicianName"
                    ),
                    "req_phys": study.get("MainDicomTags").get("RequestingPhysician"),
                }
            )
        return data

    @classmethod
    def update_studies(cls, studies, server):
        """Update studies"""

        entries = cls.get_info_from_dicom(studies)
        updates = []
        for entry in entries:
            try:
                study = cls.search(
                    [("uuid", "=", entry["uuid"]), ("server", "=", server)], limit=1
                )[0]
                study.description = entry["description"]
                study.date = entry["date"]
                study.ident = entry["ident"]
                study.institution = entry["institution"]
                study.ref_phys = entry["ref_phys"]
                study.req_phys = entry["req_phys"]
                updates.append(study)
                logger.info("Updating study {}".format(entry["uuid"]))
            except:
                continue
                logger.warning("Unable to update study {}".format(entry["uuid"]))
        cls.save(updates)

    @classmethod
    def create_studies(cls, studies, server):
        """Create studies"""

        pool = Pool()
        Patient = pool.get("gnuhealth.orthanc.patient")

        entries = cls.get_info_from_dicom(studies)
        for entry in entries:
            try:
                patient = Patient.search(
                    [("uuid", "=", entry["parent_patient"]), ("server", "=", server)],
                    limit=1,
                )[0]
            except:
                patient = None
                logger.warning(
                    "No parent patient found for study {}".format(entry["ID"])
                )
            entry.pop("parent_patient")  # remove non-model entry
            entry["server"] = server
            entry["patient"] = patient
        cls.create(entries)
Exemple #11
0
class HouseBuildingLoan(Workflow, ModelSQL, ModelView):
    'House Building Loan'
    __name__ = 'hba.loan'

    salary_code = fields.Char('Salary Code',
                              states={
                                  'readonly': ~Eval('state').in_(['draft']),
                              },
                              depends=['state'],
                              required=True)
    employee = fields.Many2One('company.employee',
                               'Name of Applicant',
                               states={
                                   'readonly': ~Eval('state').in_(['draft']),
                               },
                               depends=['state'],
                               required=True)
    designation = fields.Many2One("employee.designation",
                                  "Designation",
                                  states={
                                      'readonly':
                                      ~Eval('state').in_(['draft']),
                                  },
                                  depends=['state'],
                                  required=True)
    department = fields.Many2One("company.department",
                                 "Department",
                                 states={
                                     'readonly': ~Eval('state').in_(['draft']),
                                 },
                                 depends=['state'],
                                 required=True)
    post_held = fields.Selection([
        ('permanent', 'Permanent'), ('temporary_offg', 'Temporary/Offg'),
        ('length_of_service', 'Length of service on the date of application')
    ],
                                 string='Post held',
                                 sort=False,
                                 states={
                                     'readonly': ~Eval('state').in_(['draft']),
                                 },
                                 depends=['state'],
                                 required=True)
    place_of_posting = fields.Char('Place of Posting',
                                   states={
                                       'readonly':
                                       ~Eval('state').in_(['draft']),
                                   },
                                   depends=['state'],
                                   required=True)
    scale_pay = fields.Char('Scale Pay',
                            states={
                                'readonly': ~Eval('state').in_(['draft']),
                            },
                            depends=['state'],
                            required=True)
    pension_rule = fields.Selection([
        ('nps', 'NPS'),
        ('gpf', 'GPF'),
    ],
                                    string='Pension Rule',
                                    sort=False,
                                    states={
                                        'readonly':
                                        ~Eval('state').in_(['draft']),
                                    },
                                    depends=['state'],
                                    required=True)
    retirement_date = fields.Date('Date of Retirement', required=True)
    advance = fields.Selection(
        [('yes', 'Yes'), ('no', 'No')],
        string='Any Other advance/Final withdrawal taken\
        for purchase of land/construction',
        sort=False,
        required=True)
    advance_needed = fields.Selection(
        [('plot', 'Purchase of Plot'),
         ('construction', 'Construction of new House'),
         ('enlarging_house', 'Enlarging existing House'),
         ('ready_built', 'Purchase of Ready Built House'),
         ('own_house', 'Own House')],
        string='Advance Needed for',
        sort=False,
        required=True)
    advance_amount = fields.Float('Amount',
                                  states={
                                      'invisible':
                                      ~Eval('advance').in_(['yes']),
                                  },
                                  depends=['advance'])
    source = fields.Char('Source',
                         states={
                             'invisible': ~Eval('advance').in_(['yes']),
                         },
                         depends=['advance'])
    attest_copy = fields.Many2One('ir.attachment',
                                  'attested Copy',
                                  states={
                                      'invisible':
                                      ~Eval('advance').in_(['yes']),
                                  },
                                  depends=['advance'])
    location_address = fields.Char(
        'Location with Address',
        states={
            'invisible':
            ~Eval('advance_needed').in_(['plot', 'enlarging_house']),
        },
        depends=['advance_needed'])
    location_type = fields.Selection([
        ('rural', 'Rural'),
        ('urbun', 'Urban'),
    ],
                                     string='Location Type',
                                     sort=False,
                                     states={
                                         'invisible':
                                         ~Eval('advance_needed').in_(['plot']),
                                     },
                                     depends=['advance_needed'])
    clearly = fields.Selection([('yes', 'Yes'), ('no', 'No')],
                               string='Is it Clearly Demacrated & Developed',
                               sort=False,
                               states={
                                   'invisible':
                                   ~Eval('advance_needed').in_(['plot']),
                               },
                               depends=['advance_needed'])
    area = fields.Float('Apporximate area(in sq.mts.)',
                        states={
                            'invisible': ~Eval('advance_needed').in_(['plot']),
                        },
                        depends=['advance_needed'])
    cost = fields.Float('cost',
                        states={
                            'invisible': ~Eval('advance_needed').in_(['plot']),
                        },
                        depends=['advance_needed'])
    amount = fields.Float('Amount actually paid',
                          states={
                              'invisible':
                              ~Eval('advance_needed').in_(['plot']),
                          },
                          depends=['advance_needed'])
    acquired = fields.Char('If not Purchase when proposed to be acquired',
                           states={
                               'invisible':
                               ~Eval('advance_needed').in_(['plot']),
                           },
                           depends=['advance_needed'])
    unexpired = fields.Char('Unexpired portion of lease if not free hold',
                            states={
                                'invisible':
                                ~Eval('advance_needed').in_(['plot']),
                            },
                            depends=['advance_needed'])
    amount_required = fields.Float('Amount of advance required', required=True)
    installment_no = fields.Integer('No. of instalments for repayment',
                                    required=True)
    construction = fields.One2Many(
        'construction',
        'hba_loan',
        'Construction',
        states={
            'invisible': ~Eval('advance_needed').in_(['construction']),
        },
        depends=['advance_needed'])
    floor = fields.Integer('Floor-wise area to be constructed')
    plinth_area = fields.Float('Plinth area(in sq.mtrs.')
    enlargement = fields.Float(
        'Plinth area proposed for enlargement(in sq. mtrs.)')
    cunstr_cost = fields.Float('Construction Cost')
    enlargement_cost = fields.Float('Cost of proposed enlargement')
    total_plinth = fields.Float('Total Plinth area')
    total_cost = fields.Float('Total Cost')
    constructed = fields.Date('When Constructed')
    price_settled = fields.Float('Price Settled')
    agency = fields.Char('The Agency from whom to be purchased')
    already_paid = fields.Float('Already paid')
    to_be_paid = fields.Float('To be Paid')
    own_house = fields.One2Many('own.house',
                                'hba_loan',
                                'Own House',
                                states={
                                    'invisible':
                                    ~Eval('advance_needed').in_(['own_house']),
                                },
                                depends=['advance_needed'])
    loan_line = fields.One2Many('hba.loan.line',
                                'loan',
                                'Installment Lines',
                                readonly=True)
    payout = fields.Float('Payout',
                          states={
                              'readonly': ~Eval('state').in_(['draft']),
                              'invisible': ~Eval('refund').in_(['refundable']),
                          },
                          depends=['state'])
    pending = fields.Float('Pending',
                           states={
                               'readonly': ~Eval('state').in_(['draft']),
                               'invisible':
                               ~Eval('refund').in_(['refundable']),
                           },
                           depends=['state'])
    reschedule = fields.Float('Reschedule',
                              states={
                                  'readonly': ~Eval('state').in_(['draft']),
                                  'invisible':
                                  ~Eval('refund').in_(['refundable']),
                              },
                              depends=['state'])
    state = fields.Selection([('draft', 'Draft'),
                              ('forwarded_to_jo', 'Forwarded to JO'),
                              ('forwarded_to_ao', 'Forwarded to AO'),
                              ('approve', 'Approved'), ('cancel', 'Cancel')],
                             'Status',
                             readonly=True,
                             sort=False)
    cancel_reason = fields.Char(
        'Cancel Reason',
        states={
            'invisible': ~Eval('state').in_(['forwarded_to_ao', 'cancel']),
            'readonly': ~Eval('state').in_(['forwarded_to_ao']),
        },
        depends=['state'],
    )
    check = fields.Boolean('Check',
                           states={
                               'invisible':
                               Eval('state').in_([
                                   'draft', 'forwarded_to_ao',
                                   'forwarded_to_jo', 'approve', 'cancel'
                               ]),
                           },
                           depends=['state'])

    @staticmethod
    def default_state():
        return 'draft'

    @staticmethod
    def default_employee():
        pool = Pool()
        User = pool.get('res.user')
        user = User(Transaction().user)
        employee = user.employee
        return employee.id if employee else None

    @staticmethod
    def default_salary_code():
        pool = Pool()
        User = pool.get('res.user')
        user = User(Transaction().user)
        employee = user.employee
        return employee.salary_code if employee else None

    @staticmethod
    def default_designation():
        pool = Pool()
        User = pool.get('res.user')
        user = User(Transaction().user)
        employee = user.employee
        return employee.designation.id if employee.designation else None

    @staticmethod
    def default_department():
        pool = Pool()
        User = pool.get('res.user')
        user = User(Transaction().user)
        employee = user.employee
        return employee.department.id if employee.department else None

    @staticmethod
    def default_pay_in_band():
        pool = Pool()
        User = pool.get('res.user')
        user = User(Transaction().user)
        employee = user.employee
        return employee.pay_in_band if employee else None

    @staticmethod
    def default_pension_rule():
        pool = Pool()
        User = pool.get('res.user')
        user = User(Transaction().user)
        employee = user.employee
        return employee.gpf_nps if employee else None

    @classmethod
    def validate(cls, records):
        """Method to validate records(rows) in a model(table)"""
        super().validate(records)
        for record in records:
            house_loan = cls.search([('id', '!=', record.id),
                                     ('employee', '=', record.employee),
                                     ('state', '=', 'approve')])
            if house_loan:
                cls.raise_user_error('You have alraedy take house loan')

    @classmethod
    def view_attributes(cls):
        """Define states for attributes in form view"""
        plot = ~Eval('advance_needed').in_(['plot'])
        construction = ~Eval('advance_needed').in_(['construction'])
        enlarging_house = ~Eval('advance_needed').in_(['enlarging_house'])
        ready_built = ~Eval('advance_needed').in_(['ready_built'])
        own_house = ~Eval('advance_needed').in_(['own_house'])

        attribute = [
            ("//page[@id='plot']", "states", {
                "invisible": plot
            }),
            ("//page[@id='construction']", "states", {
                "invisible": construction
            }),
            ("//page[@id='existing_house']", "states", {
                "invisible": enlarging_house
            }),
            ("//page[@id='build_house']", "states", {
                "invisible": ready_built
            }),
            ("//page[@id='own_house']", "states", {
                "invisible": own_house
            }),
        ]
        return attribute

    @fields.depends('employee')
    def on_change_employee(self, name=None):
        if self.employee:
            self.salary_code = self.employee.salary_code
            self.designation = self.employee.designation
            self.department = self.employee.department
            self.pay_in_band = self.employee.pay_in_band
            if self.employee.gpf_nps:
                self.pension_rule = self.employee.gpf_nps

    @classmethod
    def __setup__(cls):
        """Setup workflow transitions and button properties
           when an instance of this class is initialized"""
        super().__setup__()
        cls._transitions |= set((
            ('draft', 'forwarded_to_jo'),
            ('forwarded_to_jo', 'forwarded_to_ao'),
            ('forwarded_to_ao', 'approve'),
            ('forwarded_to_ao', 'cancel'),
        ))
        cls._buttons.update({
            'calculate_instalment': {},
            'submitted_to_jo': {
                'invisible': ~Eval('state').in_(['draft']),
                'depends': ['state'],
            },
            'forward_to_jo': {
                'invisible': ~Eval('state').in_(['forwarded_to_jo']),
                'depends': ['state'],
            },
            'forward_to_ao': {
                'invisible': ~Eval('state').in_(['forwarded_to_ao']),
                'depends': ['state'],
            },
            'cancel': {
                'invisible': ~Eval('state').in_(['forwarded_to_ao']),
                'depends': ['state'],
            },
        })

    @classmethod
    def calculate_instalment(cls, records):
        for record in records:
            if record.check == False:
                cls.loan_installment(records)
                record.check = True
                record.save()

    @classmethod
    @ModelView.button
    @Workflow.transition('forwarded_to_jo')
    def submitted_to_jo(cls, records):
        """Change status of loan application to forwarded_to_jo"""
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('forwarded_to_ao')
    def forward_to_jo(cls, records):
        """Change status of loan application to forwarded_to_ao"""
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('approve')
    def forward_to_ao(cls, records):
        """Change status of loan application to approve"""
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('cancel')
    def cancel(cls, records):
        """Change status of loan application to cancel"""
        for record in records:
            if not record.cancel_reason:
                cls.raise_user_error('Please fill the Cancel reason')
        pass

    @classmethod
    def loan_installment(cls, records):
        """Calculate number of installments for loan"""
        count = 0
        LoanLine = Pool().get('hba.loan.line')
        for loan in records:
            amount = (loan.amount_required / loan.installment_no)
            for line in range(1, int(loan.installment_no) + 1):
                mydate = datetime.now().month
                month = mydate - 1
                if month + line > 12:
                    count += 1
                    if count > 12:
                        count = 1
                    months = datetime.now().date(1900, count, 1).strftime('%B')
                else:
                    months = datetime.now().date(1900, month + line,
                                                 1).strftime('%B')
                vals = {
                    'month': months,
                    'amount': amount,
                    'status': 'pending',
                    'loan': loan.id
                }
                line = LoanLine.create([vals])

    @classmethod
    def write(cls, *args):
        """ Override default write method of model """
        actions = iter(args)
        for mechanisms, values in zip(actions, actions):
            if 'installment_no' in values.keys(
            ) or 'amount_required' in values.keys():
                cls.change_loan_installment(mechanisms, values)
        super().write(*args)

    @classmethod
    def change_loan_installment(cls, records, values):
        """Change number of installments pending for loan"""
        cursor = Transaction().connection.cursor()
        LoanLine = Pool().get('hba.loan.line')
        amount = 0
        for loan in records:
            cursor.execute(
                'SELECT sum(amount) FROM hba_loan_line \
                WHERE loan=%s AND status != %s', (loan.id, 'pending'))
            total_amount = cursor.fetchone()
            if total_amount[0]:
                reschedule = loan.amount_required - total_amount[0]
                cls.write(records, {
                    'payout': total_amount[0],
                    'reschedule': reschedule
                })
                amount = (reschedule / values['installment_no'])
            else:
                if 'installment_no' in values.keys():
                    amount = (loan.amount_required / values['installment_no'])
                elif 'amount_required' in values.keys():
                    amount = (values['amount_required'] / loan.installment_no)
                elif 'installment_no' in values.keys(
                ) and 'amount_required' in values.keys():
                    amount = (values['amount_required'] /
                              values['installment_no'])
            cursor.execute(
                'delete FROM hba_loan_line WHERE loan=%s \
            AND status = %s', (loan.id, 'pending'))
            count = 0
            installment_no = 0
            if 'installment_no' in values.keys():
                installment_no = values['installment_no']
            else:
                installment_no = loan.installment_no
            for line in range(1, int(installment_no) + 1):
                mydate = datetime.now().month
                if total_amount[0]:
                    month = mydate
                else:
                    month = mydate - 1
                if month + line > 12:
                    count += 1
                    if count > 12:
                        count = 1
                    months = datetime(1900, count, 1).date().strftime('%B')
                else:
                    months = datetime(1900, month + line,
                                      1).date().strftime('%B')
                vals = {
                    'month': months,
                    'amount': amount,
                    'status': 'pending',
                    'loan': loan.id
                }
                line = LoanLine.create([vals])
Exemple #12
0
class OrthancPatient(ModelSQL, ModelView):
    """Orthanc patient information"""

    __name__ = "gnuhealth.orthanc.patient"

    patient = fields.Many2One(
        "gnuhealth.patient", "Patient", help="Local linked patient"
    )
    name = fields.Char("PatientName", readonly=True)
    bd = fields.Date("Birthdate", readonly=True)
    ident = fields.Char("PatientID", readonly=True)
    uuid = fields.Char("PatientUUID", readonly=True, required=True)
    studies = fields.One2Many(
        "gnuhealth.orthanc.study", "patient", "Studies", readonly=True
    )
    server = fields.Many2One("gnuhealth.orthanc.config", "Server", readonly=True)
    link = fields.Function(
        fields.Char("URL", help="Link to patient in Orthanc Explorer"), "get_link"
    )

    def get_link(self, name):
        pre = "".join([self.server.domain.rstrip("/"), "/"])
        add = "app/explorer.html#patient?uuid={}".format(self.uuid)
        return urljoin(pre, add)

    @classmethod
    def __setup__(cls):
        super().__setup__()
        t = cls.__table__()
        cls._sql_constraints = [
            (
                "uuid_unique",
                Unique(t, t.server, t.uuid),
                "UUID must be unique for a given server",
            )
        ]

    @staticmethod
    def get_info_from_dicom(patients):
        """Extract information for writing to database"""

        data = []
        for patient in patients:
            try:
                bd = datetime.strptime(
                    patient["MainDicomTags"]["PatientBirthDate"], "%Y%m%d"
                ).date()
            except:
                bd = None
            data.append(
                {
                    "name": patient.get("MainDicomTags").get("PatientName"),
                    "bd": bd,
                    "ident": patient.get("MainDicomTags").get("PatientID"),
                    "uuid": patient.get("ID"),
                }
            )
        return data

    @classmethod
    def update_patients(cls, patients, server):
        """Update patients"""

        Patient = pool.get("gnuhealth.patient")

        entries = cls.get_info_from_dicom(patients)
        updates = []
        for entry in entries:
            try:
                patient = cls.search(
                    [("uuid", "=", entry["uuid"]), ("server", "=", server)], limit=1
                )[0]
                patient.name = entry["name"]
                patient.bd = entry["bd"]
                patient.ident = entry["ident"]
                if not patient.patient:  # don't update unless no patient attached
                    try:
                        g_patient = Patient.search(
                            [("puid", "=", entry["ident"])], limit=1
                        )[0]
                        patient.patient = g_patient
                        logger.info(
                            "New Matching PUID found for {}".format(entry["ident"])
                        )
                    except:
                        pass
                updates.append(patient)
                logger.info("Updating patient {}".format(entry["uuid"]))
            except:
                continue
                logger.warning("Unable to update patient {}".format(entry["uuid"]))
        cls.save(updates)

    @classmethod
    def create_patients(cls, patients, server):
        """Create patients"""

        pool = Pool()
        Patient = pool.get("gnuhealth.patient")

        entries = cls.get_info_from_dicom(patients)
        for entry in entries:
            try:
                g_patient = Patient.search([("puid", "=", entry["ident"])], limit=1)[0]
                logger.info("Matching PUID found for {}".format(entry["uuid"]))
            except:
                g_patient = None
            entry["server"] = server
            entry["patient"] = g_patient
        cls.create(entries)
class PurchaseRequest(ModelSQL, ModelView):
    'Purchase Request'
    __name__ = 'purchase.request'

    product = fields.Many2One('product.product',
                              'Product',
                              required=True,
                              select=True,
                              readonly=True,
                              domain=[('purchasable', '=', True)])
    party = fields.Many2One('party.party',
                            'Party',
                            select=True,
                            states=STATES,
                            depends=DEPENDS)
    quantity = fields.Float('Quantity',
                            required=True,
                            states=STATES,
                            digits=(16, Eval('uom_digits', 2)),
                            depends=DEPENDS + ['uom_digits'])
    uom = fields.Many2One('product.uom',
                          'UOM',
                          required=True,
                          select=True,
                          states=STATES,
                          depends=DEPENDS)
    uom_digits = fields.Function(fields.Integer('UOM Digits'),
                                 'on_change_with_uom_digits')
    computed_quantity = fields.Float('Computed Quantity', readonly=True)
    computed_uom = fields.Many2One('product.uom',
                                   'Computed UOM',
                                   readonly=True)
    purchase_date = fields.Date('Best Purchase Date', readonly=True)
    supply_date = fields.Date('Expected Supply Date', readonly=True)
    default_uom_digits = fields.Function(fields.Integer('Default UOM Digits'),
                                         'on_change_with_default_uom_digits')
    stock_level = fields.Float('Stock at Supply Date',
                               readonly=True,
                               digits=(16, Eval('default_uom_digits', 2)),
                               depends=['default_uom_digits'])
    warehouse = fields.Many2One('stock.location',
                                "Warehouse",
                                states={
                                    'required': Eval('warehouse_required',
                                                     False),
                                },
                                domain=[('type', '=', 'warehouse')],
                                depends=['warehouse_required'],
                                readonly=True)
    warehouse_required = fields.Function(fields.Boolean('Warehouse Required'),
                                         'get_warehouse_required')
    purchase_line = fields.Many2One('purchase.line',
                                    'Purchase Line',
                                    readonly=True)
    purchase = fields.Function(fields.Many2One('purchase.purchase',
                                               'Purchase'),
                               'get_purchase',
                               searcher='search_purchase')
    company = fields.Many2One('company.company',
                              'Company',
                              required=True,
                              readonly=True,
                              domain=[
                                  ('id',
                                   If(In('company', Eval('context', {})), '=',
                                      '!='), Eval('context',
                                                  {}).get('company', -1)),
                              ])
    origin = fields.Reference('Origin',
                              selection='get_origin',
                              readonly=True,
                              required=True)
    exception_ignored = fields.Boolean('Ignored Exception')
    state = fields.Function(fields.Selection([
        ('purchased', 'Purchased'),
        ('done', 'Done'),
        ('draft', 'Draft'),
        ('cancel', 'Cancel'),
        ('exception', 'Exception'),
    ], 'State'),
                            'get_state',
                            searcher='search_state')

    @classmethod
    def __setup__(cls):
        super(PurchaseRequest, cls).__setup__()
        cls._order[0] = ('id', 'DESC')
        cls._error_messages.update({
            'create_request': ('Purchase requests are only created '
                               'by the system.'),
            'delete_purchase_line': ('You can not delete purchased '
                                     'request.'),
        })
        cls._buttons.update({
            'handle_purchase_cancellation_exception': {
                'invisible': Eval('state') != 'exception',
            },
        })

    @classmethod
    def __register__(cls, module_name):
        pool = Pool()
        ModelData = pool.get('ir.model.data')
        TableHandler = backend.get('TableHandler')
        model_data = ModelData.__table__()
        super(PurchaseRequest, cls).__register__(module_name)

        # Migration from 3.6: removing the constraint on the quantity
        tablehandler = TableHandler(cls, module_name)
        tablehandler.drop_constraint('check_purchase_request_quantity')

        # Migration from 3.8: renaming module of Purchase Request group entry
        cursor = Transaction().connection.cursor()
        cursor.execute(*model_data.update(
            columns=[model_data.module],
            values=['purchase_request'],
            where=((model_data.fs_id == 'group_purchase_request')
                   & (model_data.module == 'stock_supply'))))

    def get_rec_name(self, name):
        if self.warehouse:
            return "%s@%s" % (self.product.name, self.warehouse.name)
        else:
            return self.product.name

    @classmethod
    def search_rec_name(cls, name, clause):
        res = []
        names = clause[2].split('@', 1)
        res.append(('product.template.name', clause[1], names[0]))
        if len(names) != 1 and names[1]:
            res.append(('warehouse', clause[1], names[1]))
        return res

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

    @staticmethod
    def default_exception_ignored():
        return False

    def get_purchase(self, name):
        if self.purchase_line:
            return self.purchase_line.purchase.id

    @classmethod
    def search_purchase(cls, name, clause):
        return [('purchase_line.purchase', ) + tuple(clause[1:])]

    @property
    def currency(self):
        return self.company.currency

    def get_state(self, name):
        if self.purchase_line:
            if (self.purchase_line.purchase.state == 'cancel'
                    and not self.exception_ignored):
                return 'exception'
            elif self.purchase_line.purchase.state == 'cancel':
                return 'cancel'
            elif self.purchase_line.purchase.state == 'done':
                return 'done'
            else:
                return 'purchased'
        return 'draft'

    @classmethod
    def search_state(cls, name, clause):
        pool = Pool()
        Purchase = pool.get('purchase.purchase')
        PurchaseLine = pool.get('purchase.line')

        request = cls.__table__()
        purchase_line = PurchaseLine.__table__()
        purchase = Purchase.__table__()

        _, operator_, state = clause
        Operator = fields.SQL_OPERATORS[operator_]
        state_case = Case(
            ((purchase.state == 'cancel')
             & (request.exception_ignored == False), 'exception'),
            ((purchase.state == 'cancel')
             & (request.exception_ignored == True), 'cancel'),
            (purchase.state == 'done', 'done'),
            (request.purchase_line != Null, 'purchased'),
            else_='draft')
        state_query = request.join(
            purchase_line,
            type_='LEFT',
            condition=request.purchase_line == purchase_line.id).join(
                purchase,
                type_='LEFT',
                condition=purchase_line.purchase == purchase.id).select(
                    request.id, where=Operator(state_case, state))

        return [('id', 'in', state_query)]

    def get_warehouse_required(self, name):
        return self.product.type in ('goods', 'assets')

    @fields.depends('uom')
    def on_change_with_uom_digits(self, name=None):
        if self.uom:
            return self.uom.digits
        return 2

    @fields.depends('product')
    def on_change_with_default_uom_digits(self, name=None):
        if self.product:
            return self.product.default_uom.digits
        return 2

    @classmethod
    def _get_origin(cls):
        'Return the set of Model names for origin Reference'
        return set()

    @classmethod
    def get_origin(cls):
        pool = Pool()
        IrModel = pool.get('ir.model')
        models = IrModel.search([
            ('model', 'in', list(cls._get_origin())),
        ])
        return [(m.model, m.name) for m in models]

    @classmethod
    def create(cls, vlist):
        for vals in vlist:
            for field_name in ('product', 'quantity', 'uom', 'company'):
                if vals.get(field_name) is None:
                    cls.raise_user_error('create_request')
        return super(PurchaseRequest, cls).create(vlist)

    @classmethod
    def delete(cls, requests):
        if any(r.purchase_line for r in requests):
            cls.raise_user_error('delete_purchase_line')
        super(PurchaseRequest, cls).delete(requests)

    @classmethod
    def find_best_supplier(cls, product, date):
        '''
        Return the best supplier and purchase_date for the product.
        '''
        Date = Pool().get('ir.date')

        supplier = None
        today = Date.today()
        for product_supplier in product.product_suppliers:
            supply_date = product_supplier.compute_supply_date(date=today)
            timedelta = date - supply_date
            if not supplier and timedelta >= datetime.timedelta(0):
                supplier = product_supplier.party
                break

        if supplier:
            purchase_date = product_supplier.compute_purchase_date(date)
        else:
            purchase_date = today
        return supplier, purchase_date

    @classmethod
    @ModelView.button_action(
        'purchase_request.wizard_purchase_cancellation_handle_exception')
    def handle_purchase_cancellation_exception(cls, purchases):
        pass
class HealthService(ModelSQL, ModelView):
    'Health Service'
    __name__ = 'gnuhealth.health_service'

    STATES = {'readonly': Eval('state') == 'invoiced'}

    name = fields.Char('ID', readonly=True)
    desc = fields.Char('Description')
    patient = fields.Many2One('gnuhealth.patient',
                              'Patient',
                              required=True,
                              states=STATES)
    institution = fields.Many2One('gnuhealth.institution', 'Institution')

    service_date = fields.Date('Date')
    service_line = fields.One2Many('gnuhealth.health_service.line',
                                   'name',
                                   'Service Line',
                                   help="Service Line")
    state = fields.Selection([
        ('draft', 'Draft'),
        ('invoiced', 'Invoiced'),
    ],
                             'State',
                             readonly=True)
    invoice_to = fields.Many2One('party.party', 'Invoice to')

    @classmethod
    def __setup__(cls):
        super(HealthService, cls).__setup__()

        t = cls.__table__()
        cls._sql_constraints = [
            ('name_unique', Unique(t,
                                   t.name), 'The Service ID must be unique'),
        ]
        cls._buttons.update({
            'button_set_to_draft': {
                'invisible': Equal(Eval('state'), 'draft')
            }
        })

    @staticmethod
    def default_state():
        return 'draft'

    @staticmethod
    def default_service_date():
        return datetime.date.today()

    @staticmethod
    def default_institution():
        HealthInst = Pool().get('gnuhealth.institution')
        institution = HealthInst.get_institution()
        return institution

    @classmethod
    @ModelView.button
    def button_set_to_draft(cls, services):
        cls.write(services, {'state': 'draft'})

    @classmethod
    def create(cls, vlist):
        Sequence = Pool().get('ir.sequence')
        Config = Pool().get('gnuhealth.sequences')

        vlist = [x.copy() for x in vlist]
        for values in vlist:
            if not values.get('name'):
                config = Config(1)
                values['name'] = Sequence.get_id(
                    config.health_service_sequence.id)
        return super(HealthService, cls).create(vlist)
Exemple #15
0
class Party:
    __name__ = 'party.party'
    vat_number_city = fields.Char('VAT Number City',
                                  states={'readonly': ~Eval('active', True)})
    type_document = fields.Selection([
        ('', ''),
        ('04', 'RUC'),
        ('05', 'Cedula'),
        ('06', 'Pasaporte'),
        ('07', 'Consumidor Final'),
    ],
                                     'Type Document',
                                     states={
                                         'readonly': ~Eval('active', True),
                                     },
                                     depends=['active'])
    mandatory_accounting = fields.Selection([
        ('yes', 'Yes'),
        ('no', 'No'),
    ],
                                            'Mandatory Accounting',
                                            required=False)
    first_name = fields.Char('Primer Nombre')
    second_name = fields.Char('Segundo Nombre')
    first_family_name = fields.Char('Primer Apellido')
    second_family_name = fields.Char('Segundo Apellido')
    commercial_name = fields.Char('Commercial Name')
    type_party = fields.Selection(
        [
            ('', ''),
            ('sociedad', 'Sociedad'),
            ('persona_natural', 'Personal natural'),
            ('contribuyente_especial', 'Contribuyente especial'),
            ('entidad_publica', 'Entidad del sector publico'),
            ('companias_seguros', 'Companias de aseguros y reaseguros'),
        ],
        'Type Party',
        states={
            'readonly': ~Eval('active', True),
            'invisible': Eval('type_document') != '04',
        })
    registro_mercantil = fields.Char(
        'Registro Mercantil', states={'readonly': ~Eval('active', True)})
    start_activities = fields.Date('Start Activities')

    @classmethod
    def __setup__(cls):
        super(Party, cls).__setup__()
        cls._error_messages.update(
            {'invalid_vat_number': ('Invalid VAT Number "%s".')})
        cls._sql_constraints += [
            ('vat_number', 'UNIQUE(vat_number)', 'VAT Number already exists!'),
        ]

    @staticmethod
    def default_type_document():
        return '04'

    @staticmethod
    def default_mandatory_accounting():
        return 'no'

    @classmethod
    def search_rec_name(cls, name, clause):
        parties = cls.search([
            ('vat_number', ) + tuple(clause[1:]),
        ], limit=1)
        if parties:
            return [('vat_number', ) + tuple(clause[1:])]
        return [('name', ) + tuple(clause[1:])]

    @classmethod
    def validate(cls, parties):
        for party in parties:
            if party.type_document == '04' and bool(party.vat_number):
                super(Party, cls).validate(parties)

    def pre_validate(self):
        if not self.vat_number:
            return
        if self.vat_number == '9999999999999':
            return
        vat_number = self.vat_number.replace(".", "")
        if vat_number.isdigit() and len(vat_number) > 9:
            is_valid = self.compute_check_digit(vat_number)
            if is_valid:
                return
        self.raise_user_error('invalid_vat_number', (self.vat_number, ))

    def compute_check_digit(self, raw_number):
        "Compute the check digit - Modulus 10 and 11"
        factor = 2
        x = 0
        set_check_digit = None
        if self.type_document == '04':
            # Si es RUC valide segun el tipo de tercero
            if self.type_party == 'persona_natural':
                if len(raw_number) != 13 or int(
                        raw_number[2]) > 5 or raw_number[-3:] != '001':
                    return
                number = raw_number[:9]
                set_check_digit = raw_number[9]
                for n in number:
                    y = int(n) * factor
                    if y >= 10:
                        y = int(str(y)[0]) + int(str(y)[1])
                    x += y
                    if factor == 2:
                        factor = 1
                    else:
                        factor = 2
                res = (x % 10)
                if res == 0:
                    value = 0
                else:
                    value = 10 - (x % 10)
            elif self.type_party == 'entidad_publica':
                if not len(raw_number) == 13 or raw_number[2] != '6' \
                    or raw_number[-3:] != '001':
                    return
                number = raw_number[:8]
                set_check_digit = raw_number[8]
                for n in reversed(number):
                    x += int(n) * factor
                    factor += 1
                    if factor == 8:
                        factor = 2
                value = 11 - (x % 11)
                if value == 11:
                    value = 0
            else:
                if len(raw_number) != 13 or \
                    (self.type_party in ['sociedad', 'companias_seguros'] \
                    and int(raw_number[2]) != 9) or raw_number[-3:] != '001':
                    return
                number = raw_number[:9]
                set_check_digit = raw_number[9]
                for n in reversed(number):
                    x += int(n) * factor
                    factor += 1
                    if factor == 8:
                        factor = 2
                value = 11 - (x % 11)
                if value == 11:
                    value = 0
        else:
            #Si no tiene RUC valide: cedula, pasaporte, consumidor final (cedula)
            if len(raw_number) != 10:
                return
            number = raw_number[:9]
            set_check_digit = raw_number[9]
            for n in number:
                y = int(n) * factor
                if y >= 10:
                    y = int(str(y)[0]) + int(str(y)[1])
                x += y
                if factor == 2:
                    factor = 1
                else:
                    factor = 2
            res = (x % 10)
            if res == 0:
                value = 0
            else:
                value = 10 - (x % 10)
        return (set_check_digit == str(value))
Exemple #16
0
class Work(DeactivableMixin, ModelSQL, ModelView):
    'Work'
    __name__ = 'timesheet.work'
    name = fields.Char('Name',
                       states={
                           'invisible': Bool(Eval('origin')),
                           'required': ~Eval('origin'),
                       },
                       depends=['origin'],
                       help="The main identifier of the work.")
    origin = fields.Reference(
        'Origin',
        selection='get_origin',
        states={
            'invisible': Bool(Eval('name')),
            'required': ~Eval('name'),
        },
        depends=['name'],
        help="Use to relate the time spent to other records.")
    duration = fields.Function(
        fields.TimeDelta('Timesheet Duration',
                         'company_work_time',
                         help="Total time spent on this work."),
        'get_duration')
    timesheet_start_date = fields.Date(
        'Timesheet Start',
        domain=[
            If(
                Eval('timesheet_start_date') & Eval('timesheet_end_date'),
                ('timesheet_start_date', '<=', Eval('timesheet_end_date')),
                ()),
        ],
        depends=['timesheet_end_date'],
        help="Restrict adding lines before the date.")
    timesheet_end_date = fields.Date(
        'Timesheet End',
        domain=[
            If(
                Eval('timesheet_start_date') & Eval('timesheet_end_date'),
                ('timesheet_end_date', '>=', Eval('timesheet_start_date')),
                ()),
        ],
        depends=['timesheet_start_date'],
        help="Restrict adding lines after the date.")
    company = fields.Many2One('company.company',
                              'Company',
                              required=True,
                              select=True,
                              help="Make the work belong to the company.")
    timesheet_lines = fields.One2Many('timesheet.line',
                                      'work',
                                      'Timesheet Lines',
                                      depends=['active'],
                                      states={
                                          'readonly':
                                          Not(Bool(Eval('active'))),
                                      },
                                      help="Spend time on this work.")
    # Self referring field to use for aggregation in graph view
    work = fields.Function(fields.Many2One('timesheet.work', 'Work'),
                           'get_work')

    @classmethod
    def __setup__(cls):
        super(Work, cls).__setup__()
        t = cls.__table__()
        cls._sql_constraints += [
            ('origin_unique', Unique(t, t.origin, t.company),
             'timesheet.msg_work_origin_unique_company'),
        ]

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

        super(Work, cls).__register__(module_name)

        # Migration from 4.0: remove required on name
        table_h.not_null_action('name', 'remove')

        # Migration from 4.0: remove parent, left and right
        if table_h.column_exist('parent'):
            id2name = {}
            id2parent = {}
            cursor.execute(*table.select(table.id, table.parent, table.name))
            for id_, parent, name in cursor:
                id2name[id_] = name
                id2parent[id_] = parent

            for id_, name in id2name.items():
                parent = id2parent[id_]
                while parent:
                    name = '%s\\%s' % (id2name[parent], name)
                    parent = id2parent[parent]
                cursor.execute(
                    *table.update([table.name], [name], where=table.id == id_))
            table_h.drop_column('parent')
        table_h.drop_column('left')
        table_h.drop_column('right')

        # Migration from 4.0: remove timesheet_available
        if table_h.column_exist('timesheet_available'):
            cursor.execute(*table.delete(
                where=table.timesheet_available == Literal(False)))
            table_h.drop_column('timesheet_available')

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

    @classmethod
    def _get_origin(cls):
        'Return list of Model names for origin Reference'
        return []

    @classmethod
    def get_origin(cls):
        Model = Pool().get('ir.model')
        models = cls._get_origin()
        models = Model.search([
            ('model', 'in', models),
        ])
        return [('', '')] + [(m.model, m.name) for m in models]

    @classmethod
    def get_duration(cls, works, name):
        pool = Pool()
        Line = pool.get('timesheet.line')
        transaction = Transaction()
        cursor = transaction.connection.cursor()
        context = transaction.context

        table_w = cls.__table__()
        line = Line.__table__()
        ids = [w.id for w in works]
        durations = dict.fromkeys(ids, None)
        where = Literal(True)
        if context.get('from_date'):
            where &= line.date >= context['from_date']
        if context.get('to_date'):
            where &= line.date <= context['to_date']
        if context.get('employees'):
            where &= line.employee.in_(context['employees'])

        query_table = table_w.join(line,
                                   'LEFT',
                                   condition=line.work == table_w.id)

        for sub_ids in grouped_slice(ids):
            red_sql = reduce_ids(table_w.id, sub_ids)
            cursor.execute(*query_table.select(table_w.id,
                                               Sum(line.duration),
                                               where=red_sql & where,
                                               group_by=table_w.id))
            for work_id, duration in cursor.fetchall():
                # SQLite uses float for SUM
                if duration and not isinstance(duration, datetime.timedelta):
                    duration = datetime.timedelta(seconds=duration)
                durations[work_id] = duration
        return durations

    def get_work(self, name):
        return self.id

    def get_rec_name(self, name):
        if isinstance(self.origin, ModelStorage):
            return self.origin.rec_name
        else:
            return self.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'
        return [
            bool_op,
            ('name', ) + tuple(clause[1:]),
        ] + [('origin.rec_name', ) + tuple(clause[1:]) + (origin, )
             for origin in cls._get_origin()]

    @classmethod
    def copy(cls, works, default=None):
        if default is None:
            default = {}
        else:
            default = default.copy()
        default.setdefault('timesheet_lines', None)
        return super(Work, cls).copy(works, default=default)

    @classmethod
    def validate(cls, works):
        super(Work, cls).validate(works)
        for work in works:
            if work.origin and not work._validate_company():
                raise CompanyValidationError(
                    gettext('timesheet.msg_work_company_different_origin',
                            work=work.rec_name))

    def _validate_company(self):
        return True

    @classmethod
    def search_global(cls, text):
        for record, rec_name, icon in super(Work, cls).search_global(text):
            icon = icon or 'tryton-clock'
            yield record, rec_name, icon

    @property
    def hours(self):
        if not self.duration:
            return 0
        return self.duration.total_seconds() / 60 / 60
Exemple #17
0
class PlanificationProfessionalLine(ModelSQL, ModelView):
    'Planification Professional Line'
    __name__ = 'lims.planification.professional.line'

    template = fields.Many2One('lims.template.analysis_sheet', 'Template')
    laboratory = fields.Many2One('lims.laboratory', 'Laboratory')
    professional = fields.Many2One('lims.laboratory.professional',
        'Professional')
    date = fields.Date('Date')
    state = fields.Selection([
        ('draft', 'Draft'),
        ('active', 'Active'),
        ('validated', 'Validated'),
        ('done', 'Done'),
        ], 'State')
    samples_qty = fields.Function(fields.Integer('# Samples'),
        'get_fields')
    completion_percentage = fields.Function(fields.Numeric('Complete',
        digits=(1, 4), domain=[
            ('completion_percentage', '>=', 0),
            ('completion_percentage', '<=', 1),
            ]),
        'get_fields')
    color = fields.Function(fields.Char('Color'), 'get_color')

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

    @classmethod
    def table_query(cls):
        pool = Pool()
        Sheet = pool.get('lims.analysis_sheet')
        Compilation = pool.get('lims.interface.compilation')
        sheet = Sheet.__table__()
        compilation = Compilation.__table__()

        context = Transaction().context
        where = Literal(True)
        if context.get('laboratory'):
            where &= sheet.laboratory == context.get('laboratory')
        if context.get('from_date'):
            where &= compilation.date_time >= datetime.combine(
                context.get('from_date'), time(0, 0))
        if context.get('to_date'):
            where &= compilation.date_time <= datetime.combine(
                context.get('to_date'), time(23, 59))

        columns = []
        for fname, field in cls._fields.items():
            if hasattr(field, 'set'):
                continue
            if fname == 'date':
                column = Cast(compilation.date_time, 'date').as_(fname)
            else:
                column = Column(sheet, fname).as_(fname)
            columns.append(column)
        return sheet.join(compilation,
            condition=sheet.compilation == compilation.id).select(*columns,
            where=where)

    @classmethod
    def get_fields(cls, records, name):
        pool = Pool()
        Sheet = pool.get('lims.analysis_sheet')

        sheets = Sheet.browse(records)
        return {s.id: getattr(s, name) for s in sheets}

    def get_color(self, name):
        return 'lightblue'
Exemple #18
0
class Article(Workflow, ModelSQL, ModelView, CMSMenuItemMixin):
    "CMS Articles"
    __name__ = 'nereid.cms.article'
    _rec_name = 'uri'

    uri = fields.Char('URI', required=True, select=True, translate=True)
    title = fields.Char('Title', required=True, select=True, translate=True)
    content = fields.Text('Content', required=True, translate=True)
    template = fields.Char('Template', required=True)
    image = fields.Many2One('nereid.static.file', 'Image')
    employee = fields.Many2One('company.employee', 'Employee')
    author = fields.Many2One('nereid.user', 'Author')
    published_on = fields.Date('Published On')
    publish_date = fields.Function(fields.Char('Publish Date'),
                                   'get_publish_date')
    sequence = fields.Integer('Sequence', required=True, select=True)
    reference = fields.Reference('Reference', selection='allowed_models')
    description = fields.Text('Short Description')
    attributes = fields.One2Many('nereid.cms.article.attribute', 'article',
                                 'Attributes')
    categories = fields.Many2Many(
        'nereid.cms.category-article',
        'article',
        'category',
        'Categories',
    )
    content_type = fields.Selection('content_type_selection',
                                    'Content Type',
                                    required=True)
    # Article can have a banner
    banner = fields.Many2One('nereid.cms.banner', 'Banner')
    state = fields.Selection([('draft', 'Draft'), ('published', 'Published'),
                              ('archived', 'Archived')],
                             'State',
                             required=True,
                             select=True,
                             readonly=True)

    @classmethod
    def __setup__(cls):
        super(Article, cls).__setup__()
        cls._order.insert(0, ('sequence', 'ASC'))
        cls._transitions |= set((
            ('draft', 'published'),
            ('published', 'draft'),
            ('published', 'archived'),
            ('archived', 'draft'),
        ))
        cls._buttons.update({
            'archive': {
                'invisible': Eval('state') != 'published',
            },
            'publish': {
                'invisible': Eval('state').in_(['published', 'archived']),
            },
            'draft': {
                'invisible': Eval('state') == 'draft',
            }
        })

    @classmethod
    def content_type_selection(cls):
        """
        Returns a selection for content_type.
        """
        default_types = [('html', 'HTML'), ('plain', 'Plain Text')]

        if markdown:
            default_types.append(('markdown', 'Markdown'))
        if publish_parts:
            default_types.append(('rst', 'reStructured TeXT'))

        return default_types

    @classmethod
    def default_content_type(cls):
        """
        Default content_type.
        """
        return 'plain'

    def __html__(self):
        """
        Uses content_type field to generate html content.
        Concept from Jinja2's Markup class.
        """
        if self.content_type == 'rst':
            if publish_parts:
                res = publish_parts(self.content, writer_name='html')
                return res['html_body']
            self.raise_user_error(
                "`docutils` not installed, to render rst articles.")
        if self.content_type == 'markdown':
            if markdown:
                return markdown(self.content)
            self.raise_user_error(
                "`markdown` not installed, to render markdown article.")
        return self.content

    @classmethod
    @ModelView.button
    @Workflow.transition('archived')
    def archive(cls, articles):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('published')
    def publish(cls, articles):
        pass

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

    @classmethod
    def allowed_models(cls):
        MenuItem = Pool().get('nereid.cms.menuitem')

        return MenuItem.allowed_models()

    @fields.depends('title', 'uri')
    def on_change_title(self):
        if self.title and not self.uri:
            self.uri = slugify(self.title)

    @staticmethod
    def default_template():
        return 'article.jinja'

    @staticmethod
    def default_employee():
        User = Pool().get('res.user')

        if 'employee' in Transaction().context:
            return Transaction().context['employee']

        user = User(Transaction().user)
        if user.employee:
            return user.employee.id

        if has_request_context() and current_user.employee:
            return current_user.employee.id

    @staticmethod
    def default_author():
        if has_request_context():
            return current_user.id

    @staticmethod
    def default_published_on():
        Date = Pool().get('ir.date')
        return Date.today()

    @classmethod
    @route('/article/<uri>')
    def render(cls, uri):
        """
        Renders the template
        """
        try:
            article, = cls.search([
                ('uri', '=', uri),
                ('state', '=', 'published'),
            ])
        except ValueError:
            abort(404)
        return render_template(article.template, article=article)

    @classmethod
    @route('/sitemaps/article-index.xml')
    def sitemap_index(cls):
        index = SitemapIndex(cls, [])
        return index.render()

    @classmethod
    @route('/sitemaps/article-<int:page>.xml')
    def sitemap(cls, page):
        sitemap_section = SitemapSection(cls, [], page)
        sitemap_section.changefreq = 'daily'
        return sitemap_section.render()

    @classmethod
    def get_publish_date(cls, records, name):
        """
        Return publish date to render on view
        """
        res = {}
        for record in records:
            res[record.id] = str(record.published_on)
        return res

    def get_absolute_url(self, **kwargs):
        return url_for('nereid.cms.article.render', uri=self.uri, **kwargs)

    @staticmethod
    def default_state():
        if 'published' in Transaction().context:
            return 'published'
        return 'draft'

    def get_menu_item(self, max_depth):
        """
        Return huge dictionary with serialized article category for menu item

        {
            title: <display name>,
            link: <url>,
            record: <instance of record>  # if type_ is `record`
        }
        """
        return {
            'record': self,
            'title': self.title,
            'link': self.get_absolute_url(),
        }

    def atom_id(self):
        """
        Returns an atom ID for the article
        """
        return ('tag:' + current_website.name + ',' + self.publish_date +
                ':Article/' + str(self.id))

    def atom_publish_date(self):
        """
        Returns the article's publish date with timezone set as UTC
        """
        return pytz.utc.localize(
            datetime.combine(self.published_on, datetime.min.time()))

    def serialize(self, purpose=None):
        """
        Serialize Article records
        """
        if purpose == 'atom':
            # The keys in the dictionary returned are used by Werkzeug's
            # AtomFeed class.
            return {
                'id':
                self.atom_id(),
                'title':
                self.title,
                'author': (self.author.serialize(
                    purpose=purpose) if self.author else None),
                'content':
                self.content,
                'content_type':
                ('text' if self.content_type == 'plain' else 'html'),
                'link': {
                    'rel': 'alternate',
                    'type': 'text/html',
                    'href': self.get_absolute_url(external=True),
                },
                'category': [
                    category.serialize(purpose=purpose)
                    for category in self.categories
                ],
                'published':
                self.atom_publish_date(),
                'updated':
                self.write_date or self.atom_publish_date(),
            }
        elif hasattr(super(Article, self), 'serialize'):
            return super(Article, self).serialize(purpose=purpose)

    @classmethod
    @route('/article/all.atom')
    def atom_feed(cls):
        """
        Renders the atom feed for all articles.
        """
        feed = AtomFeed("All Articles",
                        feed_url=request.url,
                        url=request.host_url)
        for article in cls.search([('state', '=', 'published')]):
            feed.add(**article.serialize(purpose='atom'))

        return feed.get_response()
Exemple #19
0
class Hshn(ModelSQL, ModelView):
    """ Class for business logic of the module hshn.
        The used fields, set deafult values,
        button actions and special logic for sending a mail are defined in the Class """
    __name__ = "hshn.hshn"
    company = fields.Many2One('company.company', 'Company', required=True,
        states={
            'readonly': (Eval('state') != 'draft') | Eval('lines', [0]),
            },
        domain=[
            ('id', If(Eval('context', {}).contains('company'), '=', '!='),
                Eval('context', {}).get('company', -1)),
            ],
        depends=['state'], select=True)

    topic = fields.Char('Topic', required=True, help='Please enter your topic')
    project_study_spo3 = fields.Selection([
        ('None', ''),
        ('SEPS', 'SEPS'),
        ('PSBWL', 'PSBWL'),
        ('PSWIN', 'PSWIN'),
        ('PSIT', 'PSIT'),
    ], 'Project study SPO3', states={
        'readonly': Eval('spo_selection') != 'SPO3',
        'required': Bool(Eval('spo_selection') != 'SPO4')
    }, help='Please select the project study for which you will submit the proposal'+
        '\n SEPS  = Project Study Software development EDV-No: 281531'+
        '\n PSBWL = Project Study BWL EDV-No:281542'+
        '\n PSWIN = Project Study economic computer science EDV-No: 281560'+
        '\n PSIT  = Project Study IT-Systems EDV-No:281584')
    project_study_spo4 = fields.Selection([
        ('None', ''),
        ('PSEIS', 'PSEIS'),
        ('PSEMU', 'PSEMU'),
        ('PSIT', 'PSIT'),
        ('PSAIS', 'PSAIS'),
        ('PSIM', 'PSIM'),
        ('PSSMU', 'PSSMU'),
        ('PSSMM', 'PSSMM'),
        ('PSSRM', 'PSSRM'),
    ], 'Project study SPO4', states={
        'readonly': Eval('spo_selection') != 'SPO4',
        'required': Bool(Eval('spo_selection') != 'SPO3')
    }, help='Please select the project study for which you will submit the proposal' +
        '\n PSEIS = Project Study Enterprise Information Systems EDV-No: 281761' +
        '\n PSEMU = Project Study Development mobile Enterprise Applications EDV-No:281760' +
        '\n PSIT  = Project Study IT-Systems EDV-No: 281765' +
        '\n PSAIS = Project Study Analytic Information Systems and Data Science EDV-No:281784' +
        '\n PSIM  = Project Study Information Management EDV-No: 281780' +
        '\n PSSMU = Project Study Social Media in enterprise context' +
        '\n PSSMM = Project Study Social Media Management and Audiovisual Communication EDV-No:281796' +
        '\n PSSRM = Project Study Social Relationship Management EDV-No:281790')
    description = fields.Text('Description', required=True, help='Please enter a detailed ' +
                                                                 'description of the topic \n Note: You can also add attachments')
    input_date = fields.Date('Date', readonly=True)
    like_count = fields.Integer('Like count', readonly=True)
    lecturer = fields.Many2One('party.party', 'Lecturer', required=True, select=True, )
    mail = fields.Boolean('Mail to lecturer', states={
        'readonly': Not(Bool(Eval('lecturer'))),
    }, help='Select the lecturer which you want to assign')
    spo_selection = fields.Selection([
        ('SPO3', 'SPO3'),
        ('SPO4', 'SPO4')
    ], 'SPO', help='Please select the SPO for which you will submit the proposal')

    @classmethod
    def default_like_count(cls):
        """Set the default value of the like_count field to 0.
        Because a new topic doesn't has likes"""
        return 0

    @classmethod
    def default_input_date(cls):
        """Set the default value of the input_date fied to the current date"""
        return datetime.date.today()

    @classmethod
    def default_spo_selection(cls):
        """Set the default value of the spo_selection fied to SPO3"""
        return 'SPO3'

    @classmethod
    def default_project_study_spo3(cls):
        """Set the default value of the project_study_spo3 fied to None.
        This is necessary because this field is required  and doesn't can be undefined"""
        return 'None'

    @classmethod
    def default_project_study_spo4(cls):
        """Set the default value of the project_study_spo4 fied to None.
        This is necessary because this field is required  and doesn't can be undefined"""
        return 'None'

    @classmethod
    def default_like_state(cls):
        """Set the default value of the state field to false"""
        return 'like'

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

    def _get_like_btn(self):
        return {}

    def get_like_btn(self):
        return {}

    @classmethod
    def __setup__(cls):
        super(Hshn, cls).__setup__()
        """Initialize the like_btn"""
        cls._buttons.update({
            'like_btn': {
            }
            })

    @fields.depends('spo_selection')
    def on_change_spo_selection(self):
        """Change the value of the fields project_study_spo3 and project_study_spo4 to ''
        and None depending on which SPO was selectet in the spo_selection field.
        This is necessary for the required fields logic"""
        if self.spo_selection == 'SPO3':
            self.project_study_spo3 = ''
            self.project_study_spo4 = 'None'
        else:
            self.project_study_spo4 = ''
            self.project_study_spo3 = 'None'

    @classmethod
    @ModelView.button
    def like_btn(cls, records):
        """Defines the logic by clicking on the Button.
        Count up the field like_count by one and save the changes into the database.
        It also insets a row in the table hshn_user to save which user liked which topic.
        This will be needed for deactivating the like button and activation the dislike button"""

        pool = Pool()
        model_hshn = pool.get('hshn.hshn')

        # get the current user ID
        user_id = Transaction().user

        model_user = pool.get('hshn.user')

        for row in records:

            # check if user already liked the topic
            user_list = model_user.search([('create_uid', '=', user_id)])

            for user in user_list:
                if user.hshn_id is not None:
                    if row.id is user.hshn_id.id:
                        # topic already liked
                        return

            # save the liked topic to the user
            values2 = [{'id':user_id, 'hshn_id':row.id}]
            model_user.create(values2)

            # count up the likes
            if row.like_count is None:
                row.like_count = 1
            else:
                row.like_count += 1

        # Save the updatet record
        model_hshn.save(records)

        return 'reload'


    @classmethod
    def validate(cls, records_mail):
        """Check before saving if the field mail is selected(True) and send in this case the entered
        values via mail to the lecturer.
        The email will be send to all email addresses which are saved for the lecturer in
        party.contact_mechanism"""
        super(Hshn, cls)

        pool = Pool()
        model = pool.get('party.contact_mechanism')
        try:
            server = get_smtp_server()
        except :
            pass

        # get the record
        row = records_mail

        # Read in the mail content
        mail_content = {}
        file = open('../trytond/modules/hshn/mail.txt')
        for line in file:
            try:
                name, var = line.partition('=')
            except ValueError:
                continue
            mail_content[name.strip()] = var

        return
        # send a mail
        if row.mail is True:

            # set the spo
            if row.spo_selection == 'SPO3':
                project_study = row.project_study_spo3
            else:
                project_study = row.project_study_spo4

            # get the party of the selected lecturer
            records_contact = model.search([('party', '=', row.lecturer)])

            # send a mail to each mail address which is saved for the lecturer
            for row2 in records_contact:
                if row2.type == 'email':
                    try:
                        server.sendmail(mail_content['mail_address'], row2.value, mail_content['mail_message1'] +
                            str(row.lecturer.name) +
                            mail_content['mail_message2'] +
                            '\n'+cls.topic.string+': ' + str(row.topic) + '\n'+cls.description.string+': ' +
                            str(row.description) + '\n' + str(row.spo_selection) + mail_content['mail_message3'] +
                            str(project_study))
                    except:
                        pass

        # set mail to false
        row.mail = False
class Service(Workflow, ModelSQL, ModelView):
    'Service'
    __name__ = 'service.service'
    __history = True
    company = fields.Many2One(
        'company.company',
        'Company',
        required=True,
        readonly=True,
        select=True,
        domain=[
            ('id', If(Eval('context', {}).contains('company'), '=',
                      '!='), Eval('context', {}).get('company', -1)),
        ],
        depends=_DEPENDS)
    party = fields.Many2One('party.party',
                            'Party',
                            states=_STATES,
                            required=True)
    number_service = fields.Char('No. Comprobante', readonly=True)
    type = fields.Selection(_TYPE,
                            'Type',
                            select=True,
                            states={
                                'readonly':
                                ((Eval('state') == 'delivered')
                                 | Eval('context', {}).get('type')),
                            })

    total = fields.Function(
        fields.Numeric('Total',
                       states={
                           'invisible': Eval('type') == 'home_service',
                       }), 'get_amount')

    entry_date = fields.Date('Entry Date',
                             states=_STATES,
                             domain=[('entry_date', '<',
                                      Eval('delivery_date', None))],
                             depends=['delivery_date'])
    delivery_date = fields.Date('Estimated Delivery Date',
                                states=_STATES,
                                domain=[('delivery_date', '>',
                                         Eval('entry_date', None))],
                                depends=['entry_date'])
    technical = fields.Many2One('company.employee',
                                'Technical',
                                states=_STATES)
    garanty = fields.Boolean('Garanty', help="Income Garanty", states=_STATES)
    new = fields.Boolean('New',
                         states={
                             'invisible': ~Eval('garanty', True),
                             'readonly': Eval('state') == 'delivered',
                         })
    lined = fields.Boolean('Lined',
                           states={
                               'invisible': ~Eval('garanty', True),
                               'readonly': Eval('state') == 'delivered',
                           })
    beaten = fields.Boolean('Beaten',
                            states={
                                'invisible': ~Eval('garanty', True),
                                'readonly': Eval('state') == 'delivered',
                            })
    broken = fields.Boolean('Broken',
                            states={
                                'invisible': ~Eval('garanty', True),
                                'readonly': Eval('state') == 'delivered',
                            })
    stained = fields.Boolean('Stained',
                             states={
                                 'invisible': ~Eval('garanty', True),
                                 'readonly': Eval('state') == 'delivered',
                             })
    invoice_date = fields.Date('Invoice Date',
                               states={
                                   'invisible': ~Eval('garanty', True),
                                   'readonly': Eval('state') == 'delivered',
                               })
    invoice_number = fields.Char('Invoice number',
                                 states={
                                     'invisible': ~Eval('garanty', True),
                                     'readonly': Eval('state') == 'delivered',
                                 })
    case_number = fields.Char('Case number',
                              states={
                                  'invisible': ~Eval('garanty', True),
                                  'readonly': Eval('state') == 'delivered',
                              })
    send_date = fields.Date('Send Date',
                            states={
                                'invisible': ~Eval('garanty', True),
                                'readonly': Eval('state') == 'delivered',
                            })
    remission = fields.Char('No. guide remission',
                            states={
                                'invisible': ~Eval('garanty', True),
                                'readonly': Eval('state') == 'delivered',
                            })
    transport = fields.Char('Transport',
                            states={
                                'invisible': ~Eval('garanty', True),
                                'readonly': Eval('state') == 'delivered',
                            })
    photo = fields.Binary('Foto', states=_STATES)
    state = fields.Selection([('pending', 'Pending'), ('review', 'In Review'),
                              ('ready', 'Ready'),
                              ('without', 'Without Solution'),
                              ('warranty', 'Warranty not cover'),
                              ('delivered', 'Delivered')],
                             'State',
                             readonly=True)
    lines = fields.One2Many('service.service.line',
                            'service',
                            'Lines',
                            states=_STATES)

    accessories = fields.Text('Accessories',
                              states={
                                  'readonly': Eval('accessories') != '',
                              })
    observations = fields.Text('Observations', states=_STATES)
    history_lines = fields.One2Many('service.service.history_lines', 'service',
                                    'Lines')
    total_home_service = fields.Numeric('Total',
                                        states={
                                            'invisible':
                                            Eval('type') == 'service',
                                        })

    detail = fields.Text('Repair Detail',
                         states={
                             'invisible': Eval('state') != 'delivered',
                             'readonly': Eval('detail') != '',
                         })
    state_date = fields.Function(fields.Char('State Date'), 'get_state_date')

    equipo = fields.Char('Equipo')
    marca = fields.Char('Marca')
    modelo = fields.Char('Modelo')

    direccion = fields.Char(u'Dirección',
                            states={
                                'invisible': ~Eval('party'),
                            })
    telefono = fields.Char(u'Teléfono', states={
        'invisible': ~Eval('party'),
    })
    correo = fields.Char(u'Correo Electrónico',
                         states={
                             'invisible': ~Eval('party'),
                         })

    @classmethod
    def __setup__(cls):
        super(Service, cls).__setup__()
        cls.__rpc__['getTechnicalService'] = RPC(check_access=False,
                                                 readonly=False)

        cls._error_messages.update({
            'modify_invoice': ('You can not modify service "%s".'),
            'delete_cancel': ('You can not delete service "%s".'),
        })

        cls._transitions |= set((
            ('pending', 'review'),
            ('review', 'ready'),
            ('review', 'without'),
            ('review', 'warranty'),
            ('ready', 'delivered'),
            ('without', 'delivered'),
            ('warranty', 'delivered'),
        ))

        cls._buttons.update({
            'review': {
                'invisible': Eval('state') != ('pending')
            },
            'ready': {
                'invisible':
                Eval('state').in_(['pending', 'ready', 'without', 'delivered'])
            },
            'without': {
                'invisible':
                Eval('state').in_(['pending', 'ready', 'without', 'delivered'])
            },
            'warranty': {
                'invisible':
                ~Eval('garanty', True) | (Eval('state').in_(
                    ['pending', 'ready', 'without', 'delivered']))
            },
            'delivered': {
                'invisible':
                Eval('state').in_(['review', 'pending', 'delivered'])
            },
        })

    @fields.depends('invoice_date', 'garanty')
    def on_change_invoice_date(self):
        res = {}
        Date = Pool().get('ir.date')
        if self.garanty != None:
            year = Date.today() - datetime.timedelta(days=365)
            if self.invoice_date < year:
                res['invoice_date'] = self.invoice_date
                self.raise_user_error(
                    u'Está seguro de la fecha de ingreso: "%s"'
                    u'tiene mas de un año de garantia', (self.invoice_date))
        else:
            res['invoice_date'] = self.invoice_date

        return res

    @fields.depends('party')
    def on_change_party(self):
        res = {}
        if self.party:
            if self.party.addresses[0]:
                res['direccion'] = self.party.addresses[0].street
            else:
                res['direccion'] = ""
            if self.party.phone:
                res['telefono'] = self.party.phone
            elif self.party.mobile:
                res['telefono'] = self.party.mobile
            else:
                res['telefono'] = ""
            if self.party.email:
                res['correo'] = self.party.email
            else:
                res['correo'] = ""
        else:
            res['direccion'] = ""
            res['telefono'] = ""
            res['correo'] = ""

        return res

    @fields.depends('lines')
    def on_change_lines(self):
        res = {}
        if self.lines:
            for line in self.lines:
                if line.product:
                    res['equipo'] = line.periferic.name
                else:
                    res['equipo'] = ""

                if line.trademark:
                    res['marca'] = line.trademark.name
                else:
                    res['marca'] = ""

                if line.model:
                    res['modelo'] = line.model
                else:
                    res['modelo'] = ""
        return res

    @classmethod
    def get_state_date(cls, services, names):
        pool = Pool()
        Date = pool.get('ir.date')
        date_now = Date.today()
        result = {n: {s.id: '' for s in services} for n in names}
        for name in names:
            for service in services:
                if (service.delivery_date < date_now) and (service.state !=
                                                           'delivered'):
                    result[name][service.id] = 'vencida'
                elif (service.delivery_date
                      == date_now) and (service.state != 'delivered'):
                    result[name][service.id] = 'vence_hoy'
                else:
                    result[name][service.id] = ''
        return result

    @staticmethod
    def default_entry_date():
        Date = Pool().get('ir.date')
        return Date.today()

    @staticmethod
    def default_accessories():
        return ''

    @staticmethod
    def default_detail():
        return ''

    @staticmethod
    def default_delivery_date():
        Date = Pool().get('ir.date')
        return Date.today() + datetime.timedelta(days=1)

    @staticmethod
    def default_state():
        return 'pending'

    @staticmethod
    def default_type():
        return Transaction().context.get('type', 'service')

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

    @classmethod
    def get_amount(cls, services, names):
        amount = Decimal(0.0)
        total = dict((i.id, _ZERO) for i in services)
        for service in services:
            for line in service.lines:
                if line.reference_amount:
                    amount += line.reference_amount
            total[service.id] = amount

        result = {
            'total': total,
        }
        for key in result.keys():
            if key not in names:
                del result[key]
        return result

    @fields.depends('total', 'total_home_service')
    def on_change_total_home_service(self):
        res = {}

        if self.total_home_service:
            res['total'] = self.total_home_service
        else:
            res['total'] = Decimal(0.0)

        return res

    def set_number(self):
        pool = Pool()
        Period = pool.get('account.period')
        Sequence = pool.get('ir.sequence.strict')
        Date = pool.get('ir.date')

        if self.number_service:
            return

        test_state = True

        accounting_date = self.entry_date
        period_id = Period.find(self.company.id,
                                date=accounting_date,
                                test_state=test_state)
        period = Period(period_id)
        sequence = period.get_service_sequence(self.type)
        if not sequence:
            self.raise_user_error('no_withholding_sequence', {
                'withholding': self.rec_name,
                'period': period.rec_name,
            })
        with Transaction().set_context(date=self.entry_date or Date.today()):
            number = Sequence.get_id(sequence.id)
            vals = {'number_service': number}
            if (not self.entry_date and self.type in ('service')):
                vals['entry_date'] = Transaction().context['date']
        self.write([self], vals)

    @classmethod
    def check_modify(cls, services):
        for service in services:
            if (service.state in ('delivered')):
                cls.raise_user_error('modify_invoice',
                                     (service.number_service, ))

    @classmethod
    def delete(cls, services):
        cls.check_modify(services)
        for service in services:
            if (service.state in ('review', 'ready', 'without', 'warranty',
                                  'delivered')):
                cls.raise_user_error('delete_cancel',
                                     (service.number_service, ))
        super(Service, cls).delete(services)

    @classmethod
    def copy(cls, services, default=None):
        if default is None:
            default = {}
        default = default.copy()
        default['state'] = 'pending'
        default['number_service'] = None
        default['type'] = 'service'
        return super(Service, cls).copy(services, default=default)

    @classmethod
    @ModelView.button
    @Workflow.transition('review')
    def review(cls, services):
        for service in services:
            pool = Pool()
            Contact = pool.get('party.contact_mechanism')
            Address = pool.get('party.address')

            if service.party:
                if service.party.addresses[0].street:
                    addresses = service.party.addresses[0]
                    addresses.street = service.direccion
                    addresses.save()
                else:
                    if service.direccion:
                        party = service.party
                        party.address = Address.create([{
                            'street':
                            service.direccion,
                            'party':
                            service.party.id
                        }])
                        party.save()
                    else:
                        service.raise_user_error(
                            u'Actualice la dirección del cliente')

                if service.party.email:
                    emails = Contact.search([('party', '=', service.party),
                                             ('type', '=', 'email')])
                    for email in emails:
                        email.value = service.correo
                        email.save()
                else:
                    if service.correo:
                        contact_mechanisms = []
                        contact_mechanisms.append({
                            'type': 'email',
                            'value': service.correo,
                            'party': service.party.id
                        })
                        contact_mechanisms = Contact.create(contact_mechanisms)
                    else:
                        service.raise_user_error(
                            'Actualice el correo del cliente')

                if service.party.phone:
                    phones = Contact.search([('party', '=', service.party),
                                             ('type', '=', 'phone')])
                    for phone in phones:
                        phone.value = service.telefono
                        phone.save()
                else:
                    if service.telefono:
                        contact_mechanisms = []
                        contact_mechanisms.append({
                            'type': 'phone',
                            'value': service.telefono,
                            'party': service.party.id,
                        })
                        contact_mechanisms = Contact.create(contact_mechanisms)
                    else:
                        service.raise_user_error(
                            u'Actualice el teléfono del cliente')

            service.raise_user_warning(
                'datos%s' % service.id,
                u'Está seguro que los datos del cliente:\n "%s"'
                u'\nCorreo: "%s" y Teléfono: "%s", \nestán actualizados.',
                (service.party.name, service.correo, service.telefono))

            service.set_number()

        cls.write([i for i in services if i.state != 'review'], {
            'state': 'review',
        })

    @classmethod
    @ModelView.button
    @Workflow.transition('ready')
    def ready(cls, services):
        cls.write([i for i in services if i.state != 'ready'], {
            'state': 'ready',
        })

    @classmethod
    @ModelView.button
    @Workflow.transition('without')
    def without(cls, services):
        cls.write([i for i in services if i.state != 'without'], {
            'state': 'without',
        })

    @classmethod
    @ModelView.button
    @Workflow.transition('warranty')
    def warranty(cls, services):
        cls.write([i for i in services if i.state != 'warranty'], {
            'state': 'warranty',
        })

    @classmethod
    @ModelView.button
    @Workflow.transition('delivered')
    def delivered(cls, services):
        cls.write([i for i in services if i.state != 'delivered'], {
            'state': 'delivered',
        })

    @classmethod
    def getTechnicalService(cls, identificacion):
        pool = Pool()
        Service = pool.get('service.service')
        Party = pool.get('party.party')
        parties = Party.search([('vat_number', '=', identificacion)])
        for p in parties:
            party = p
        services = Service.search([('party', '=', party)])
        all_services = []
        if services:
            for service in services:
                lines_services = {}
                for line in service.lines:
                    lines_services[0] = str(service.entry_date)
                    lines_services[1] = str(service.delivery_date)
                    lines_services[2] = service.number_service
                    lines_services[3] = line.periferic.name
                    lines_services[4] = line.trademark.name
                    lines_services[5] = line.model
                    lines_services[6] = line.failure
                    lines_services[7] = str(line.reference_amount)
                    lines_services[8] = line.technical.party.name
                    lines_services[9] = service.state
                    lines_services[10] = service.accessories
                    lines_services[11] = service.detail
                    all_services.append(lines_services)
            return all_services
        else:
            return []
Exemple #21
0
class OpenChartAccountStart(ModelView):
    'Open Chart of Accounts'
    __name__ = 'analytic_account.open_chart.start'
    start_date = fields.Date('Start Date')
    end_date = fields.Date('End Date')
class BalanceProductFixedAssets(ModelSQL, ModelView):
    "Turnover and Balances Fixed Assets"
    _name = "ekd.balances.fixed_assets"
    _description =__doc__
    _inherits = {'ekd.balances.assets': 'assets'}

    assets = fields.Many2One('ekd.balances.assets', 'Assets', required=True,
            ondelete='CASCADE')

    date_income = fields.Date('Date Income', required=True)
    date_expense = fields.Date('Date Expense')
    period_income = fields.Many2One('ekd.period', 'Period Income', required=True, select=2, 
                domain=[
                    ('company','=',Eval('company'))
                ])
    period_expense = fields.Many2One('ekd.period', 'Period Expense', select=2, 
                domain=[
                    ('company','=',Eval('company'))
                ])
    initial_cost = fields.Numeric('Initial cost', digits=(16, Eval('currency_digits', 2)))
    replacement = fields.Numeric('Replacement value', digits=(16, Eval('currency_digits', 2)))
    residual = fields.Numeric('Residual value', digits=(16, Eval('currency_digits', 2)))
    deprecation = fields.Many2Many("ekd.balances.fixed_assets.deprecation", 'fixed_assets', 'move_line', 'Deprecation')

    state = fields.Selection([
                ('draft','Draft'),
                ('open','Open'),
                ('done','Closed'),
                ('deleted','Deleted')
                ], 'State', required=True)
    deleted = fields.Boolean('Flag Deleting')

    def __init__(self):
        super(BalanceProductFixedAssets, self).__init__()

    def default_state(self):
        return Transaction().context.get('state') or 'draft'

    def default_company(self):
        return Transaction().context.get('company') or False

    def default_currency_digits(self):
        return 2

    def get_rec_name(self, ids, name):
        if not ids:
            return {}
        res = {}
        for balance in self.browse(ids):
            res[balance.id] = balance.product.name
        return res

    def get_currency_digits(self, ids, name):
        res = {}.fromkeys(ids, 2)
        company_id = Transaction().context.get('company')
        company = self.pool.get('company.company').browse(company_id)
        for line in self.browse(ids):
            if line.account.currency:
                res[line.id] = line.account.currency.currency_digits
            elif company.currency:
                res[line.id] = company.currency.currency_digits
Exemple #23
0
class Mandate(Workflow, ModelSQL, ModelView):
    'SEPA Mandate'
    __name__ = 'account.payment.sepa.mandate'
    party = fields.Many2One('party.party',
                            'Party',
                            required=True,
                            select=True,
                            states={
                                'readonly':
                                Eval('state').in_(
                                    ['requested', 'validated', 'canceled']),
                            },
                            depends=['state'])
    account_number = fields.Many2One(
        'bank.account.number',
        'Account Number',
        ondelete='RESTRICT',
        states={
            'readonly': Eval('state').in_(['validated', 'canceled']),
            'required': Eval('state') == 'validated',
        },
        domain=[
            ('type', '=', 'iban'),
            ('account.owners', '=', Eval('party')),
        ],
        depends=['state', 'party'])
    identification = fields.Char('Identification',
                                 size=35,
                                 states={
                                     'readonly':
                                     Eval('identification_readonly', True),
                                     'required':
                                     Eval('state') == 'validated',
                                 },
                                 depends=['state', 'identification_readonly'])
    identification_readonly = fields.Function(
        fields.Boolean('Identification Readonly'),
        'get_identification_readonly')
    company = fields.Many2One(
        'company.company',
        'Company',
        required=True,
        select=True,
        domain=[
            ('id', If(Eval('context', {}).contains('company'), '=',
                      '!='), Eval('context', {}).get('company', -1)),
        ],
        states={
            'readonly': Eval('state') != 'draft',
        },
        depends=['state'])
    type = fields.Selection([
        ('recurrent', 'Recurrent'),
        ('one-off', 'One-off'),
    ],
                            'Type',
                            states={
                                'readonly':
                                Eval('state').in_(['validated', 'canceled']),
                            },
                            depends=['state'])
    sequence_type_rcur = fields.Boolean("Always use RCUR",
                                        states={
                                            'invisible':
                                            Eval('type') == 'one-off',
                                        },
                                        depends=['type'])
    scheme = fields.Selection([
        ('CORE', 'Core'),
        ('B2B', 'Business to Business'),
    ],
                              'Scheme',
                              required=True,
                              states={
                                  'readonly':
                                  Eval('state').in_(['validated', 'canceled']),
                              },
                              depends=['state'])
    scheme_string = scheme.translated('scheme')
    signature_date = fields.Date('Signature Date',
                                 states={
                                     'readonly':
                                     Eval('state').in_(
                                         ['validated', 'canceled']),
                                     'required':
                                     Eval('state') == 'validated',
                                 },
                                 depends=['state'])
    state = fields.Selection([
        ('draft', 'Draft'),
        ('requested', 'Requested'),
        ('validated', 'Validated'),
        ('canceled', 'Canceled'),
    ],
                             'State',
                             readonly=True)
    payments = fields.One2Many('account.payment', 'sepa_mandate', 'Payments')
    has_payments = fields.Function(fields.Boolean('Has Payments'),
                                   'has_payments')

    @classmethod
    def __setup__(cls):
        super(Mandate, cls).__setup__()
        cls._transitions |= set((
            ('draft', 'requested'),
            ('requested', 'validated'),
            ('validated', 'canceled'),
            ('requested', 'canceled'),
            ('requested', 'draft'),
        ))
        cls._buttons.update({
            'cancel': {
                'invisible': ~Eval('state').in_(['requested', 'validated']),
                'depends': ['state'],
            },
            'draft': {
                'invisible': Eval('state') != 'requested',
                'depends': ['state'],
            },
            'request': {
                'invisible': Eval('state') != 'draft',
                'depends': ['state'],
            },
            'validate_mandate': {
                'invisible': Eval('state') != 'requested',
                'depends': ['state'],
            },
        })
        t = cls.__table__()
        cls._sql_constraints = [
            ('identification_unique', Unique(t, t.company, t.identification),
             'account_payment_sepa.msg_mandate_unique_id'),
        ]

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

    @staticmethod
    def default_type():
        return 'recurrent'

    @classmethod
    def default_sequence_type_rcur(cls):
        return False

    @staticmethod
    def default_scheme():
        return 'CORE'

    @staticmethod
    def default_state():
        return 'draft'

    @staticmethod
    def default_identification_readonly():
        pool = Pool()
        Configuration = pool.get('account.configuration')
        config = Configuration(1)
        return bool(config.sepa_mandate_sequence)

    def get_identification_readonly(self, name):
        return bool(self.identification)

    def get_rec_name(self, name):
        if self.identification:
            return self.identification
        return '(%s)' % self.id

    @classmethod
    def search_rec_name(cls, name, clause):
        return [tuple(('identification', )) + tuple(clause[1:])]

    @classmethod
    def create(cls, vlist):
        pool = Pool()
        Sequence = pool.get('ir.sequence')
        Configuration = pool.get('account.configuration')

        config = Configuration(1)
        vlist = [v.copy() for v in vlist]
        for values in vlist:
            if (config.sepa_mandate_sequence
                    and not values.get('identification')):
                values['identification'] = Sequence.get_id(
                    config.sepa_mandate_sequence.id)
            # Prevent raising false unique constraint
            if values.get('identification') == '':
                values['identification'] = None
        return super(Mandate, cls).create(vlist)

    @classmethod
    def write(cls, *args):
        actions = iter(args)
        args = []
        for mandates, values in zip(actions, actions):
            # Prevent raising false unique constraint
            if values.get('identification') == '':
                values = values.copy()
                values['identification'] = None
            args.extend((mandates, values))
        super(Mandate, cls).write(*args)

    @classmethod
    def copy(cls, mandates, default=None):
        if default is None:
            default = {}
        else:
            default = default.copy()
        default.setdefault('payments', [])
        default.setdefault('signature_date', None)
        default.setdefault('identification', None)
        return super(Mandate, cls).copy(mandates, default=default)

    @property
    def is_valid(self):
        if self.state == 'validated':
            if self.type == 'one-off':
                if not self.has_payments:
                    return True
            else:
                return True
        return False

    @property
    def sequence_type(self):
        if self.type == 'one-off':
            return 'OOFF'
        elif not self.sequence_type_rcur and (not self.payments or all(
                not p.sepa_mandate_sequence_type
                for p in self.payments) or all(p.rejected
                                               for p in self.payments)):
            return 'FRST'
        # TODO manage FNAL
        else:
            return 'RCUR'

    @classmethod
    def has_payments(cls, mandates, name):
        pool = Pool()
        Payment = pool.get('account.payment')
        payment = Payment.__table__
        cursor = Transaction().connection.cursor()

        has_payments = dict.fromkeys([m.id for m in mandates], False)
        for sub_ids in grouped_slice(mandates):
            red_sql = reduce_ids(payment.sepa_mandate, sub_ids)
            cursor.execute(*payment.select(payment.sepa_mandate,
                                           Literal(True),
                                           where=red_sql,
                                           group_by=payment.sepa_mandate))
            has_payments.update(cursor.fetchall())

        return {'has_payments': has_payments}

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

    @classmethod
    @ModelView.button
    @Workflow.transition('requested')
    def request(cls, mandates):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('validated')
    def validate_mandate(cls, mandates):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('canceled')
    def cancel(cls, mandates):
        # TODO must be automaticaly canceled 13 months after last collection
        pass

    @classmethod
    def delete(cls, mandates):
        for mandate in mandates:
            if mandate.state not in ('draft', 'canceled'):
                raise AccessError(
                    gettext(
                        'account_payment_sepa'
                        '.msg_mandate_delete_draft_canceled',
                        mandate=mandate.rec_name))
        super(Mandate, cls).delete(mandates)
Exemple #24
0
class CompensationMoveStart(ModelView, BankMixin):
    'Create Compensation Move Start'
    __name__ = 'account.move.compensation_move.start'
    party = fields.Many2One('party.party', 'Party', readonly=True)
    account = fields.Many2One('account.account',
                              'Account',
                              domain=[
                                  'OR', ('type.receivable', '=', True),
                                  ('type.payable', '=', True)
                              ],
                              required=True)
    date = fields.Date('Date')
    maturity_date = fields.Date('Maturity Date')
    description = fields.Char('Description')
    payment_kind = fields.Selection([
        ('both', 'Both'),
        ('payable', 'Payable'),
        ('receivable', 'Receivable'),
    ], 'Payment Kind')
    payment_type = fields.Many2One('account.payment.type',
                                   'Payment Type',
                                   domain=[('kind', '=', Eval('payment_kind'))
                                           ],
                                   depends=['payment_kind'])

    @staticmethod
    def default_date():
        pool = Pool()
        return pool.get('ir.date').today()

    @staticmethod
    def default_maturity_date():
        pool = Pool()
        return pool.get('ir.date').today()

    @classmethod
    def default_get(cls, fields, with_rec_name=True):
        pool = Pool()
        Line = pool.get('account.move.line')
        PaymentType = pool.get('account.payment.type')

        defaults = super(CompensationMoveStart,
                         cls).default_get(fields, with_rec_name)

        party = None
        company = None
        amount = Decimal('0.0')

        lines = Line.browse(Transaction().context.get('active_ids', []))
        for line in lines:
            amount += line.debit - line.credit
            if not party:
                party = line.party
            elif party != line.party:
                raise UserError(
                    gettext('account_bank.different_parties',
                            party=line.party.rec_name,
                            line=line.rec_name))
            if not company:
                company = line.account.company
        if (company and company.currency.is_zero(amount)
                and len(set([x.account for x in lines])) == 1):
            raise UserError(gettext('account_bank.normal_reconcile'))
        if amount > 0:
            defaults['payment_kind'] = 'receivable'
        else:
            defaults['payment_kind'] = 'payable'
        defaults['bank_account'] = None
        if party:
            defaults['party'] = party.id
            if (defaults['payment_kind'] in ['receivable', 'both']
                    and party.customer_payment_type):
                defaults['payment_type'] = party.customer_payment_type.id
            elif (defaults['payment_kind'] in ['payable', 'both']
                  and party.supplier_payment_type):
                defaults['payment_type'] = party.supplier_payment_type.id
            if defaults.get('payment_type'):
                payment_type = PaymentType(defaults['payment_type'])
                defaults['account_bank'] = payment_type.account_bank

                self = cls()
                self.payment_type = payment_type
                self.party = party
                self._get_bank_account()
                defaults['account_bank_from'] = (
                    self.on_change_with_account_bank_from())
                defaults['bank_account'] = (self.bank_account.id
                                            if self.bank_account else None)
            if amount > 0:
                defaults['account'] = (party.account_receivable.id
                                       if party.account_receivable else None)
            else:
                defaults['account'] = (party.account_payable.id
                                       if party.account_payable else None)
        return defaults

    def on_change_with_payment_type(self, name=None):
        pass
Exemple #25
0
class Document(ModelSQL, ModelView):
    "Documents"
    _name='ekd.document'
    _order_name = 'date_document'
    _order=['date_document', 'date_account']
    _description=__doc__

    company = fields.Many2One('company.company', 'Company', readonly=True)
    model = fields.Many2One('ir.model', 'Model', domain=[('model','like','ekd.document%')])
    model_str = fields.Char('Model Name', size=128)
    direction = fields.Selection([
                    ('input','Input'),
                    ('move','Move'),
                    ('internal','Internal'),
                    ('output','Output')
                    ],'Direction document')
    name = fields.Char('Description')
    template = fields.Many2One('ekd.document.template', 'Document Name', help="Template documents", order_field="%(table)s.template %(order)s")
    note = fields.Text('Note document')
    number_our = fields.Char('Number Outgoing', size=32, readonly=True, 
                            states={
                                'invisible': Not(Bool(Eval('number_our')))
                                })
    number_in = fields.Char('Number of incoming', size=32)
    date_document = fields.Date('Date Create')
    date_account = fields.Date('Date Account')
    employee = fields.Many2One('company.employee', 'Employee')
    from_party = fields.Many2One('party.party', 'From partner')
    to_party = fields.Many2One('party.party', 'To partner')
    amount = fields.Numeric('Amount Document', digits=(16, Eval("currency_digits",2)))
    amount_payment = fields.Function(fields.Numeric('Amount Payment', digits=(16, Eval("currency_digits", 2))), 'get_payment_field')
    amount_paid = fields.Function(fields.Numeric('Amount Paid', digits=(16, Eval("currency_digits", 2))), 'get_paid_field')
    currency = fields.Many2One('currency.currency', 'Currency')
    currency_digits = fields.Function(fields.Integer('Currency Digits' , on_change_with=['currency']), 'get_currency_digits')
    document_base = fields.Reference('Document Base', selection='documents_base_get',
                on_change=['document_base', 'lines'])
    lines = fields.One2Many('ekd.document.line.product', 'invoice', 'Lines')
    childs = fields.One2Many('ekd.document','parent', 'Child documents', readonly=True)
    parent = fields.Many2One('ekd.document', 'Parent document')
    state = fields.Selection(_STATES_FULL, 'State', readonly=True)
    stage = fields.Many2One('ekd.document.template.stage', 'Stage', readonly=True)
    journal_work = fields.One2Many('ekd.document.journal_work','document','Journal Change Stages', readonly=True)
    post_date = fields.Date('Date Post')
    active = fields.Boolean('Active', required=True)
    id_1c = fields.Char("ID import from 1C", size=None, select=1)
    deleting = fields.Boolean('Flag Deleting')

    def __init__(self): 
        super(Document, self).__init__()

        self._order.insert(0, ('company','ASC'))
        self._order.insert(0, ('date_document', 'ASC'))
        self._order.insert(0, ('template', 'ASC'))
        self._order.insert(0, ('date_account', 'ASC'))
        self._order.insert(0, ('number_our', 'ASC'))

    def default_state(self):
        return 'draft'

    def default_date_document(self):
        context = Transaction().context
        if context.get('date_document'):
            return context.get('date_document')
        elif context.get('current_date'):
            return context.get('current_date')
        return datetime.datetime.now()

    def default_date_account(self ):
        context = Transaction().context
        if context.get('date_account'):
            return context.get('date_account')
        elif context.get('current_date'):
            return context.get('current_date')
        return datetime.datetime.now()

    def default_from_party(self):
        return Transaction().context.get('from_party')

    def default_to_party(self):
        return Transaction().context.get('to_party')

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

    def default_child(self):
        return Transaction().context.get('child')

    def default_amount(self):
        return Transaction().context.get('amount')

    def default_name(self):
        return Transaction().context.get('name')

    def default_note(self):
        return Transaction().context.get('note')

    def default_currency(self):
        company_obj = self.pool.get('company.company')
        currency_obj = self.pool.get('currency.currency')
        context = Transaction().context
        if context.get('company'):
            company = company_obj.browse(context['company'])
            return company.currency.id
        return False

    def default_currency_digits(self):
        company_obj = self.pool.get('company.company')
        context = Transaction().context
        if context.get('company'):
            company = company_obj.browse(context['company'])
            return company.currency.digits
        return 2

    def default_active(self):
        return True

    def documents_base_dict_get(self, model=False):
        if not model:
            model = self._name
        dictions_obj = self.pool.get('ir.dictions')
        res = []
        diction_ids = dictions_obj.search( [
                                ('model', 'like', 'ekd.document.head%'),
                                ('pole', '=', 'document_base'),
                                ])
        if diction_ids:
            for diction in dictions_obj.browse( diction_ids):
                res.append([diction.key, diction.value])
        return res

    def documents_base_get(self):
        return self.documents_base_dict_get(self._name)

    def get_rec_name(self, ids, name):
        res={}

        for document in self.browse(ids):
            if document.template:
                if document.template.shortcut:
                        TemplateName = document.template.shortcut
                else:
                        TemplateName = document.template.name

            if document.number_our:
                DocumentNumber = document.number_our
            elif document.number_in:
                DocumentNumber = document.number_in
            else:
                DocumentNumber = u'без номера'

            if document.date_document:
                DocumentDate = document.date_document.strftime('%d.%m.%Y')
            else:
                DocumentDate = u'без даты'

            if document.template:
                 res[document.id] = TemplateName+ u' № '+DocumentNumber+u' от '+DocumentDate
            else:
                 res[document.id] = u'Без имени № '+ DocumentNumber+u' от '+DocumentDate

        return res

    def get_payment_field(self, ids, name):
        res = {}
        cursor = Transaction().cursor
        for id in ids:
            res.setdefault(id, Decimal('0.0'))
        cursor.execute("SELECT doc_base, SUM(amount_payment) "\
                        "FROM ekd_document_line_payment "\
                        "WHERE doc_base in ("+','.join(map(str,ids))+") and state in ('wait0', 'wait1', 'payment') "\
                        "GROUP BY doc_base")
        for id, sum in cursor.fetchall():
            # SQLite uses float for SUM
            if not isinstance(sum, Decimal):
                sum = Decimal(str(sum))
            res[id] = sum
        return res

    def get_paid_field(self, ids, name):
        res = {}
        cursor = Transaction().cursor
        for id in ids:
            res.setdefault(id, Decimal('0.0'))
        cursor.execute("SELECT doc_base, SUM(amount_payment) "\
                        "FROM ekd_document_line_payment "\
                        "WHERE doc_base in ("+','.join(map(str,ids))+") and state='done' "\
                        "GROUP BY doc_base")
        for id, sum in cursor.fetchall():
            # SQLite uses float for SUM
            if not isinstance(sum, Decimal):
                sum = Decimal(str(sum))
            res[id] = sum
        return res

    def get_currency_digits(self, ids, name):
        assert name in ('currency_digits'), 'Invalid name %s' % (name)
        res={}.fromkeys(ids, 2)
        for document in self.browse(ids):
            if document.currency:
                res[document.id] = document.currency.digits
        return res

    def on_change_document_base(self, values):
        return values

    def button_draft(self, ids):
        for document in self.browse(ids):
            if document.template.model:
                self.pool.get(document.template.model).button_draft(ids)

    def button_cancel(self, ids):
        for document in self.browse(ids):
            if document.template.model:
                self.pool.get(document.template.model).button_cancel(ids)

    def button_restore(self, ids):
        for document in self.browse(ids):
            if document.template.model:
                self.pool.get(document.template.model).button_restore(ids)

    def button_issued(self, ids):
        for document in self.browse(idst):
            if document.template.model:
                self.pool.get(document.template.model).button_issued(ids)

    def button_on_payment(self, ids):
        for document in self.browse(idst):
            if document.template.model:
                self.pool.get(document.template.model).button_payment(ids)

    def button_pay(self, ids):
        for document in self.browse(idst):
            if document.template.model:
                self.pool.get(document.template.model).button_pay(ids)

    def button_confirmed(self, ids):
        for document in self.browse(idst):
            if document.template.model:
                self.pool.get(document.template.model).button_confirmed(ids)
Exemple #26
0
class HrPayslip(Workflow, ModelSQL, ModelView):
    '''Pay Slip'''

    __name__ = 'hr.payslip'

    employee = fields.Many2One(
        'company.employee',
        'Employee',
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'])
    salary_code = fields.Char(
        'Salary Code',
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'])
    structure = fields.Many2One(
        'salary.structure',
        'Structure',
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'])
    contract = fields.Many2One(
        'hr.contract',
        'Salary Details',
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'])
    code = fields.Integer('Code',
                          states={'readonly': ~Eval('state').in_(['draft'])},
                          depends=['state'])
    name = fields.Char('name',
                       states={'readonly': ~Eval('state').in_(['draft'])},
                       depends=['state'])
    number = fields.Char('Reference',
                         states={'readonly': ~Eval('state').in_(['draft'])},
                         depends=['state'])
    date_from = fields.Date('Date From',
                            states={'readonly': ~Eval('state').in_(['draft'])},
                            depends=['state'])
    date_to = fields.Date('Date To',
                          states={'readonly': ~Eval('state').in_(['draft'])},
                          depends=['state'])
    state = fields.Selection([('draft', 'Draft'), ('verify', 'Waiting'),
                              ('done', 'Done'), ('cancel', 'Rejected'),
                              ('confirm', 'Successful')],
                             'Status',
                             readonly=True)
    lines = fields.One2Many('hr.payslip.line',
                            'slip',
                            string='Payslip Lines',
                            states={'readonly': ~Eval('state').in_(['draft'])},
                            depends=['state'])
    pay_and_allowance = fields.One2Many(
        'hr.payslip.line',
        'slip',
        string='Payslip Lines',
        domain=[('category.code', 'in', ['Basic', 'Allowance', 'Gross',
                                         'Net'])],
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'])
    deductions = fields.One2Many(
        'hr.payslip.line',
        'slip',
        string='Payslip Lines',
        domain=[('category.code', 'in', ['Deduction'])],
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'])
    details_by_salary_rule_category = fields.One2Many(
        'hr.payslip.line',
        'slip',
        string='Details by Salary Rule',
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'])
    payslip_run = fields.Many2One(
        'hr.payslip.run',
        'Payslip Batches',
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'])  #batches in payslip.run
    bank_name = fields.Char('Bank Name',
                            states={'readonly': ~Eval('state').in_(['draft'])},
                            depends=['state'],
                            readonly=True)
    ifsc = fields.Char('IFSC Code',
                       states={'readonly': ~Eval('state').in_(['draft'])},
                       depends=['state'],
                       readonly=True)
    bank_address = fields.Text(
        'Bank Address',
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'],
        readonly=True)
    account_no = fields.Integer(
        'Account Number',
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'],
        readonly=True)
    bank_status = fields.Char(
        'Bank Account Status',
        states={'readonly': ~Eval('state').in_(['draft'])},
        depends=['state'],
        readonly=True)

    @fields.depends('employee')
    def on_change_employee(self):
        self.salary_code = self.employee.salary_code
        self.number = self
        self.bank_name = self.employee.bank_name.bank
        self.bank_address = self.employee.bank_address
        self.account_no = self.employee.account_no
        self.bank_status = self.employee.bank_status
        start_date = datetime.date.today()
        contract = Pool().get('hr.contract')
        contracts = contract.search([('employee', '=', self.employee),
                                     ('date_start', '<=', start_date),
                                     ('date_end', '>=', start_date)])

    @property
    def pay_and_allowances(self):
        allowances_lines = []
        if self.lines:
            for line in self.lines:
                if line.category.code in ['BASIC', 'ALW']:
                    allowances_lines.append(line)
        return allowances_lines

    @property
    def deductions(self):
        deductions_lines = []
        if self.lines:
            for line in self.lines:
                if line.category.code in ['DED']:
                    deductions_lines.append(line)
        return deductions_lines

    @staticmethod
    def default_state():
        return 'draft'

    @classmethod
    def __setup__(cls):
        super().__setup__()
        cls._order = [
            ('salary_code', 'ASC'),
        ]
        cls._transitions |= set((
            ('draft', 'verify'),
            ('verify', 'confirm'),
            ('confirm', 'done'),
            ('confirm', 'cancel'),
            ('verify', 'cancel'),
        ))
        cls._buttons.update({
            'verify': {
                'invisible': ~Eval('state').in_(['draft']),
                'depends': ['state'],
            },
            'cancel': {
                'invisible': ~Eval('state').in_(['confirm', 'verify']),
                'depends': ['state'],
            },
            'confirm': {
                'invisible': ~Eval('state').in_(['verify']),
                'depends': ['state'],
            },
            'done': {
                'invisible': ~Eval('state').in_(['confirm']),
                'depends': ['state'],
            },
        })

    @classmethod
    @ModelView.button
    @Workflow.transition('verify')
    def verify(cls, records):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('cancel')
    def cancel(cls, records):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('confirm')
    def confirm(cls, records):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('done')
    def done(cls, records):
        pass

    def calculate_rules(self):
        structure = self.structure
        PayslipLine = Pool().get('hr.payslip.line')

        for rule in structure.rules:
            condition = rule.check(
                self,
                self.employee,
                self.contract,
            )
            if not condition:
                continue
            amount = rule.calculate(
                self,
                self.employee,
                self.contract,
            )
            vals = {
                'name': rule.name,
                'code': rule.code,
                'slip': self.id,
                'salary_rule': rule.id,
                'category': rule.category.id,
                'employee': self.employee.id,
                'amount': amount,
                'total': amount,
                'priority': rule.priority
            }
            print(vals)
            line = PayslipLine.create([vals])

    @classmethod
    #@ModelView.button_action('payroll.payslip_line_view_tree')
    def _compute_salary(cls, records):
        pass

    @classmethod
    def default_date_from(cls):
        start_date = datetime.date.today().replace(day=1)
        # y=datetime.datetime(x.year,x.month,1)
        return start_date

    @classmethod
    def default_date_to(cls):
        today = datetime.date.today().month
        end_date = (datetime.date.today().replace(month=today + 1, day=1) -
                    datetime.timedelta(days=1))
        return end_date

    @classmethod
    def default_payslip_month_year(cls):
        month = datetime.date.today().strftime("%B")
        year = datetime.date.today().year
        date_ = month + ", " + str(year)
        return date_

    @classmethod
    def validate(cls, records):
        super(HrPayslip, cls).validate(records)
        for record in records:
            if not record.salary_code:
                cls.raise_user_error('Enter Salary Code')
Exemple #27
0
class DateRequired(ModelSQL):
    'Date Required'
    __name__ = 'test.date_required'
    date = fields.Date(string='Date', help='Test date', required=True)
Exemple #28
0
class ShipmentDrop(Workflow, ModelSQL, ModelView):
    "Drop Shipment"
    __name__ = 'stock.shipment.drop'

    effective_date = fields.Date('Effective Date', readonly=True)
    planned_date = fields.Date('Planned Date',
                               states={
                                   'readonly': Eval('state') != 'draft',
                               },
                               depends=['state'])
    company = fields.Many2One(
        'company.company',
        'Company',
        required=True,
        states={
            'readonly': Eval('state') != 'draft',
        },
        domain=[
            ('id', If(Eval('context', {}).contains('company'), '=',
                      '!='), Eval('context', {}).get('company', -1)),
        ],
        depends=['state'])
    reference = fields.Char('Reference',
                            select=1,
                            states={
                                'readonly': Eval('state') != 'draft',
                            },
                            depends=['state'])
    supplier = fields.Many2One('party.party',
                               'Supplier',
                               required=True,
                               states={
                                   'readonly': (((Eval('state') != 'draft')
                                                 | Eval('supplier_moves', [0]))
                                                & Eval('supplier')),
                               },
                               depends=['state', 'supplier'])
    contact_address = fields.Many2One('party.address',
                                      'Contact Address',
                                      states={
                                          'readonly': Eval('state') != 'draft',
                                      },
                                      domain=[('party', '=', Eval('supplier'))
                                              ],
                                      depends=['state', 'supplier'])
    customer = fields.Many2One('party.party',
                               'Customer',
                               required=True,
                               states={
                                   'readonly': (((Eval('state') != 'draft')
                                                 | Eval('customer_moves', [0]))
                                                & Eval('customer')),
                               },
                               depends=['state'])
    delivery_address = fields.Many2One('party.address',
                                       'Delivery Address',
                                       required=True,
                                       states={
                                           'readonly':
                                           Eval('state') != 'draft',
                                       },
                                       domain=[('party', '=', Eval('customer'))
                                               ],
                                       depends=['state', 'customer'])
    moves = fields.One2Many('stock.move',
                            'shipment',
                            'Moves',
                            domain=[
                                ('company', '=', Eval('company')),
                                [
                                    'OR',
                                    [
                                        ('from_location.type', '=',
                                         'supplier'),
                                        ('to_location.type', '=', 'drop'),
                                    ],
                                    [
                                        ('from_location.type', '=', 'drop'),
                                        ('to_location.type', '=', 'customer'),
                                    ],
                                ],
                            ],
                            depends=['company'],
                            readonly=True)
    supplier_moves = fields.One2Many(
        'stock.move',
        'shipment',
        'Supplier Moves',
        filter=[('to_location.type', '=', 'drop')],
        states={
            'readonly': Eval('state').in_(['shipped', 'done', 'cancel']),
        },
        depends=['state', 'supplier'])
    customer_moves = fields.One2Many('stock.move',
                                     'shipment',
                                     'Customer Moves',
                                     filter=[('from_location.type', '=',
                                              'drop')],
                                     states={
                                         'readonly':
                                         Eval('state') != 'shipped',
                                     },
                                     depends=['state', 'customer'])
    code = fields.Char('Code', select=1, readonly=True)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('waiting', 'Waiting'),
        ('shipped', 'Shipped'),
        ('done', 'Done'),
        ('cancel', 'Canceled'),
    ],
                             'State',
                             readonly=True)

    @classmethod
    def __register__(cls, module_name):
        pool = Pool()
        Move = pool.get('stock.move')
        PurchaseLine = pool.get('purchase.line')
        PurchaseRequest = pool.get('purchase.request')
        SaleLine = pool.get('sale.line')
        Location = pool.get('stock.location')
        move = Move.__table__()
        purchase_line = PurchaseLine.__table__()
        purchase_request = PurchaseRequest.__table__()
        sale_line = SaleLine.__table__()
        location = Location.__table__()
        cursor = Transaction().connection.cursor()

        super(ShipmentDrop, cls).__register__(module_name)

        # Migration from 3.6
        cursor.execute(*location.select(Count(location.id),
                                        where=(location.type == 'drop')))
        has_drop_shipment, = cursor.fetchone()

        if not has_drop_shipment:
            drop_shipment = Location(name='Migration Drop Shipment',
                                     type='drop',
                                     active=False)
            drop_shipment.save()
            drop_shipment_location = drop_shipment.id

            move_sale_query = move.join(
                purchase_line,
                condition=move.origin ==
                Concat('purchase.line,', purchase_line.id)).join(
                    purchase_request,
                    condition=purchase_request.purchase_line ==
                    purchase_line.id).join(
                        sale_line,
                        condition=sale_line.purchase_request ==
                        purchase_request.id).select(
                            move.id,
                            move.to_location,
                            sale_line.id,
                            where=move.shipment.like('stock.shipment.drop,%'))
            cursor.execute(*move_sale_query)
            move_sales = cursor.fetchall()

            for sub_move in grouped_slice(move_sales):
                sub_ids = [s[0] for s in sub_move]
                cursor.execute(*move.update(columns=[move.to_location],
                                            values=[drop_shipment_location],
                                            where=move.id.in_(sub_ids)))

            cursor.execute(*move.select(limit=1))
            moves = list(cursor_dict(cursor))
            if moves:
                move_columns = moves[0].keys()
                columns = [Column(move, c) for c in move_columns if c != 'id']
                create_move = move.insert(
                    columns=columns,
                    values=move.select(
                        *columns,
                        where=move.shipment.like('stock.shipment.drop,%')))
                cursor.execute(*create_move)

            for move_id, customer_location, line_id in move_sales:
                cursor.execute(
                    *move.update(columns=[
                        move.origin, move.from_location, move.to_location
                    ],
                                 values=[
                                     Concat('sale.line,', str(line_id)),
                                     drop_shipment_location, customer_location
                                 ],
                                 where=(move.id == move_id)))

    @classmethod
    def __setup__(cls):
        super(ShipmentDrop, cls).__setup__()
        cls._transitions |= set((
            ('draft', 'waiting'),
            ('waiting', 'shipped'),
            ('draft', 'cancel'),
            ('waiting', 'cancel'),
            ('waiting', 'draft'),
            ('cancel', 'draft'),
            ('shipped', 'done'),
            ('shipped', 'cancel'),
        ))
        cls._buttons.update({
            'cancel': {
                'invisible': Eval('state').in_(['cancel', 'done']),
                'depends': ['state'],
            },
            'draft': {
                'invisible':
                ~Eval('state').in_(['cancel', 'draft', 'waiting']),
                'icon':
                If(Eval('state') == 'cancel', 'tryton-undo', 'tryton-back'),
                'depends': ['state'],
            },
            'wait': {
                'invisible': Eval('state') != 'draft',
                'depends': ['state'],
            },
            'ship': {
                'invisible': Eval('state') != 'waiting',
                'depends': ['state'],
            },
            'done': {
                'invisible': Eval('state') != 'shipped',
                'depends': ['state'],
            },
        })

    @staticmethod
    def default_state():
        return 'draft'

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

    @fields.depends('supplier')
    def on_change_supplier(self):
        if self.supplier:
            self.contact_address = self.supplier.address_get()
        else:
            self.contact_address = None

    @fields.depends('customer')
    def on_change_customer(self):
        if self.customer:
            self.delivery_address = self.customer.address_get(type='delivery')
        else:
            self.delivery_address = None

    def _get_move_planned_date(self):
        '''
        Return the planned date for moves
        '''
        return self.planned_date

    @classmethod
    def _set_move_planned_date(cls, shipments):
        '''
        Set planned date of moves for the shipments
        '''
        Move = Pool().get('stock.move')
        to_write = []
        for shipment in shipments:
            planned_date = shipment._get_move_planned_date()
            to_write.extend(([
                m for m in shipment.moves
                if m.state not in ('assigned', 'done', 'cancel')
            ], {
                'planned_date': planned_date,
            }))
        if to_write:
            Move.write(*to_write)

    @classmethod
    def create(cls, vlist):
        pool = Pool()
        Sequence = pool.get('ir.sequence')
        Config = pool.get('stock.configuration')

        vlist = [x.copy() for x in vlist]
        config = Config(1)
        for values in vlist:
            values['code'] = Sequence.get_id(config.shipment_drop_sequence)
        shipments = super(ShipmentDrop, cls).create(vlist)
        cls._set_move_planned_date(shipments)
        return shipments

    @classmethod
    def write(cls, *args):
        super(ShipmentDrop, cls).write(*args)
        cls._set_move_planned_date(sum(args[::2], []))

    @classmethod
    def copy(cls, shipments, default=None):
        if default is None:
            default = {}
        else:
            default = default.copy()
        default.setdefault('moves', None)
        return super(ShipmentDrop, cls).copy(shipments, default=default)

    @classmethod
    def delete(cls, shipments):
        pool = Pool()
        Move = pool.get('stock.move')

        cls.cancel(shipments)
        for shipment in shipments:
            if shipment.state != 'cancel':
                raise AccessError(
                    gettext('sale_supply_drop_shipment'
                            '.msg_drop_shipment_delete_cancel') % {
                                'shipment': shipment.rec_name,
                            })
        Move.delete([m for s in shipments for m in s.supplier_moves])
        super(ShipmentDrop, cls).delete(shipments)

    @classmethod
    @ModelView.button
    @Workflow.transition('cancel')
    @process_sale('customer_moves')
    @process_purchase('supplier_moves')
    def cancel(cls, shipments):
        Move = Pool().get('stock.move')
        Move.cancel([m for s in shipments for m in s.supplier_moves])
        Move.cancel([
            m for s in shipments for m in s.customer_moves
            if s.state == 'shipped'
        ])
        Move.write([
            m for s in shipments
            for m in s.customer_moves if s.state != 'shipped'
        ], {'shipment': None})

    @classmethod
    @ModelView.button
    @Workflow.transition('draft')
    def draft(cls, shipments):
        pool = Pool()
        Move = pool.get('stock.move')
        PurchaseLine = pool.get('purchase.line')
        SaleLine = pool.get('sale.line')
        for shipment in shipments:
            for move in shipment.moves:
                if (move.state == 'cancel'
                        and isinstance(move.origin, (PurchaseLine, SaleLine))):
                    raise AccessError(
                        gettext('sale_supply_drop_shipment.msg_reset_move',
                                move=move.rec_name))
        Move.draft(
            [m for s in shipments for m in s.moves if m.state != 'staging'])

    @classmethod
    def _synchronize_moves(cls, shipments):
        pool = Pool()
        UoM = pool.get('product.uom')
        Move = pool.get('stock.move')

        to_save = []
        cost_exp = Decimal(str(10.0**-Move.cost_price.digits[1]))
        for shipment in shipments:
            product_qty = defaultdict(int)
            product_cost = defaultdict(int)

            for c_move in shipment.customer_moves:
                if c_move.state == 'cancel':
                    continue
                product_qty[c_move.product] += UoM.compute_qty(
                    c_move.uom,
                    c_move.quantity,
                    c_move.product.default_uom,
                    round=False)

            s_product_qty = defaultdict(int)
            for s_move in shipment.supplier_moves:
                if s_move.state == 'cancel':
                    continue
                if s_move.cost_price:
                    internal_quantity = Decimal(str(s_move.internal_quantity))
                    product_cost[s_move.product] += (s_move.unit_price *
                                                     internal_quantity)

                quantity = UoM.compute_qty(s_move.uom,
                                           s_move.quantity,
                                           s_move.product.default_uom,
                                           round=False)
                s_product_qty[s_move.product] += quantity
                if product_qty[s_move.product]:
                    if quantity <= product_qty[s_move.product]:
                        product_qty[s_move.product] -= quantity
                        continue
                    else:
                        out_quantity = (quantity - product_qty[s_move.product])
                        out_quantity = UoM.compute_qty(
                            s_move.product.default_uom, out_quantity,
                            s_move.uom)
                        product_qty[s_move.product] = 0
                else:
                    out_quantity = s_move.quantity

                if not out_quantity:
                    continue
                unit_price = UoM.compute_price(s_move.product.default_uom,
                                               s_move.product.list_price,
                                               s_move.uom)
                new_customer_move = shipment._get_customer_move(s_move)
                new_customer_move.quantity = out_quantity
                new_customer_move.unit_price = unit_price
                to_save.append(new_customer_move)

            for product, cost in product_cost.items():
                qty = Decimal(str(s_product_qty[product]))
                if qty:
                    product_cost[product] = (cost / qty).quantize(cost_exp)
            for c_move in list(shipment.customer_moves) + to_save:
                if c_move.id is not None and c_move.state == 'cancel':
                    continue
                c_move.cost_price = product_cost[c_move.product]
                if c_move.id is None:
                    continue
                if product_qty[c_move.product] > 0:
                    exc_qty = UoM.compute_qty(c_move.product.default_uom,
                                              product_qty[c_move.product],
                                              c_move.uom)
                    removed_qty = UoM.compute_qty(c_move.uom,
                                                  min(exc_qty,
                                                      c_move.quantity),
                                                  c_move.product.default_uom,
                                                  round=False)
                    c_move.quantity = max(
                        0, c_move.uom.round(c_move.quantity - exc_qty))
                    product_qty[c_move.product] -= removed_qty
                to_save.append(c_move)

        if to_save:
            Move.save(to_save)

    def _get_customer_move(self, move):
        pool = Pool()
        Move = pool.get('stock.move')
        return Move(
            from_location=move.to_location,
            to_location=self.customer.customer_location,
            product=move.product,
            uom=move.uom,
            quantity=move.quantity,
            shipment=self,
            planned_date=self.planned_date,
            company=move.company,
            currency=move.company.currency,
            unit_price=move.unit_price,
        )

    @classmethod
    @ModelView.button
    @Workflow.transition('waiting')
    def wait(cls, shipments):
        pool = Pool()
        PurchaseRequest = pool.get('purchase.request')
        SaleLine = pool.get('sale.line')
        Move = pool.get('stock.move')

        requests = []
        for sub_lines in grouped_slice([
                m.origin.id for s in shipments for m in s.supplier_moves
                if m.origin
        ]):
            requests += PurchaseRequest.search([
                ('purchase_line', 'in', list(sub_lines)),
            ])
        pline2request = {r.purchase_line: r for r in requests}
        sale_lines = SaleLine.search([
            ('purchase_request', 'in', [r.id for r in requests]),
        ])
        request2sline = {sl.purchase_request: sl for sl in sale_lines}

        to_save = []
        for shipment in shipments:
            for move in shipment.supplier_moves:
                if not move.origin:
                    continue
                sale_line = request2sline.get(pline2request.get(move.origin))
                if not sale_line:
                    continue
                for move in sale_line.moves:
                    if (move.state not in ('cancel', 'done')
                            and not move.shipment
                            and move.from_location.type == 'drop'):
                        move.shipment = shipment
                        to_save.append(move)
        Move.save(to_save)
        cls._synchronize_moves(shipments)

    @classmethod
    @ModelView.button
    @Workflow.transition('shipped')
    @process_purchase('supplier_moves')
    def ship(cls, shipments):
        pool = Pool()
        Move = pool.get('stock.move')
        Move.do([m for s in shipments for m in s.supplier_moves])
        cls._synchronize_moves(shipments)

    @classmethod
    @ModelView.button
    @Workflow.transition('done')
    @process_sale('customer_moves')
    def done(cls, shipments):
        pool = Pool()
        Move = pool.get('stock.move')
        Date = pool.get('ir.date')
        Move.do([m for s in shipments for m in s.customer_moves])
        cls.write(shipments, {
            'effective_date': Date.today(),
        })
Exemple #29
0
class ProductQuantitiesByWarehouseMove(ModelSQL, ModelView):
    "Product Quantities By Warehouse Moves"
    __name__ = 'stock.product_quantities_warehouse.move'

    date = fields.Date("Date")
    move = fields.Many2One('stock.move', "Move")
    origin = fields.Reference("Origin", selection='get_origin')
    quantity = fields.Float("Quantity")
    cumulative_quantity_start = fields.Function(
        fields.Float("Cumulative Quantity Start"), 'get_cumulative_quantity')
    cumulative_quantity_delta = fields.Float("Cumulative Quantity Delta")
    cumulative_quantity_end = fields.Function(
        fields.Float("Cumulative Quantity End"), 'get_cumulative_quantity')
    company = fields.Many2One('company.company', "Company")

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

    @classmethod
    def table_query(cls):
        pool = Pool()
        Date = pool.get('ir.date')
        Location = pool.get('stock.location')
        Move = pool.get('stock.move')
        Product = pool.get('product.product')
        move = from_ = Move.__table__()
        transaction = Transaction()
        context = transaction.context
        database = transaction.database
        today = Date.today()

        if context.get('product_template') is not None:
            product = Product.__table__()
            from_ = move.join(product, condition=move.product == product.id)
            product_clause = product.template == context['product_template']
        else:
            product_clause = move.product == context.get('product', -1)

        if 'warehouse' in context:
            warehouse = Location(context.get('warehouse'))
            if context.get('stock_skip_warehouse'):
                location_id = warehouse.storage_location.id
            else:
                location_id = warehouse.id
        else:
            location_id = -1
        warehouse = With('id',
                         query=Location.search([
                             ('parent', 'child_of', [location_id]),
                         ],
                                               query=True,
                                               order=[]))
        date_column = Coalesce(move.effective_date, move.planned_date)
        quantity = Case((move.to_location.in_(warehouse.select(
            warehouse.id)), move.internal_quantity),
                        else_=-move.internal_quantity)
        if database.has_window_functions():
            cumulative_quantity_delta = Sum(quantity,
                                            window=Window(
                                                [date_column],
                                                order_by=[move.id.asc]))
        else:
            cumulative_quantity_delta = Literal(0)
        return (from_.select(
            move.id.as_('id'),
            Literal(0).as_('create_uid'),
            CurrentTimestamp().as_('create_date'),
            Literal(None).as_('write_uid'),
            Literal(None).as_('write_date'),
            date_column.as_('date'),
            move.id.as_('move'),
            move.origin.as_('origin'),
            quantity.as_('quantity'),
            cumulative_quantity_delta.as_('cumulative_quantity_delta'),
            move.company.as_('company'),
            where=product_clause
            & ((move.from_location.in_(warehouse.select(warehouse.id))
                & ~move.to_location.in_(warehouse.select(warehouse.id)))
               | (~move.from_location.in_(warehouse.select(warehouse.id))
                  & move.to_location.in_(warehouse.select(warehouse.id))))
            & ((date_column < today) & (move.state == 'done')
               | (date_column >= today)),
            with_=warehouse))

    @classmethod
    def get_origin(cls):
        pool = Pool()
        Move = pool.get('stock.move')
        return Move.get_origin()

    @classmethod
    def get_cumulative_quantity(cls, records, names):
        pool = Pool()
        Product = pool.get('product.product')
        transaction = Transaction()
        database = transaction.database
        trans_context = transaction.context

        def valid_context(name):
            return (trans_context.get(name) is not None
                    and isinstance(trans_context[name], int))

        if not any(map(valid_context, ['product', 'product_template'])):
            return {r.id: None for r in records}

        if trans_context.get('product') is not None:
            grouping = ('product', )
            grouping_filter = ([trans_context['product']], )
            key = trans_context['product']
        else:
            grouping = ('product.template', )
            grouping_filter = ([trans_context.get('product_template')], )
            key = trans_context['product_template']
        warehouse_id = trans_context.get('warehouse')

        def cast_date(date):
            if isinstance(date, str):
                date = datetime.date(*map(int, date.split('-', 2)))
            return date

        dates = sorted({cast_date(r.date) for r in records})
        quantities = {}
        date_start = None
        for date in dates:
            try:
                context = {
                    'stock_date_start': date_start,
                    'stock_date_end': date - datetime.timedelta(days=1),
                    'forecast': True,
                }
            except OverflowError:
                pass
            with Transaction().set_context(**context):
                quantities[date] = Product.products_by_location(
                    [warehouse_id],
                    grouping=grouping,
                    grouping_filter=grouping_filter,
                    with_childs=True).get((warehouse_id, key), 0)
            date_start = date
        cumulate = 0
        for date in dates:
            cumulate += quantities[date]
            quantities[date] = cumulate

        result = {}
        if database.has_window_functions():
            if 'cumulative_quantity_start' in names:
                result['cumulative_quantity_start'] = {
                    r.id: (quantities[cast_date(r.date)] +
                           r.cumulative_quantity_delta - r.quantity)
                    for r in records
                }
            if 'cumulative_quantity_end' in names:
                result['cumulative_quantity_end'] = {
                    r.id: (quantities[cast_date(r.date)] +
                           r.cumulative_quantity_delta)
                    for r in records
                }
        else:
            values = {r.id: quantities[cast_date(r.date)] for r in records}
            for name in names:
                result[name] = values
        return result

    def get_rec_name(self, name):
        return self.move.rec_name
class PurchaseRequisition(Workflow, ModelSQL, ModelView):
    "Purchase Requisition"
    __name__ = 'purchase.requisition'
    _rec_name = 'number'
    _states = {
        'readonly': Eval('state') != 'draft',
        }

    company = fields.Many2One(
        'company.company', "Company", required=True, select=True,
        states={
            'readonly': (Eval('state') != 'draft') | Eval('lines', [0]),
            })
    number = fields.Char('Number', readonly=True, select=True)
    description = fields.Char('Description', states=_states)
    employee = fields.Many2One(
        'company.employee', 'Employee', required=True, states=_states)
    supply_date = fields.Date(
        'Supply Date',
        states={
            'required': ~Eval('state').in_(['draft', 'cancelled']),
            'readonly': _states['readonly'],
            })
    warehouse = fields.Many2One(
        'stock.location', 'Warehouse',
        domain=[
            ('type', '=', 'warehouse'),
            ],
        states=_states)
    currency = fields.Many2One(
        'currency.currency', 'Currency',
        states={
            'readonly': (_states['readonly']
                | (Eval('lines', [0]) & Eval('currency'))),
            })
    total_amount = fields.Function(
        Monetary("Total", currency='currency', digits='currency'),
        'get_amount')
    total_amount_cache = Monetary(
        "Total Cache", currency='currency', digits='currency')
    lines = fields.One2Many(
        'purchase.requisition.line', 'requisition', 'Lines',
        states=_states)

    approved_by = employee_field(
        "Approved By", states=['approved', 'processing', 'done', 'cancelled'])
    rejected_by = employee_field(
        "Rejected By", states=['rejected', 'processing', 'done', 'cancelled'])
    state = fields.Selection([
            ('draft', "Draft"),
            ('waiting', "Waiting"),
            ('rejected', "Rejected"),
            ('approved', "Approved"),
            ('processing', "Processing"),
            ('done', "Done"),
            ('cancelled', "Cancelled"),
            ], "State", readonly=True, required=True, sort=False)

    del _states

    @classmethod
    def __setup__(cls):
        super(PurchaseRequisition, cls).__setup__()
        cls._transitions |= set((
                ('cancelled', 'draft'),
                ('rejected', 'draft'),
                ('draft', 'cancelled'),
                ('draft', 'waiting'),
                ('waiting', 'draft'),
                ('waiting', 'rejected'),
                ('waiting', 'approved'),
                ('approved', 'processing'),
                ('approved', 'draft'),
                ('processing', 'done'),
                ('done', 'processing'),
                ))
        cls._buttons.update({
                'cancel': {
                    'invisible': Eval('state') != 'draft',
                    'depends': ['state'],
                    },
                'draft': {
                    'invisible': ~Eval('state').in_(
                        ['cancelled', 'waiting', 'approved', 'rejected']),
                    'icon': If(Eval('state').in_(['cancelled', 'rejected']),
                        'tryton-undo',
                        'tryton-back'),
                    'depends': ['state'],
                    },
                'wait': {
                    'pre_validate': [('supply_date', '!=', None)],
                    'invisible': ((Eval('state') != 'draft')
                        | ~Eval('lines', [])),
                    'readonly': ~Eval('lines', []),
                    'depends': ['state'],
                    },
                'approve': {
                    'invisible': Eval('state') != 'waiting',
                    'depends': ['state'],
                    },
                'process': {
                    'invisible': ~Eval('state').in_(
                        ['approved', 'processing']),
                    'icon': If(Eval('state') == 'approved',
                        'tryton-forward', 'tryton-refresh'),
                    'depends': ['state'],
                    },
                'reject': {
                    'invisible': Eval('state') != 'waiting',
                    'depends': ['state'],
                    },
                })
        # The states where amounts are cached
        cls._states_cached = ['approved', 'done', 'rejected',
            'processing', 'cancelled']

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

        super().__register__(module_name)

        # Migration from 5.6: rename state cancel to cancelled
        cursor.execute(*table.update(
                [table.state], ['cancelled'],
                where=table.state == 'cancel'))

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

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

    @classmethod
    def default_employee(cls):
        return Transaction().context.get('employee')

    @classmethod
    def default_warehouse(cls):
        Location = Pool().get('stock.location')
        return Location.get_default_warehouse()

    @classmethod
    def default_currency(cls):
        Company = Pool().get('company.company')
        company = Transaction().context.get('company')
        if company:
            return Company(company).currency.id

    @fields.depends('lines', 'currency')
    def on_change_with_total_amount(self):
        self.total_amount = Decimal('0.0')
        if self.lines:
            for line in self.lines:
                self.total_amount += getattr(line, 'amount', None) or 0
        if self.currency:
            self.total_amount = self.currency.round(self.total_amount)
        return self.total_amount

    @classmethod
    def store_cache(cls, requisitions):
        for requisition in requisitions:
            requisition.total_amount_cache = requisition.total_amount
        cls.save(requisitions)

    @classmethod
    def get_amount(cls, requisitions, name):
        total_amount = {}

        # Sort cached first and re-instantiate to optimize cache management
        requisitions = sorted(requisitions,
            key=lambda r: r.state in cls._states_cached, reverse=True)
        requisitions = cls.browse(requisitions)
        for requisition in requisitions:
            if (requisition.state in cls._states_cached
                    and requisition.total_amount_cache is not None):
                total_amount[requisition.id] = requisition.total_amount_cache
            else:
                total_amount[requisition.id] = (
                    requisition.on_change_with_total_amount())
        return total_amount

    @classmethod
    def create_requests(cls, requisitions):
        pool = Pool()
        Request = pool.get('purchase.request')
        requests = []
        for requisition in requisitions:
            for line in requisition.lines:
                request = line.compute_request()
                if request:
                    requests.append(request)
        if requests:
            Request.save(requests)

    @classmethod
    def view_attributes(cls):
        return super().view_attributes() + [
            ('/tree', 'visual',
                If(Eval('state') == 'cancelled', 'muted', '')),
            ]

    @classmethod
    def create(cls, vlist):
        pool = Pool()
        Config = pool.get('purchase.configuration')

        config = Config(1)
        vlist = [v.copy() for v in vlist]
        default_company = cls.default_company()
        for values in vlist:
            if values.get('number') is None:
                values['number'] = config.get_multivalue(
                    'purchase_requisition_sequence',
                    company=values.get('company', default_company)).get()
        return super(PurchaseRequisition, cls).create(vlist)

    @classmethod
    def delete(cls, requisitions):
        # Cancel before delete
        cls.cancel(requisitions)
        for requisition in requisitions:
            if requisition.state != 'cancelled':
                raise AccessError(
                    gettext('purchase_requisition.msg_delete_cancel',
                        requisition=requisition.rec_name))
        super(PurchaseRequisition, cls).delete(requisitions)

    def check_for_waiting(self):
        if not self.warehouse:
            for line in self.lines:
                if line.product and line.product.type in {'goods', 'assets'}:
                    raise RequiredValidationError(
                        gettext('purchase_requisition.msg_warehouse_required',
                            requisition=self.rec_name))

    @classmethod
    def copy(cls, requisitions, default=None):
        if default is None:
            default = {}
        else:
            default = default.copy()
        default.setdefault('number', None)
        default.setdefault('supply_date', None)
        default.setdefault('approved_by')
        default.setdefault('rejected_by')
        return super(PurchaseRequisition, cls).copy(
            requisitions, default=default)

    @classmethod
    @ModelView.button
    @Workflow.transition('cancelled')
    def cancel(cls, requisitions):
        cls.store_cache(requisitions)

    @classmethod
    @ModelView.button
    @Workflow.transition('draft')
    @reset_employee('approved_by', 'rejected_by')
    def draft(cls, requisitions):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('waiting')
    def wait(cls, requisitions):
        for requisition in requisitions:
            requisition.check_for_waiting()

    @classmethod
    @ModelView.button
    @Workflow.transition('rejected')
    @set_employee('rejected_by')
    def reject(cls, requisitions):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('approved')
    @set_employee('approved_by')
    def approve(cls, requisitions):
        pool = Pool()
        Configuration = pool.get('purchase.configuration')
        transaction = Transaction()
        context = transaction.context
        cls.store_cache(requisitions)
        config = Configuration(1)
        with transaction.set_context(
                queue_scheduled_at=config.purchase_process_after,
                queue_batch=context.get('queue_batch', True)):
            cls.__queue__.process(requisitions)

    @classmethod
    @Workflow.transition('processing')
    def proceed(cls, requisitions):
        pass

    @classmethod
    @Workflow.transition('done')
    def do(cls, requisitions):
        pass

    @classmethod
    @ModelView.button
    def process(cls, requisitions):
        done = []
        process = []
        requisitions = [r for r in requisitions
            if r.state in {'approved', 'processing', 'done'}]
        cls.create_requests(requisitions)
        for requisition in requisitions:
            if requisition.is_done():
                if requisition.state != 'done':
                    done.append(requisition)
            elif requisition.state != 'processing':
                process.append(requisition)
        if process:
            cls.proceed(process)
        if done:
            cls.do(done)

    def is_done(self):
        return all(
            r.purchase and r.purchase.state in {'cancelled', 'confirmed'}
            for l in self.lines for r in l.purchase_requests)