예제 #1
0
    def __setup__(cls):
        super(AddSalePaymentView, cls).__setup__()

        INV = Or(
            Eval('method') == 'manual',
            And(
                Eval('method') == 'credit_card',
                Bool(Eval('use_existing_card'))))
        STATE1 = {
            'required':
            And(~Bool(Eval('use_existing_card')),
                Eval('method') == 'credit_card'),
            'invisible':
            INV
        }
        DEPENDS = ['use_existing_card', 'method']

        cls.owner.states.update(STATE1)
        cls.owner.depends.extend(DEPENDS)
        cls.number.states.update(STATE1)
        cls.number.depends.extend(DEPENDS)
        cls.expiry_month.states.update(STATE1)
        cls.expiry_month.depends.extend(DEPENDS)
        cls.expiry_year.states.update(STATE1)
        cls.expiry_year.depends.extend(DEPENDS)
        cls.csc.states.update(STATE1)
        cls.csc.depends.extend(DEPENDS)
        cls.swipe_data.states = {'invisible': INV}
        cls.swipe_data.depends = ['method']
예제 #2
0
 def __setup__(cls):
     super(Appointment, cls).__setup__()
     cls._error_messages.update(
         no_institution="No institution specified in appointment [%s]")
     cls.state.selection = APPOINTMENT_STATES
     cls._buttons.update({
         'start_encounter': {
             'readonly':
             Not(And(Equal(Eval('state'), 'arrived'), Bool(Eval('name')))),
             'invisible':
             In(Eval('state'), ['processing', 'done']),
         },
         'goto_encounter': {
             'invisible': Not(In(Eval('state'), ['processing', 'done']))
         },
         'client_arrived': {
             'readonly':
             Not(And(Equal(Eval('state'), 'confirmed'), Bool(Eval('name'))))
         }
     })
     ro_states = {'readonly': Not(In(Eval('state'), ['confirmed', 'free']))}
     cls.patient.states.update(ro_states)
     cls.institution.states = ro_states
     cls.state.states = ro_states
     cls.appointment_date.states = ro_states
     cls.comments.states.update(
         {'invisible': ~Eval('can_do_details', False)})
예제 #3
0
class Project(metaclass=PoolMeta):
    __name__ = 'lims.project'

    int_itl_party = fields.Many2One('party.party', 'ITL Party',
        depends=['type'], states={
            'required': Bool(Equal(Eval('type'), 'itl')),
            })
    int_result_date = fields.Date('Result date')
    int_report_reception = fields.Date('Report reception')
    int_evaluation = fields.Text('Evaluation',
        depends=['type', 'end_date'], states={
            'required': And(Equal(Eval('type'), 'itl'),
                Bool(Eval('end_date'))),
            })

    @classmethod
    def __setup__(cls):
        super().__setup__()
        project_type = ('itl', 'Interlaboratory')
        if project_type not in cls.type.selection:
            cls.type.selection.append(project_type)

    @classmethod
    def view_attributes(cls):
        return super().view_attributes() + [
            ('//group[@id="itl"]', 'states', {
                    'invisible': Not(Bool(Equal(Eval('type'), 'itl'))),
                    }),
            ]
예제 #4
0
 def view_attributes(cls):
     return [
         ('/tree/field[@name="name"]', 'visual',
          If(And(Eval('limit_state', 0) > 0,
                 Eval('state', '') == 'open'),
             If(Eval('limit_state', 0) > 1, 'danger', 'warning'), '')),
     ]
예제 #5
0
 def __setup__(cls):
     super(InpatientRegistration, cls).__setup__()
     cls._sql_constraints = [('name_uniq', 'unique(name)',
                              'The Registration code already exists')]
     cls._error_messages.update({
         'bed_is_not_available':
         'Bed is not available',
         'destination_bed_unavailable':
         'Destination bed unavailable'
     })
     cls._buttons.update({
         'confirmed': {
             'invisible':
             And(Not(Equal(Eval('state'), 'free')),
                 Not(Equal(Eval('state'), 'cancelled'))),
         },
         'cancel': {
             'invisible': Not(Equal(Eval('state'), 'confirmed')),
         },
         'discharge': {
             'invisible': Not(Equal(Eval('state'), 'hospitalized')),
         },
         'admission': {
             'invisible': Not(Equal(Eval('state'), 'confirmed')),
         },
     })
예제 #6
0
    def __setup__(cls):
        super(Surgery, cls).__setup__()
        cls._error_messages.update({
            'end_date_before_start':
            'End time "%(end_date)s" BEFORE '
            'surgery date "%(surgery_date)s"',
            'or_is_not_available':
            'Operating Room is not available'
        })

        cls._order.insert(0, ('surgery_date', 'DESC'))

        cls._buttons.update({
            'confirmed': {
                'invisible':
                And(Not(Equal(Eval('state'), 'draft')),
                    Not(Equal(Eval('state'), 'cancelled'))),
            },
            'cancel': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
            'start': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
            'done': {
                'invisible': Not(Equal(Eval('state'), 'in_progress')),
            },
            'signsurgery': {
                'invisible': Not(Equal(Eval('state'), 'done')),
            },
        })
예제 #7
0
 def __setup__(cls):
     super().__setup__()
     cls.address.states['invisible'] = And(
         cls.address.states.get('invisible', True),
         ~Eval('is_visit_location', False))
     cls.address.states['required'] = Or(
         cls.address.states.get('required', False),
         Eval('is_visit_location', False))
     cls.address.depends.append('is_visit_location')
예제 #8
0
    def __setup__(cls):
        super(PayInvoiceUsingTransactionStart, cls).__setup__()

        INV = Or(
            Eval('method') == 'manual',
            And(
                Eval('method') == 'credit_card',
                Bool(Eval('use_existing_card'))
            )
        )
        STATE1 = {
            'required': And(
                ~Bool(Eval('use_existing_card')),
                Eval('method') == 'credit_card',
                Eval('transaction_type') == 'charge',
            ),
            'invisible': INV
        }
        DEPENDS = ['use_existing_card', 'method', 'transaction_type']

        cls.owner.states.update(STATE1)
        cls.owner.depends.extend(DEPENDS)
        cls.number.states.update(STATE1)
        cls.number.depends.extend(DEPENDS)
        cls.expiry_month.states.update(STATE1)
        cls.expiry_month.depends.extend(DEPENDS)
        cls.expiry_year.states.update(STATE1)
        cls.expiry_year.depends.extend(DEPENDS)
        cls.csc.states.update(STATE1)
        cls.csc.depends.extend(DEPENDS)
        cls.swipe_data.states = {'invisible': INV}
        cls.swipe_data.depends = ['method']

        cls.credit_account.domain = [
            ('company', '=', Eval('company', -1)),
            ('kind', 'in', cls._credit_account_domain())
        ]
        cls.credit_account.depends = ['company']
예제 #9
0
    def __setup__(cls):
        super(Party, cls).__setup__()
        cls._buttons.update({
            'get_afip_data': {},
        })
        cls._error_messages.update({
            'unique_vat_number':
            'The VAT number must be unique in each country.',
            'vat_number_not_found':
            'El CUIT no ha sido encontrado',
        })

        cls.vat_number.states['required'] = And(
            Bool(Eval('vat_country')),
            Not(Equal(Eval('iva_condition'), 'consumidor_final')))
예제 #10
0
 def view_attributes(cls):
     pyson1 = And(
         Eval('employee') == Eval('context', {}).get('employee', ''),
         ~Eval('state').in_(['disclose', 'signed', 'representation']))
     attribute = [
         ("//page[@id='appraisal']", "states", {
             "invisible": pyson1
         }),
         ("//page[@id='reviewing']", "states", {
             "invisible": pyson1
         }),
         ("//page[@id='accepting']", "states", {
             "invisible": pyson1
         }),
     ]
     return attribute
예제 #11
0
class Interface(metaclass=PoolMeta):
    __name__ = 'lims.interface'

    export_file_type = fields.Selection([
        (None, ''),
        ('excel', 'Excel'),
        ('csv', 'Comma Separated Values'),
        ('txt', 'Text File'),
        ], 'File Type', sort=False)
    export_field_separator = fields.Selection([
        ('comma', 'Comma (,)'),
        ('colon', 'Colon (:)'),
        ('semicolon', 'Semicolon (;)'),
        ('tab', 'Tab'),
        ('space', 'Space'),
        ('other', 'Other'),
        ], 'Field separator', sort=False,
        states={
            'required': Eval('export_file_type') == 'csv',
            'invisible': Eval('export_file_type') != 'csv',
            },
        depends=['export_file_type'])
    export_field_separator_other = fields.Char('Other',
        states={
            'required': And(
                Eval('export_file_type') == 'csv',
                Eval('export_field_separator') == 'other'),
            'invisible': Or(
                Eval('export_file_type') != 'csv',
                Eval('export_field_separator') != 'other'),
            },
        depends=['export_file_type', 'export_field_separator'])
    export_order_field = fields.Many2One('lims.interface.column',
        'Order field', depends=['id'],
        domain=[('interface', '=', Eval('id')), ('group', '=', None)])

    @staticmethod
    def default_export_file_type():
        return 'csv'

    @staticmethod
    def default_export_field_separator():
        return 'semicolon'
예제 #12
0
    def __setup__(cls):
        cls.main_specialty = fields.Function(
            fields.Many2One(
                'gnuhealth.institution.specialties',
                'Specialty',
                domain=[('name', '=', Eval('active_id'))],
                depends=['specialties'],
                help="Choose the speciality in the case of Specialized "
                "Hospitals or where this center excels",
                # Allow to select the institution specialty only if the
                # record already exists
                states={
                    'required':
                    And(
                        Eval('institution_type') == 'specialized',
                        Eval('id', 0) > 0),
                    'readonly':
                    Eval('id', 0) < 0
                }),
            'get_main_specialty',
            'set_main_specialty',
            'search_main_specialty')

        cls.institution_type = fields.Selection((
            ('doctor_office', 'Doctor office'),
            ('primary_care', 'Primary Care Center'),
            ('clinic', 'Clinic'),
            ('hospital', 'General Hospital'),
            ('specialized', 'Specialized Hospital'),
            ('nursing_home', 'Nursing Home'),
            ('hospice', 'Hospice'),
            ('rural', 'Rural facility'),
            ('admindept', 'Administrative Department'),
            ('sclinic', 'Specialist Clinic'),
            ('lab', 'Laboratory'),
        ),
                                                'Type',
                                                required=True,
                                                sort=False)
예제 #13
0
    def __setup__(cls):
        super(InpatientRegistration, cls).__setup__()
        t = cls.__table__()
        cls._sql_constraints = [
            ('name_unique', Unique(t, t.name),
             'The Registration code already exists'),
        ]

        cls._error_messages.update({
            'bed_is_not_available':
            'Bed is not available',
            'discharge_reason_needed':
            'Admission and Discharge reasons \n'
            'as well as Discharge Dx are needed',
            'destination_bed_unavailable':
            'Destination bed unavailable',
            'need_timezone':
            'You need to set up the company timezone'
        })
        cls._buttons.update({
            'confirmed': {
                'invisible':
                And(Not(Equal(Eval('state'), 'free')),
                    Not(Equal(Eval('state'), 'cancelled'))),
            },
            'cancel': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
            'admission': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
            'discharge': {
                'invisible': Not(Equal(Eval('state'), 'hospitalized')),
            },
            'bedclean': {
                'invisible': Not(Equal(Eval('state'), 'done')),
            },
        })
예제 #14
0
class AparEmployeeFormSectionLine(ModelSQL, ModelView):
    "Apar Employee Form Section Line"

    __name__ = "apar.employee.form.section.line"

    question = fields.Many2One('apar.form.template.question',
                               'Question_Link',
                               required=True)
    question_text = fields.Char('Description')
    grade_reporting = fields.Float(
        'Grades by Reporting Authority',
        states={
            "readonly":
            And(
                Eval('section.part.employee_form.reporting_officer') != Eval(
                    'context', {}).get('employee', ''),
                Eval('state') != 'reporting_officer')
        },
        depends=['state', 'section'])

    grade_reviewing = fields.Float(
        'Grades by Reviewing Authority',
        states={
            "readonly":
            And(
                Eval('section.part.employee_form.reviewing_officer') != Eval(
                    'context', {}).get('employee', ''),
                Eval('state') != 'reviewing_officer')
        },
        depends=['state', 'section'])

    section = fields.Many2One('apar.employee.form.section',
                              'Section',
                              ondelete='CASCADE')
    state = fields.Selection([(None, ''),
                              ('reporting_officer', 'Reporting Officer'),
                              ('reviewing_officer', 'Reviewing Officer')],
                             'State')

    @staticmethod
    def default_state():
        return None

    @classmethod
    def __setup__(cls):
        super().__setup__()
        cls._error_messages.update(
            {'invalid_marks': ('Grades should be between 0 and 10 only')})

    @classmethod
    def validate(cls, records):
        super(AparEmployeeFormSectionLine, cls).validate(records)
        for record in records:
            record.check_range()

    def check_range(self):
        "Check range between 1 and 10"
        if self.grade_reporting:
            if (self.grade_reporting < 0 or self.grade_reporting > 10):
                self.raise_user_error('invalid_marks')
        if self.grade_reviewing:
            if (self.grade_reviewing < 0 or self.grade_reviewing > 10):
                self.raise_user_error('invalid_marks')
예제 #15
0
class Sequence(DeactivableMixin, ModelSQL, ModelView):
    "Sequence"
    __name__ = 'ir.sequence'

    _strict = False
    name = fields.Char('Sequence Name', required=True, translate=True)
    sequence_type = fields.Many2One('ir.sequence.type',
                                    "Sequence Type",
                                    required=True,
                                    ondelete='RESTRICT',
                                    states={
                                        'readonly': Eval('id', -1) >= 0,
                                    },
                                    depends=['id'])
    prefix = fields.Char('Prefix', strip=False)
    suffix = fields.Char('Suffix', strip=False)
    type = fields.Selection([
        ('incremental', 'Incremental'),
        ('decimal timestamp', 'Decimal Timestamp'),
        ('hexadecimal timestamp', 'Hexadecimal Timestamp'),
    ], 'Type')
    number_next_internal = fields.Integer(
        'Next Number',
        states={
            'invisible': ~Eval('type').in_(['incremental']),
            'required':
            And(Eval('type').in_(['incremental']), not sql_sequence),
        },
        depends=['type'])
    number_next = fields.Function(number_next_internal, 'get_number_next',
                                  'set_number_next')
    number_increment = fields.Integer('Increment Number',
                                      states={
                                          'invisible':
                                          ~Eval('type').in_(['incremental']),
                                          'required':
                                          Eval('type').in_(['incremental']),
                                      },
                                      depends=['type'])
    padding = fields.Integer('Number padding',
                             states={
                                 'invisible':
                                 ~Eval('type').in_(['incremental']),
                                 'required': Eval('type').in_(['incremental']),
                             },
                             depends=['type'])
    timestamp_rounding = fields.Float(
        'Timestamp Rounding',
        required=True,
        states={
            'invisible':
            ~Eval('type').in_(['decimal timestamp', 'hexadecimal timestamp']),
        },
        depends=['type'])
    timestamp_offset = fields.Float(
        'Timestamp Offset',
        required=True,
        states={
            'invisible':
            ~Eval('type').in_(['decimal timestamp', 'hexadecimal timestamp']),
        },
        depends=['type'])
    last_timestamp = fields.Integer(
        'Last Timestamp',
        states={
            'invisible':
            ~Eval('type').in_(['decimal timestamp', 'hexadecimal timestamp']),
            'required':
            Eval('type').in_(['decimal timestamp', 'hexadecimal timestamp']),
        },
        depends=['type'])

    @classmethod
    def __setup__(cls):
        super(Sequence, cls).__setup__()
        table = cls.__table__()
        cls._sql_constraints += [
            ('check_timestamp_rounding',
             Check(table, table.timestamp_rounding > 0),
             'Timestamp rounding should be greater than 0'),
        ]

    @classmethod
    def __register__(cls, module):
        pool = Pool()
        SequenceType = pool.get('ir.sequence.type')
        cursor = Transaction().connection.cursor()
        table = cls.__table__()
        sequence_type = SequenceType.__table__()

        super().__register__(module)

        table_h = cls.__table_handler__(module)

        # Migration from 5.8: replace code by sequence_type
        if table_h.column_exist('code'):
            cursor.execute(*table.update(
                [table.sequence_type],
                sequence_type.select(sequence_type.id,
                                     where=sequence_type.code == table.code)))
            table_h.drop_column('code')

    @staticmethod
    def default_type():
        return 'incremental'

    @staticmethod
    def default_number_increment():
        return 1

    @staticmethod
    def default_number_next():
        return 1

    @staticmethod
    def default_padding():
        return 0

    @staticmethod
    def default_timestamp_rounding():
        return 1.0

    @staticmethod
    def default_timestamp_offset():
        return 946681200.0  # Offset for 2000-01-01

    @staticmethod
    def default_last_timestamp():
        return 0

    def get_number_next(self, name):
        if self.type != 'incremental':
            return

        transaction = Transaction()
        if sql_sequence and not self._strict:
            return transaction.database.sequence_next_number(
                transaction.connection, self._sql_sequence_name)
        else:
            return self.number_next_internal

    @classmethod
    def set_number_next(cls, sequences, name, value):
        super(Sequence, cls).write(sequences, {
            'number_next_internal': value,
        })

    @classmethod
    def view_attributes(cls):
        return [
            ('//group[@id="incremental"]', 'states', {
                'invisible': ~Eval('type').in_(['incremental']),
            }),
            ('//group[@id="timestamp"]', 'states', {
                'invisible':
                ~Eval('type').in_(
                    ['decimal timestamp', 'hexadecimal timestamp']),
            }),
        ]

    @classmethod
    def create(cls, vlist):
        sequences = super(Sequence, cls).create(vlist)
        for sequence, values in zip(sequences, vlist):
            if sql_sequence and not cls._strict:
                sequence.update_sql_sequence(
                    values.get('number_next', cls.default_number_next()))
        return sequences

    @classmethod
    def write(cls, *args):
        transaction = Transaction()
        if (transaction.user != 0
                and transaction.context.get('_check_access')):
            for values in args[1::2]:
                if 'sequence_type' in values:
                    raise AccessError(
                        gettext('ir.msg_sequence_change_sequence_type'))
        super().write(*args)
        if sql_sequence and not cls._strict:
            actions = iter(args)
            for sequences, values in zip(actions, actions):
                for sequence in sequences:
                    sequence.update_sql_sequence(values.get('number_next'))

    @classmethod
    def delete(cls, sequences):
        if sql_sequence and not cls._strict:
            for sequence in sequences:
                sequence.delete_sql_sequence()
        return super(Sequence, cls).delete(sequences)

    @classmethod
    def validate(cls, sequences):
        super(Sequence, cls).validate(sequences)
        cls.check_affixes(sequences)
        cls.check_last_timestamp(sequences)

    @classmethod
    def check_affixes(cls, sequences):
        "Check prefix and suffix"
        for sequence in sequences:
            for affix, error_message in [
                (sequence.prefix, 'msg_sequence_invalid_prefix'),
                (sequence.suffix, 'msg_sequence_invalid_suffix')
            ]:
                try:
                    cls._process(affix)
                except (TypeError, ValueError) as exc:
                    raise AffixError(
                        gettext('ir.%s' % error_message,
                                affix=affix,
                                sequence=sequence.rec_name)) from exc

    @classmethod
    def check_last_timestamp(cls, sequences):
        "Check last_timestamp"

        for sequence in sequences:
            next_timestamp = cls._timestamp(sequence)
            if (sequence.last_timestamp is not None
                    and sequence.last_timestamp > next_timestamp):
                raise LastTimestampError(
                    gettext('ir.msg_sequence_last_timestamp_future'))

    @property
    def _sql_sequence_name(self):
        'Return SQL sequence name'
        return '%s_%s' % (self._table, self.id)

    def create_sql_sequence(self, number_next=None):
        'Create the SQL sequence'
        transaction = Transaction()

        if self.type != 'incremental':
            return
        if number_next is None:
            number_next = self.number_next
        if sql_sequence:
            transaction.database.sequence_create(transaction.connection,
                                                 self._sql_sequence_name,
                                                 self.number_increment,
                                                 number_next)

    def update_sql_sequence(self, number_next=None):
        'Update the SQL sequence'
        transaction = Transaction()

        exist = transaction.database.sequence_exist(transaction.connection,
                                                    self._sql_sequence_name)
        if self.type != 'incremental':
            if exist:
                self.delete_sql_sequence()
            return
        if not exist:
            self.create_sql_sequence(number_next)
            return
        if number_next is None:
            number_next = self.number_next
        transaction.database.sequence_update(transaction.connection,
                                             self._sql_sequence_name,
                                             self.number_increment,
                                             number_next)

    def delete_sql_sequence(self):
        'Delete the SQL sequence'
        transaction = Transaction()
        if self.type != 'incremental':
            return
        transaction.database.sequence_delete(transaction.connection,
                                             self._sql_sequence_name)

    @classmethod
    def _process(cls, string, date=None):
        return Template(string
                        or '').substitute(**cls._get_substitutions(date))

    @classmethod
    def _get_substitutions(cls, date):
        '''
        Returns a dictionary with the keys and values of the substitutions
        available to format the sequence
        '''
        pool = Pool()
        Date = pool.get('ir.date')
        if not date:
            date = Date.today()
        return {
            'year': date.strftime('%Y'),
            'month': date.strftime('%m'),
            'day': date.strftime('%d'),
        }

    @staticmethod
    def _timestamp(sequence):
        return int((time.time() - sequence.timestamp_offset) /
                   sequence.timestamp_rounding)

    @classmethod
    def _get_sequence(cls, sequence):
        if sequence.type == 'incremental':
            if sql_sequence and not cls._strict:
                cursor = Transaction().connection.cursor()
                cursor.execute('SELECT nextval(\'"%s"\')' %
                               sequence._sql_sequence_name)
                number_next, = cursor.fetchone()
            else:
                # Pre-fetch number_next
                number_next = sequence.number_next_internal

                cls.write(
                    [sequence], {
                        'number_next_internal':
                        (number_next + sequence.number_increment),
                    })
            return '%%0%sd' % sequence.padding % number_next
        elif sequence.type in ('decimal timestamp', 'hexadecimal timestamp'):
            timestamp = sequence.last_timestamp
            while timestamp == sequence.last_timestamp:
                timestamp = cls._timestamp(sequence)
            cls.write([sequence], {
                'last_timestamp': timestamp,
            })
            if sequence.type == 'decimal timestamp':
                return '%d' % timestamp
            else:
                return hex(timestamp)[2:].upper()
        return ''

    def get(self, _lock=False):
        '''
        Return the next sequence value
        '''
        cls = self.__class__
        # bypass rules on sequences
        with Transaction().set_context(user=False, _check_access=False):
            with Transaction().set_user(0):
                try:
                    sequence = cls(self.id)
                except TypeError:
                    raise MissingError(gettext('ir.msg_sequence_missing'))
                if _lock:
                    transaction = Transaction()
                    database = transaction.database
                    connection = transaction.connection
                    if not database.has_select_for():
                        database.lock(connection, cls._table)
                    else:
                        table = cls.__table__()
                        query = table.select(Literal(1),
                                             where=table.id == sequence.id,
                                             for_=For('UPDATE', nowait=True))
                        cursor = connection.cursor()
                        cursor.execute(*query)
                date = Transaction().context.get('date')
                return '%s%s%s' % (
                    cls._process(sequence.prefix, date=date),
                    cls._get_sequence(sequence),
                    cls._process(sequence.suffix, date=date),
                )
예제 #16
0
_STATES = {
    'readonly': Eval('state') != 'draft',
}
_DEPENDS = ['state']

_BILLING_STATES = _STATES.copy()
_BILLING_STATES.update({
    'required': (Eval('pyafipws_concept') == '2')
    | (Eval('pyafipws_concept') == '3')
})

_POS_STATES = _STATES.copy()
_POS_STATES.update({
    'required':
    And(
        Eval('type').in_(['out_invoice', 'out_credit_note']),
        ~Eval('state').in_(['draft'])),
    'invisible':
    Eval('type').in_(['in_invoice', 'in_credit_note']),
})

IVA_AFIP_CODE = collections.defaultdict(lambda: 0)
IVA_AFIP_CODE.update({
    Decimal('0'): 3,
    Decimal('0.105'): 4,
    Decimal('0.21'): 5,
    Decimal('0.27'): 6,
})

INVOICE_TYPE_AFIP_CODE = {
    ('out_invoice', 'A'): ('1', u'01-Factura A'),
예제 #17
0
 def search_has_result(cls, field_name, clause):
     return [(And(Bool(Eval('date_tested')),
                  Bool(Eval('lab_result_state'))), clause[1], clause[2])]
예제 #18
0
class Surgery(ModelSQL, ModelView):
    'Surgery'
    __name__ = 'gnuhealth.surgery'

    def surgery_duration(self, name):

        if (self.surgery_end_date and self.surgery_date):
            return self.surgery_end_date - self.surgery_date
        else:
            return None

    def patient_age_at_surgery(self, name):
        if (self.patient.name.dob and self.surgery_date):
            rdelta = relativedelta(self.surgery_date.date(),
                                   self.patient.name.dob)
            years_months_days = str(rdelta.years) + 'y ' \
                + str(rdelta.months) + 'm ' \
                + str(rdelta.days) + 'd'
            return years_months_days
        else:
            return None

    patient = fields.Many2One('gnuhealth.patient', 'Patient', required=True)
    admission = fields.Many2One('gnuhealth.appointment', 'Admission')
    operating_room = fields.Many2One('gnuhealth.hospital.or', 'Operating Room')
    code = fields.Char('Code',
                       readonly=True,
                       help="Health Center code / sequence")

    procedures = fields.One2Many(
        'gnuhealth.operation',
        'name',
        'Procedures',
        help="List of the procedures in the surgery. Please enter the first "
        "one as the main procedure")

    supplies = fields.One2Many(
        'gnuhealth.surgery_supply',
        'name',
        'Supplies',
        help="List of the supplies required for the surgery")

    pathology = fields.Many2One('gnuhealth.pathology',
                                'Condition',
                                help="Base Condition / Reason")

    classification = fields.Selection([
        (None, ''),
        ('o', 'Optional'),
        ('r', 'Required'),
        ('u', 'Urgent'),
        ('e', 'Emergency'),
    ],
                                      'Urgency',
                                      help="Urgency level for this surgery",
                                      sort=False)
    surgeon = fields.Many2One('gnuhealth.healthprofessional',
                              'Surgeon',
                              help="Surgeon who did the procedure")

    anesthetist = fields.Many2One('gnuhealth.healthprofessional',
                                  'Anesthetist',
                                  help="Anesthetist in charge")

    surgery_date = fields.DateTime('Date', help="Start of the Surgery")

    surgery_end_date = fields.DateTime(
        'End',
        states={
            'required': Equal(Eval('state'), 'done'),
        },
        help="Automatically set when the surgery is done."
        "It is also the estimated end time when confirming the surgery.")

    surgery_length = fields.Function(
        fields.TimeDelta('Duration',
                         states={
                             'invisible':
                             And(Not(Equal(Eval('state'), 'done')),
                                 Not(Equal(Eval('state'), 'signed')))
                         },
                         help="Length of the surgery"), 'surgery_duration')

    state = fields.Selection([
        ('draft', 'Draft'),
        ('confirmed', 'Confirmed'),
        ('cancelled', 'Cancelled'),
        ('in_progress', 'In Progress'),
        ('done', 'Done'),
        ('signed', 'Signed'),
    ],
                             'State',
                             readonly=True,
                             sort=False)

    signed_by = fields.Many2One(
        'gnuhealth.healthprofessional',
        'Signed by',
        readonly=True,
        states={'invisible': Not(Equal(Eval('state'), 'signed'))},
        help="Health Professional that signed this surgery document")

    # age is deprecated in GNU Health 2.0
    age = fields.Char('Estimative Age',
                      help="Use this field for historical purposes, \
        when no date of surgery is given")

    computed_age = fields.Function(
        fields.Char('Age',
                    help="Computed patient age at the moment of the surgery"),
        'patient_age_at_surgery')

    gender = fields.Function(fields.Selection([
        (None, ''),
        ('m', 'Male'),
        ('f', 'Female'),
        ('f-m', 'Female -> Male'),
        ('m-f', 'Male -> Female'),
    ], 'Gender'),
                             'get_patient_gender',
                             searcher='search_patient_gender')

    description = fields.Char('Description')
    preop_mallampati = fields.Selection([
        (None, ''),
        ('Class 1', 'Class 1: Full visibility of tonsils, uvula and soft '
         'palate'),
        ('Class 2', 'Class 2: Visibility of hard and soft palate, '
         'upper portion of tonsils and uvula'),
        ('Class 3', 'Class 3: Soft and hard palate and base of the uvula are '
         'visible'),
        ('Class 4', 'Class 4: Only Hard Palate visible'),
    ],
                                        'Mallampati Score',
                                        sort=False)
    preop_bleeding_risk = fields.Boolean(
        'Risk of Massive bleeding',
        help="Patient has a risk of losing more than 500 "
        "ml in adults of over 7ml/kg in infants. If so, make sure that "
        "intravenous access and fluids are available")

    preop_oximeter = fields.Boolean('Pulse Oximeter in place',
                                    help="Pulse oximeter is in place "
                                    "and functioning")

    preop_site_marking = fields.Boolean(
        'Surgical Site Marking',
        help="The surgeon has marked the surgical incision")

    preop_antibiotics = fields.Boolean(
        'Antibiotic Prophylaxis',
        help="Prophylactic antibiotic treatment within the last 60 minutes")

    preop_sterility = fields.Boolean(
        'Sterility confirmed',
        help="Nursing team has confirmed sterility of the devices and room")

    preop_asa = fields.Selection([
        (None, ''),
        ('ps1', 'PS 1 : Normal healthy patient'),
        ('ps2', 'PS 2 : Patients with mild systemic disease'),
        ('ps3', 'PS 3 : Patients with severe systemic disease'),
        ('ps4', 'PS 4 : Patients with severe systemic disease that is'
         ' a constant threat to life '),
        ('ps5', 'PS 5 : Moribund patients who are not expected to'
         ' survive without the operation'),
        ('ps6', 'PS 6 : A declared brain-dead patient who organs are'
         ' being removed for donor purposes'),
    ],
                                 'ASA PS',
                                 help="ASA pre-operative Physical Status",
                                 sort=False)

    preop_rcri = fields.Many2One(
        'gnuhealth.rcri',
        'RCRI',
        help='Patient Revised Cardiac Risk Index\n'
        'Points 0: Class I Very Low (0.4% complications)\n'
        'Points 1: Class II Low (0.9% complications)\n'
        'Points 2: Class III Moderate (6.6% complications)\n'
        'Points 3 or more : Class IV High (>11% complications)')

    surgical_wound = fields.Selection([
        (None, ''),
        ('I', 'Clean . Class I'),
        ('II', 'Clean-Contaminated . Class II'),
        ('III', 'Contaminated . Class III'),
        ('IV', 'Dirty-Infected . Class IV'),
    ],
                                      'Surgical wound',
                                      sort=False)

    extra_info = fields.Text('Extra Info')

    anesthesia_report = fields.Text('Anesthesia Report')

    institution = fields.Many2One('gnuhealth.institution', 'Institution')

    report_surgery_date = fields.Function(fields.Date('Surgery Date'),
                                          'get_report_surgery_date')
    report_surgery_time = fields.Function(fields.Time('Surgery Time'),
                                          'get_report_surgery_time')

    surgery_team = fields.One2Many(
        'gnuhealth.surgery_team',
        'name',
        'Team Members',
        help="Professionals Involved in the surgery")

    postoperative_dx = fields.Many2One(
        'gnuhealth.pathology',
        'Post-op dx',
        states={
            'invisible':
            And(Not(Equal(Eval('state'), 'done')),
                Not(Equal(Eval('state'), 'signed')))
        },
        help="Post-operative diagnosis")

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

    @staticmethod
    def default_surgery_date():
        return datetime.now()

    @staticmethod
    def default_surgeon():
        pool = Pool()
        HealthProf = pool.get('gnuhealth.healthprofessional')
        surgeon = HealthProf.get_health_professional()
        return surgeon

    @staticmethod
    def default_state():
        return 'draft'

    def get_patient_gender(self, name):
        return self.patient.gender

    @classmethod
    def search_patient_gender(cls, name, clause):
        res = []
        value = clause[2]
        res.append(('patient.name.gender', clause[1], value))
        return res

    # Show the gender and age upon entering the patient
    # These two are function fields (don't exist at DB level)
    @fields.depends('patient')
    def on_change_patient(self):
        gender = None
        age = ''
        self.gender = self.patient.gender
        self.computed_age = self.patient.age

    @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('code'):
                config = Config(1)
                values['code'] = Sequence.get_id(
                    config.surgery_code_sequence.id)
        return super(Surgery, cls).create(vlist)

    @classmethod
    def __setup__(cls):
        super(Surgery, cls).__setup__()
        cls._error_messages.update({
            'end_date_before_start':
            'End time "%(end_date)s" BEFORE '
            'surgery date "%(surgery_date)s"',
            'or_is_not_available':
            'Operating Room is not available'
        })

        cls._order.insert(0, ('surgery_date', 'DESC'))

        cls._buttons.update({
            'confirmed': {
                'invisible':
                And(Not(Equal(Eval('state'), 'draft')),
                    Not(Equal(Eval('state'), 'cancelled'))),
            },
            'cancel': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
            'start': {
                'invisible': Not(Equal(Eval('state'), 'confirmed')),
            },
            'done': {
                'invisible': Not(Equal(Eval('state'), 'in_progress')),
            },
            'signsurgery': {
                'invisible': Not(Equal(Eval('state'), 'done')),
            },
        })

    @classmethod
    def validate(cls, surgeries):
        super(Surgery, cls).validate(surgeries)
        for surgery in surgeries:
            surgery.validate_surgery_period()

    def validate_surgery_period(self):
        Lang = Pool().get('ir.lang')

        language, = Lang.search([
            ('code', '=', Transaction().language),
        ])
        if (self.surgery_end_date and self.surgery_date):
            if (self.surgery_end_date < self.surgery_date):
                self.raise_user_error(
                    'end_date_before_start', {
                        'surgery_date':
                        Lang.strftime(self.surgery_date, language.code,
                                      language.date),
                        'end_date':
                        Lang.strftime(self.surgery_end_date, language.code,
                                      language.date),
                    })

    @classmethod
    def write(cls, surgeries, vals):
        # Don't allow to write the record if the surgery has been signed
        if surgeries[0].state == 'signed':
            cls.raise_user_error(
                "This surgery is at state Done and has been signed\n"
                "You can no longer modify it.")
        return super(Surgery, cls).write(surgeries, vals)

    ## Method to check for availability and make the Operating Room reservation
    # for the associated surgery

    @classmethod
    @ModelView.button
    def confirmed(cls, surgeries):
        surgery_id = surgeries[0]
        Operating_room = Pool().get('gnuhealth.hospital.or')
        cursor = Transaction().connection.cursor()

        # Operating Room and end surgery time check
        if (not surgery_id.operating_room or not surgery_id.surgery_end_date):
            cls.raise_user_error("Operating Room and estimated end time  "
                                 "are needed in order to confirm the surgery")

        or_id = surgery_id.operating_room.id
        cursor.execute(
            "SELECT COUNT(*) \
            FROM gnuhealth_surgery \
            WHERE (surgery_date::timestamp,surgery_end_date::timestamp) \
                OVERLAPS (timestamp %s, timestamp %s) \
              AND (state = %s or state = %s) \
              AND operating_room = CAST(%s AS INTEGER) ",
            (surgery_id.surgery_date, surgery_id.surgery_end_date, 'confirmed',
             'in_progress', str(or_id)))
        res = cursor.fetchone()
        if (surgery_id.surgery_end_date < surgery_id.surgery_date):
            cls.raise_user_error("The Surgery end date must later than the \
                Start")
        if res[0] > 0:
            cls.raise_user_error('or_is_not_available')
        else:
            cls.write(surgeries, {'state': 'confirmed'})

    # Cancel the surgery and set it to draft state
    # Free the related Operating Room

    @classmethod
    @ModelView.button
    def cancel(cls, surgeries):
        surgery_id = surgeries[0]
        Operating_room = Pool().get('gnuhealth.hospital.or')

        cls.write(surgeries, {'state': 'cancelled'})

    # Start the surgery

    @classmethod
    @ModelView.button
    def start(cls, surgeries):
        surgery_id = surgeries[0]
        Operating_room = Pool().get('gnuhealth.hospital.or')

        cls.write(
            surgeries, {
                'state': 'in_progress',
                'surgery_date': datetime.now(),
                'surgery_end_date': datetime.now()
            })
        Operating_room.write([surgery_id.operating_room],
                             {'state': 'occupied'})

    # Finnish the surgery
    # Free the related Operating Room

    @classmethod
    @ModelView.button
    def done(cls, surgeries):
        surgery_id = surgeries[0]
        Operating_room = Pool().get('gnuhealth.hospital.or')

        cls.write(surgeries, {
            'state': 'done',
            'surgery_end_date': datetime.now()
        })

        Operating_room.write([surgery_id.operating_room], {'state': 'free'})

    # Sign the surgery document, and the surgical act.

    @classmethod
    @ModelView.button
    def signsurgery(cls, surgeries):
        surgery_id = surgeries[0]

        # Sign, change the state of the Surgery to "Signed"
        # and write the name of the signing health professional

        signing_hp = Pool().get(
            'gnuhealth.healthprofessional').get_health_professional()
        if not signing_hp:
            cls.raise_user_error(
                "No health professional associated to this user !")

        cls.write(surgeries, {'state': 'signed', 'signed_by': signing_hp})

    def get_report_surgery_date(self, name):
        Company = Pool().get('company.company')

        timezone = None
        company_id = Transaction().context.get('company')
        if company_id:
            company = Company(company_id)
            if company.timezone:
                timezone = pytz.timezone(company.timezone)

        dt = self.surgery_date
        return datetime.astimezone(dt.replace(tzinfo=pytz.utc),
                                   timezone).date()

    def get_report_surgery_time(self, name):
        Company = Pool().get('company.company')

        timezone = None
        company_id = Transaction().context.get('company')
        if company_id:
            company = Company(company_id)
            if company.timezone:
                timezone = pytz.timezone(company.timezone)

        dt = self.surgery_date
        return datetime.astimezone(dt.replace(tzinfo=pytz.utc),
                                   timezone).time()

    @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,
            ('patient', ) + tuple(clause[1:]),
            ('code', ) + tuple(clause[1:]),
        ]
예제 #19
0
    def __setup__(cls):
        super().__setup__()
        cls._error_messages.update({
            'invalid_otp': ("OTP Entered by you is invalid."),
            'missing_notes': ('''As per DOPT guidelines, if the grades are
                less than 4 or more than 8, then the remarks are mandatory.
                Please provide the remarks and then sign the part again.
            '''),
            'missing_contact':
            ("""Your mobile number is not updated in our records.
            Please contact your respective Establishment to get it updated
            in our records."""),
            'otp_expired':
            ("""Your OTP has expired, please generate new OTP by clicking
            Resend OTP button""")
        })

        c1 = Not(
            And(
                Eval('employee_form.state') == 'self_appraisal',
                Eval('employee') == Eval('context', {}).get('employee', '')))
        c2 = Not(
            And(
                Eval('employee_form.state') == 'reporting_officer',
                Eval('reporting_officer') == Eval('context',
                                                  {}).get('employee', '')))
        c3 = Not(
            And(
                Eval('employee_form.state') == 'reviewing_officer',
                Eval('reviewing_officer') == Eval('context',
                                                  {}).get('employee', '')))
        c4 = Not(
            And(
                Eval('employee_form.state') == 'accepting_authority',
                Eval('acceptance_authority') == Eval('context',
                                                     {}).get('employee', '')))
        sign_this_doc_button = Or(
            Eval('state').in_(['waiting_for_otp', 'signed']),
            [c1, [c2, [c3, c4]]])

        cls._buttons.update({
            "sign_this_document": {
                'invisible': sign_this_doc_button,
                'depends': ['state']
            },
            "form_signature_validate_otp": {
                'invisible': Eval('state').in_(['unsigned', 'signed']),
                'depends': ['state']
            },
            "resend_otp": {
                'invisible': Eval('state').in_(['unsigned', 'signed']),
                'depends': ['state']
            },
            "cancel_sign": {
                'invisible': Eval('state').in_(['unsigned', 'signed']),
                'depends': ['state']
            },
        })

        cls._transitions |= set(
            (('unsigned', 'waiting_for_otp'), ('waiting_for_otp', 'signed'),
             ('waiting_for_otp', 'unsigned')))
예제 #20
0
class DocumentInvoiceGoods(ModelWorkflow, ModelSQL, ModelView):
    "Documents (Invoice) "
    _name='ekd.document.head.invoice_goods'
    _description=__doc__
    _inherits = {'ekd.document': 'document'}

    document = fields.Many2One('ekd.document', 'Document', required=True,
            ondelete='CASCADE')

    direct_document = fields.Selection([
                ('output_goods', 'For Customer'),
                ('move_goods', 'Internal Move'),
                ('input_goods', 'From Supplier'),
                ], 'Direct Document')

    type_product = fields.Selection([
                ('fixed_assets', 'Fixed Assets'),
                ('intangible', 'Intangible assets'),
                ('material', 'Material'),
                ('goods', 'Goods'),
                ], 'Type Product')

    template_invoice = fields.Function(fields.Many2One('ekd.document.template',
                'Name',
                domain=[('type_account', '=',
                    Eval('direct_document', 
                        Get(Eval('context', {}), 'direct_document')))]
                ), 'get_fields', setter='set_fields')
    number_doc = fields.Function(fields.Char('Number',
                states={'invisible': And(Not(Bool(Eval('number_doc'))),
                    Not(Equal(Eval('direct_document',''),'input_goods')))}),
                'get_fields', setter='set_fields', searcher='template_search')
    from_to_party = fields.Function(fields.Many2One('party.party',
                'Party',
                states={'invisible': Equal(Eval('direct_document'),'move_goods')}
                ), 'get_fields', setter='set_fields')
    from_party_fnc = fields.Function(fields.Many2One('party.party',
                'From Party',
                states={'invisible': Not(Equal(Eval('direct_document'),'move_goods'))}
                ), 'get_fields', setter='set_fields')
    to_party_fnc = fields.Function(fields.Many2One('party.party',
                'To Party',
                states={'invisible': Not(Equal(Eval('direct_document'),'move_goods'))}
                ), 'get_fields', setter='set_fields')
    from_to_stock = fields.Function(fields.Many2One('ekd.company.department.stock',
                'Stock',
                states={'invisible': Equal(Eval('direct_document'),'move_goods')}
                ), 'get_fields', setter='set_fields')
    from_stock_fnc = fields.Function(fields.Many2One('ekd.company.department.stock',
                'From Stock',
                states={'invisible': Not(Equal(Eval('direct_document'),'move_goods'))}
                ), 'get_fields', setter='set_fields')
    to_stock_fnc = fields.Function(fields.Many2One('ekd.company.department.stock',
                'To Stock',
                states={'invisible': Not(Equal(Eval('direct_document'),'move_goods'))}
                ), 'get_fields', setter='set_fields')
    shipper = fields.Many2One('party.party', 'Shipper',
                states={'invisible': Eval('as_shipper', True)})
    consignee = fields.Many2One('party.party', 'Consignee',
                states={'invisible': Eval('as_consignee', True)})
    as_shipper = fields.Boolean('As Shipper')
    as_consignee = fields.Boolean('As Consignee')

    amount_doc = fields.Function(fields.Numeric('Amount', digits=(16, Eval('currency_digits', 2))), 
                'get_fields', setter='set_fields')
    amount_tax = fields.Function(fields.Numeric('Amount Tax', digits=(16, Eval('currency_digits', 2))), 
                'get_fields')
    currency = fields.Many2One('currency.currency', 'Currency')
    currency_digits = fields.Function(fields.Integer('Currency Digits',
                on_change_with=['currency']), 'get_currency_digits')
    type_tax = fields.Selection([
            ('not_vat','Not VAT'),
            ('including','Including'),
            ('over_amount','Over Amount')
            ], 'Type Compute Tax')
    lines = fields.One2Many('ekd.document.line.product', 'invoice', 'Lines',
                context={'type_product':Eval('type_product')})
    state_doc = fields.Function(fields.Selection(_STATE_INVOICE_GOODS, required=True, readonly=True, string='State'), 'get_fields', 
                setter='set_fields')
    deleting = fields.Boolean('Flag deleting', readonly=True)

    def __init__(self):
        super(DocumentInvoiceGoods, self).__init__()
        self._rpc.update({
            'button_add_number': True,
            'button_draft': True,
            'button_to_pay': True,
            'button_part_paid': True,
            'button_paid': True,
            'button_received': True,
            'button_cancel': True,
            'button_restore': True,
            'button_print': True,
            'button_send': True,
            'button_post': True,
            'button_obtained': True,
            'button_delivered': True,
            })

        self._order.insert(0, ('date_document', 'ASC'))
        self._order.insert(1, ('template', 'ASC'))

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

    def default_as_shipper(self):
        return True

    def default_as_consignee(self):
        return True

    def default_type_product(self):
        return Transaction().context.get('type_product') or 'material'

    def default_from_to_party_doc(self):
        return Transaction().context.get('from_to_party') or False

    def default_direct_document(self):
        return Transaction().context.get('direct_document') or 'invoice_revenue'

    def default_template_invoice(self):
        context = Transaction().context
        if context.get('template_invoice', False):
            return  context.get('template_invoice')
        else:
            template_obj = self.pool.get('ekd.document.template')
            template_ids = template_obj.search( [
                        ('type_account','=',context.get('direct_document'))
                        ], order=[('sequence','ASC')])
            if len(template_ids) > 0:
                return template_ids[0]

    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_state_doc(self):
        return Transaction().context.get('state_doc', 'draft')

    def get_currency_digits(self,  ids, name):
        res = {}
        for line in self.browse( ids):
            res[line.id] = line.currency and line.currency.digits or 2
        return res

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

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

    def documents_base_get(self):
        dictions_obj = self.pool.get('ir.dictions')
        res = []
        diction_ids = dictions_obj.search([
            ('model', '=', 'ekd.document.head.invoice_goods'),
            ('pole', '=', 'document_base'),
            ], order=[('sequence','ASC')])
        for diction in dictions_obj.browse(diction_ids):
            res.append([diction.key, diction.value])
        return res

    def get_fields(self,  ids, names):
        if not ids:
            return {}
        res={}
        for line in self.browse( ids):
            for name in names:
                res.setdefault(name, {})
                res[name].setdefault(line.id, False)
                if name == 'number_doc':
                    if line.direct_document == 'input_goods' :
                        res[name][line.id] = line.number_in
                    else:
                        res[name][line.id] = line.number_our
                elif name == 'state_doc':
                        res[name][line.id] = line.state
                elif name == 'amount_doc':
                    for line_spec in line.lines:
                        if line_spec.type == 'line':
                            res[name][line.id] += line_spec.amount
                elif name == 'amount_tax':
                    for line_spec in line.lines:
                        if line_spec.type == 'line':
                            res[name][line.id] += line_spec.amount_tax
                elif name == 'from_to_party':
                    if line.direct_document == 'input_goods' :
                        res[name][line.id] = line.from_party.id
                    else:
                        res[name][line.id] = line.to_party.id
                elif name == 'from_party_fnc':
                    res[name][line.id] = line.from_party.id
                elif name == 'to_party_fnc':
                    res[name][line.id] = line.to_party.id
                elif name == 'template_invoice':
                    res[name][line.id] = line.template.id
                elif name == 'note_cash':
                    res[name][line.id] = line.note
        return res

    def set_fields(self,  ids, name, value):
        if isinstance(ids, list):
            ids = ids[0]
        if not value:
            return
        document = self.browse( ids)
        if name == 'state_doc':
            self.write( ids, {'state':value, })
        elif name == 'template_invoice':
            self.write( ids, { 'template': value, })
        elif name == 'number_doc':
            if document.direct_document == 'input_goods':
                self.write( ids, { 'number_in': value, })
            else:
                self.write( ids, { 'number_our': value, })
        elif name == 'amount_doc':
            self.write( ids, { 'amount': value, })
        elif name == 'from_party_doc':
            if document.direct_document == 'input_goods':
                self.write( ids, { 'from_party': value, })
            else:
                self.write( ids, { 'to_party': value, })
        elif name == 'from_party_fnc':
            self.write( ids, { 'from_party': value, })
        elif name == 'to_party_fnc':
            self.write( ids, { 'to_party': value, })

    def template_select_get(self):
        context = Transaction().context
        template_obj = self.pool.get('ekd.document.template')
        raise Exception(str(context))
        template_ids = template_obj.search( ['type_account','=', 
                        context.get('direct_document', 'input_goods')])
        res=[]
        for template in template_obj.browse( template_ids):
            res.append([template.id,template.name])
        return res

    def template_search(self,  name, domain=[]):
        if name == 'template_bank':
            for table, exp, value in domain:
                return  [('template', 'ilike', value)]
        elif name == 'from_party_doc':
            document_obj = self.pool.get('ekd.document')
            table, exp, value = domain[0]
            find_ids = document_obj.search( [('from_party', 'ilike', value)])
            return [('document', 'in', find_ids)]
        elif name == 'to_party_doc':
            document_obj = self.pool.get('ekd.document')
            table, exp, value = domain[0]
            find_ids = document_obj.search( [('to_party', 'ilike', value)])
            return [('document', 'in', find_ids)]

    def get_rec_name(self,  ids, name):
        if not ids:
            return {}
        return self.pool.get('ekd.document').get_rec_name( ids, name)

    def on_change_document_base(self, vals):
        if not vals.get('document_base'):
            return {}
        model, model_id = vals.get('document_base').split(',')
        model_obj = self.pool.get(model)
        if model_id == '0':
            return {}
        model_line = model_obj.browse(int(model_id))
        lines_new = {}
        field_import = [
        'product_ref', 
        'type_tax', 
        'tax', 
        'type', 
        'currency', 
        'unit', 
        'currency_digits', 
        'unit_price', 
        'amount_tax', 
        'product', 
        'description', 
        'type_product', 
        'unit_digits', 
        'amount', 
        'quantity']

        if hasattr(model_obj, 'lines'):
            for line_new in model_line.lines:
                if line_new.type == 'line':
                    tmp_line = line_new.read(line_new.id, field_import)
                    tmp_line['state'] = 'draft'
                    lines_new.setdefault('add', []).append(tmp_line)
            return {
                'from_to_party': model_line.from_to_party.id,
                'parent': int(model_id),
                'lines':lines_new}
        else:
            return {
                'from_to_party': model_line.from_to_party.id,
                'parent': int(model_id)}

    def create(self, vals):
        later = {}
        vals = vals.copy()
        cursor = Transaction().cursor
        for field in vals:
            if field in self._columns\
                    and hasattr(self._columns[field], 'set'):
                later[field] = vals[field]
        for field in later:
            del vals[field]
        if cursor.nextid(self._table):
            cursor.setnextid(self._table, cursor.currid(self._table))
        new_id = super(DocumentInvoiceGoods, self).create( vals)
        invoice = self.browse( new_id)
        new_id = invoice.document.id
        cr = Transaction().cursor
        cr.execute('UPDATE "' + self._table + '" SET id = %s '\
                        'WHERE id = %s', (invoice.document.id, invoice.id))
        ModelStorage.delete(self, invoice.id)
        self.write( new_id, later)
        res = self.browse( new_id)
        return res.id

    def delete(self, ids):
        cr = Transaction().cursor
        doc_lines_obj = self.pool.get('ekd.document.line.product')
        for document in self.browse(ids):
            if document.state == 'deleted' and document.deleting:
                return super(DocumentInvoiceGoods, self).delete(ids)
            else:
                doc_lines_obj.write([x.id for x in document.lines], {'state': 'deleted', 'deleting':True})
                self.write(document.id, {'state': 'deleted', 'deleting':True})
        return True

    def button_add_number(self, ids):
        return self.new_number(ids)

    def button_post(self, ids):
        return self.post(ids)

    def button_obtained(self, ids):
        return self.obtained(ids)

    def button_delivered(self, ids):
        return self.delivered(ids)

    def button_paid(self, ids):
        return self.paid(ids)

    def button_part_paid(self, ids):
        return self.part_paid(ids)

    def button_to_pay(self, ids):
        return self.to_pay(ids)

    def button_send(self, ids):
        return self.send(ids)

    def button_print(self, ids):
        return self.print_document(ids)

    def button_cancel(self, ids):
        return self.cancel(ids)

    def button_draft(self, ids):
        return self.draft(ids)

    def button_restore(self, ids):
        return self.draft(ids)

    def new_number(self, ids):
        sequence_obj = self.pool.get('ir.sequence')
        for document in self.browse(ids):
            if document.template and document.template.sequence:
                sequence = sequence_obj.get_id(document.template.sequence.id)
            else:
                raise Exception('Error', 'Sequence for document not find!')
            self.write(document.id, {
                    'number_doc': sequence,
                    })

    def post(self, ids):
        return self.write(ids, {
            'state': 'posted',
            })

    def obtained(self, ids):
        return self.write(ids, {
            'state': 'obtained',
            })

    def delivered(self, ids):
        return self.write(ids, {
            'state': 'delivered',
            })

    def send(self, ids):
        return self.write(ids, {
            'state': 'sended',
            })

    def to_pay(self, ids):
        return self.write(ids, {
            'state': 'to_pay',
            })

    def paid(self, ids):
        return self.write(ids, {
            'state': 'paid',
            })

    def part_paid(self, ids):
        return self.write(ids, {
            'state': 'part_paid',
            })

    def print_document(self, ids):
        return self.write(ids, {
            'state': 'printed',
            })

    def draft(self, ids):
        return self.write(ids, {
                'state': 'draft',
                'deleting':False
                })

    def cancel(self, ids):
        return self.write(ids, {
                'state': 'canceled',
                })
예제 #21
0
class PayInvoiceUsingTransactionStart(BaseCreditCardViewMixin, ModelView):
    'Pay using Transaction Wizard'
    __name__ = 'account.invoice.pay_using_transaction.start'

    invoice = fields.Many2One(
        'account.invoice', 'Invoice', required=True, readonly=True
    )
    transaction_type = fields.Function(
        fields.Char("Transaction Type"), "on_change_with_transaction_type"
    )
    party = fields.Many2One('party.party', 'Party', readonly=True)
    gateway = fields.Many2One(
        'payment_gateway.gateway', 'Gateway', required=True,
        domain=[('users', '=', Eval('user'))],
        depends=['user']
    )
    method = fields.Function(
        fields.Char('Payment Gateway Method'), 'get_method'
    )
    use_existing_card = fields.Boolean(
        'Use existing Card?', states={
            'invisible': Eval('method') != 'credit_card'
        }, depends=['method']
    )
    payment_profile = fields.Many2One(
        'party.payment_profile', 'Payment Profile',
        domain=[
            ('party', '=', Eval('party')),
            ('gateway', '=', Eval('gateway')),
        ],
        states={
            'required': And(
                Eval('method') == 'credit_card', Bool(Eval('use_existing_card'))
            ),
            'invisible': ~Bool(Eval('use_existing_card'))
        }, depends=['method', 'use_existing_card', 'party', 'gateway']
    )
    user = fields.Many2One(
        "res.user", "Tryton User", readonly=True
    )
    amount = fields.Numeric(
        'Amount', digits=(16, Eval('currency_digits', 2)),
        required=True, depends=['currency_digits'],
    )
    currency_digits = fields.Function(
        fields.Integer('Currency Digits'),
        'get_currency_digits'
    )
    reference = fields.Char(
        'Reference', states={
            'invisible': Not(Eval('method') == 'manual'),
        }
    )

    company = fields.Many2One(
        'company.company', 'Company', readonly=True, required=True,
        domain=[
            ('id', If(Eval('context', {}).contains('company'), '=', '!='),
                Eval('context', {}).get('company', -1)),
        ],
    )
    credit_account = fields.Many2One(
        'account.account', 'Credit Account', required=True
    )
    transaction = fields.Many2One(
        'payment_gateway.transaction', "Transaction", domain=[
            ('party', '=', Eval('party')),
            ('gateway', '=', Eval('gateway')),
        ], states={
            'required': Eval('transaction_type') == 'refund',
            'invisible': Eval('transaction_type') != 'refund'
        }, depends=['party', 'transaction_type', 'gateway']
    )

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

        INV = Or(
            Eval('method') == 'manual',
            And(
                Eval('method') == 'credit_card',
                Bool(Eval('use_existing_card'))
            )
        )
        STATE1 = {
            'required': And(
                ~Bool(Eval('use_existing_card')),
                Eval('method') == 'credit_card',
                Eval('transaction_type') == 'charge',
            ),
            'invisible': INV
        }
        DEPENDS = ['use_existing_card', 'method', 'transaction_type']

        cls.owner.states.update(STATE1)
        cls.owner.depends.extend(DEPENDS)
        cls.number.states.update(STATE1)
        cls.number.depends.extend(DEPENDS)
        cls.expiry_month.states.update(STATE1)
        cls.expiry_month.depends.extend(DEPENDS)
        cls.expiry_year.states.update(STATE1)
        cls.expiry_year.depends.extend(DEPENDS)
        cls.csc.states.update(STATE1)
        cls.csc.depends.extend(DEPENDS)
        cls.swipe_data.states = {'invisible': INV}
        cls.swipe_data.depends = ['method']

        cls.credit_account.domain = [
            ('company', '=', Eval('company', -1)),
            ('kind', 'in', cls._credit_account_domain())
        ]
        cls.credit_account.depends = ['company']

    def get_currency_digits(self, name):  # pragma: no cover
        return self.invoice.currency_digits if self.invoice else 2

    def get_method(self, name=None):  # pragma: no cover
        """
        Return the method based on the gateway
        """
        return self.gateway.method

    @fields.depends('gateway')
    def on_change_gateway(self):  # pragma: no cover
        if self.gateway:
            self.method = self.gateway.method or None

    @fields.depends('invoice')
    def on_change_with_transaction_type(self, name=None):
        "If the receivable today is positive, it's a charge else refund"
        if self.invoice:
            if self.invoice.amount_to_pay_today >= 0:
                return 'charge'
            else:
                return 'refund'

    @classmethod
    def _credit_account_domain(cls):
        """
        Return a list of account kind
        """
        return ['receivable']

    @classmethod
    def view_attributes(cls):
        return [(
            '//group[@id="charge"]', 'states', {
                'invisible': Eval('transaction_type') != 'charge',
            }
        ), (
                '//group[@id="refund"]', 'states', {
                    'invisible': Eval('transaction_type') != 'refund',
                }
        )]
예제 #22
0
class NotebookRule(metaclass=PoolMeta):
    __name__ = 'lims.rule'

    analysis_sheet = fields.Boolean('For use in Analysis Sheets')
    apply_on_notebook = fields.Boolean('Apply directly on the Notebook',
        states={'readonly': ~And(
            Bool(Eval('analysis_sheet')), Eval('action') == 'edit')},
        depends=['analysis_sheet', 'action'])

    @staticmethod
    def default_analysis_sheet():
        return False

    @staticmethod
    def default_apply_on_notebook():
        return False

    def eval_condition(self, line):
        if self.analysis_sheet:
            return False
        return super().eval_condition(line)

    def eval_sheet_condition(self, line):
        for condition in self.conditions:
            if not condition.eval_sheet_condition(line):
                return False
        return True

    def exec_sheet_action(self, line):
        if self.action == 'add':
            self._exec_sheet_add(line)
        elif self.action == 'edit':
            if self.apply_on_notebook:
                self._exec_notebook_edit(line)
            else:
                self._exec_sheet_edit(line)

    def _exec_sheet_add(self, line):
        Typification = Pool().get('lims.typification')

        typification = Typification.search([
            ('product_type', '=', line.notebook_line.product_type),
            ('matrix', '=', line.notebook_line.matrix),
            ('analysis', '=', self.target_analysis),
            ('by_default', '=', True),
            ('valid', '=', True),
            ], limit=1)
        if not typification:
            return

        existing_line = self._get_existing_line(
            line.notebook_line.notebook.id, self.target_analysis.id)
        if not existing_line:
            self._exec_sheet_add_service(line, typification[0])

    def _exec_sheet_add_service(self, line, typification):
        cursor = Transaction().connection.cursor()
        pool = Pool()
        AnalysisLaboratory = pool.get('lims.analysis-laboratory')
        AnalysisDevice = pool.get('lims.analysis.device')
        Service = pool.get('lims.service')
        EntryDetailAnalysis = pool.get('lims.entry.detail.analysis')
        NotebookLine = pool.get('lims.notebook.line')
        AnalysisSheet = pool.get('lims.analysis_sheet')

        today = date.today()

        cursor.execute('SELECT DISTINCT(laboratory) '
            'FROM "' + AnalysisLaboratory._table + '" '
            'WHERE analysis = %s',
            (self.target_analysis.id,))
        laboratories = [x[0] for x in cursor.fetchall()]
        if not laboratories:
            return
        laboratory_id = laboratories[0]

        method_id = typification.method and typification.method.id or None

        cursor.execute('SELECT DISTINCT(device) '
            'FROM "' + AnalysisDevice._table + '" '
            'WHERE active IS TRUE '
                'AND analysis = %s  '
                'AND laboratory = %s '
                'AND by_default IS TRUE',
            (self.target_analysis.id, laboratory_id))
        devices = [x[0] for x in cursor.fetchall()]
        device_id = devices and devices[0] or None

        service_create = [{
            'fraction': line.notebook_line.fraction.id,
            'analysis': self.target_analysis.id,
            'urgent': True,
            'laboratory': laboratory_id,
            'method': method_id,
            'device': device_id,
            }]
        with Transaction().set_context(manage_service=True):
            new_service, = Service.create(service_create)

        Service.copy_analysis_comments([new_service])
        Service.set_confirmation_date([new_service])
        analysis_detail = EntryDetailAnalysis.search([
            ('service', '=', new_service.id)])
        if analysis_detail:
            EntryDetailAnalysis.create_notebook_lines(analysis_detail,
                line.notebook_line.fraction)
            EntryDetailAnalysis.write(analysis_detail, {
                'state': 'unplanned',
                })
            notebook_lines = NotebookLine.search([
                ('analysis_detail', 'in', [d.id for d in analysis_detail])])
            sheet = AnalysisSheet(Transaction().context.get(
                'lims_analysis_sheet'))
            notebook_lines = [nl for nl in notebook_lines if
                nl.get_analysis_sheet_template() == sheet.template.id]
            if notebook_lines:
                NotebookLine.write(notebook_lines, {'start_date': today})
                analysis_details = [nl.analysis_detail
                    for nl in notebook_lines]
                EntryDetailAnalysis.write(analysis_details,
                    {'state': 'planned'})
                sheet.create_lines(notebook_lines)

    def _exec_sheet_edit(self, line):
        pool = Pool()
        Field = pool.get('lims.interface.table.field')
        Data = pool.get('lims.interface.data')

        target_column = Field.search([
            ('table', '=', Transaction().context.get('lims_interface_table')),
            ('transfer_field', '=', True),
            ('related_line_field', '=', self.target_field),
            ])
        if not target_column:
            return
        target_field = target_column[0].name

        if line.notebook_line.analysis == self.target_analysis:
            sheet_line = Data(line.id)
        else:
            sheet_line = self._get_existing_line(
                line.notebook_line.notebook.id, self.target_analysis.id,
                Transaction().context.get('lims_interface_compilation'))
            if not sheet_line:
                return

        if sheet_line.annulled:
            return

        value = self.value
        if self.value.startswith('='):
            path = self.value[1:].split('.')
            field = path.pop(0)
            try:
                value = getattr(sheet_line, field)
                while path:
                    field = path.pop(0)
                    value = getattr(value, field)
            except AttributeError:
                value = None
        try:
            Data.write([sheet_line], {target_field: str(value)})
        except Exception as e:
            return

    def _exec_notebook_edit(self, line):
        pool = Pool()
        NotebookLine = pool.get('lims.notebook.line')
        Data = pool.get('lims.interface.data')
        AnalysisSheet = pool.get('lims.analysis_sheet')
        Field = pool.get('lims.interface.table.field')

        now = datetime.now()
        today = now.date()

        # update notebook line
        if line.notebook_line.analysis == self.target_analysis:
            notebook_line = NotebookLine(line.notebook_line.id)
        else:
            target_line = NotebookLine.search([
                ('notebook', '=', line.notebook_line.notebook),
                ('analysis', '=', self.target_analysis),
                ], order=[('repetition', 'DESC')], limit=1)
            if not target_line:
                return
            notebook_line = target_line[0]

        if notebook_line.accepted or notebook_line.annulled:
            return

        try:
            value = self.value
            if self.value.startswith('='):
                path = self.value[1:].split('.')
                field = path.pop(0)
                try:
                    value = getattr(line, field)
                    while path:
                        field = path.pop(0)
                        value = getattr(value, field)
                except AttributeError:
                    value = None
            setattr(notebook_line, self.target_field.name, value)
            if self.target_field.name in ('result', 'literal_result'):
                if not notebook_line.start_date:
                    notebook_line.start_date = today
                notebook_line.end_date = today
                if notebook_line.laboratory.automatic_accept_result:
                    notebook_line.accepted = True
                    notebook_line.acceptance_date = now
            notebook_line.save()
        except Exception as e:
            return

        # find analysis sheet line and update it
        if notebook_line.analysis_sheet:
            sheets = [notebook_line.analysis_sheet]
        else:
            template_id = notebook_line.get_analysis_sheet_template()
            if not template_id:
                return
            sheets = AnalysisSheet.search([
                ('template', '=', template_id),
                ('state', 'in', ['draft', 'active', 'validated'])
                ], order=[('id', 'DESC')])
        for s in sheets:
            with Transaction().set_context(
                    lims_interface_table=s.compilation.table.id):
                lines = Data.search([
                    ('compilation', '=', s.compilation.id),
                    ('notebook_line', '=', notebook_line.id),
                    ], limit=1)
                if not lines:
                    continue
                target_column = Field.search([
                    ('table', '=', s.compilation.table.id),
                    ('transfer_field', '=', True),
                    ('related_line_field', '=', self.target_field),
                    ])
                if not target_column:
                    return
                target_field = target_column[0].name
                try:
                    Data.write(lines, {target_field: str(value)})
                except Exception as e:
                    return

    def _get_existing_line(self, notebook_id, analysis_id,
            compilation_id=None):
        pool = Pool()
        NotebookLine = pool.get('lims.notebook.line')
        Data = pool.get('lims.interface.data')

        notebook_lines = NotebookLine.search([
            ('notebook', '=', notebook_id),
            ('analysis', '=', analysis_id),
            ])
        nl_ids = [nl.id for nl in notebook_lines]
        if not compilation_id:
            return bool(len(nl_ids))

        existing_line = Data.search([
            ('compilation', '=', compilation_id),
            ('notebook_line', 'in', nl_ids),
            ], order=[('notebook_line', 'DESC')], limit=1)
        return existing_line and existing_line[0] or None
예제 #23
0
class AddSalePaymentView(BaseCreditCardViewMixin, ModelView):
    """
    View for adding Sale Payments
    """
    __name__ = 'sale.payment.add_view'

    sale = fields.Many2One('sale.sale', 'Sale', required=True, readonly=True)

    party = fields.Many2One('party.party', 'Party', readonly=True)
    gateway = fields.Many2One('payment_gateway.gateway',
                              'Gateway',
                              required=True,
                              domain=[('users', '=', Eval('user'))],
                              depends=['user'])
    currency_digits = fields.Function(fields.Integer('Currency Digits'),
                                      'get_currency_digits')
    method = fields.Function(fields.Char('Payment Gateway Method'),
                             'get_method')
    use_existing_card = fields.Boolean(
        'Use existing Card?',
        states={'invisible': Eval('method') != 'credit_card'},
        depends=['method'])
    payment_profile = fields.Many2One(
        'party.payment_profile',
        'Payment Profile',
        domain=[
            ('party', '=', Eval('party')),
            ('gateway', '=', Eval('gateway')),
        ],
        states={
            'required':
            And(
                Eval('method') == 'credit_card',
                Bool(Eval('use_existing_card'))),
            'invisible':
            ~Bool(Eval('use_existing_card'))
        },
        depends=['method', 'use_existing_card', 'party', 'gateway'])
    amount = fields.Numeric(
        'Amount',
        digits=(16, Eval('currency_digits', 2)),
        required=True,
        depends=['currency_digits'],
    )
    reference = fields.Char('Reference',
                            states={
                                'invisible': Not(Eval('method') == 'manual'),
                            })
    user = fields.Many2One("res.user", "Tryton User", readonly=True)

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

        INV = Or(
            Eval('method') == 'manual',
            And(
                Eval('method') == 'credit_card',
                Bool(Eval('use_existing_card'))))
        STATE1 = {
            'required':
            And(~Bool(Eval('use_existing_card')),
                Eval('method') == 'credit_card'),
            'invisible':
            INV
        }
        DEPENDS = ['use_existing_card', 'method']

        cls.owner.states.update(STATE1)
        cls.owner.depends.extend(DEPENDS)
        cls.number.states.update(STATE1)
        cls.number.depends.extend(DEPENDS)
        cls.expiry_month.states.update(STATE1)
        cls.expiry_month.depends.extend(DEPENDS)
        cls.expiry_year.states.update(STATE1)
        cls.expiry_year.depends.extend(DEPENDS)
        cls.csc.states.update(STATE1)
        cls.csc.depends.extend(DEPENDS)
        cls.swipe_data.states = {'invisible': INV}
        cls.swipe_data.depends = ['method']

    def get_currency_digits(self, name):
        return self.sale.currency_digits if self.sale else 2

    def get_method(self, name=None):
        """
        Return the method based on the gateway
        """
        return self.gateway.method

    @fields.depends('gateway')
    def on_change_gateway(self):
        if self.gateway:
            return {
                'method': self.gateway.method,
            }
        return {}
class Party(ModelSQL, ModelView):
    """Pary module, extended for account_invoice_ar"""

    __name__ = 'party.party'

    iva_condition = fields.Selection(
            [
                ('', ''),
                ('responsable_inscripto', 'Responsable Inscripto'),
                ('exento', 'Exento'),
                ('consumidor_final', 'Consumidor Final'),
                ('monotributo', 'Monotributo'),
                ('no_alcanzado', 'No alcanzado'),
            ],
            'Condicion ante el IVA',
            states={
                'readonly': ~Eval('active', True),
                'required': Equal(Eval('vat_country'), 'AR'),
                },
            depends=['active'],
            )
    company_name = fields.Char('Company Name',
            states={
                'readonly': ~Eval('active', True),
                },
            depends=['active'],
            )
    company_type = fields.Selection(
            [
                ('', ''),
                ('cooperativa', 'Cooperativa'),
                ('srl', 'SRL'),
                ('sa', 'SA'),
                ('s_de_h', 'S de H'),
                ('estado', 'Estado'),
                ('exterior', 'Exterior'),
            ],
            'Company Type',
            states={
                'readonly': ~Eval('active', True),
                },
            depends=['active'],
            )
    iibb_type = fields.Selection(
            [
                ('', ''),
                ('cm', 'Convenio Multilateral'),
                ('rs', 'Regimen Simplificado'),
                ('exento', 'Exento'),
            ],
            'Inscripcion II BB',
            states={
                'readonly': ~Eval('active', True),
                },
            depends=['active'],
            )
    iibb_number = fields.Char('Nro .II BB',
            states={
                'readonly': ~Eval('active', True),
                'required': And(Not(Equal(Eval('iibb_type'), 'exento')), Bool(Eval('iibb_type')))
                },
            depends=['active'],
            )
    primary_activity_code = fields.Selection(CODES,
            'Primary Activity Code',
            states={
                'readonly': ~Eval('active', True),
                },
            depends=['active'],
            )
    secondary_activity_code = fields.Selection(CODES,
            'Secondary Activity Code',
            states={
                'readonly': ~Eval('active', True),
                },
            depends=['active'],
            )
    start_activity_date = fields.Date('Start activity date',
            states={
                'readonly': ~Eval('active', True),
                },
            depends=['active'],
            )
    vat_number = fields.Char('VAT Number', help="Value Added Tax number",
        states={
            'readonly': ~Eval('active', True),
            'required': And(Bool(Eval('vat_country')), Not(Equal(Eval('iva_condition'), 'consumidor_final'))),
            },
        depends=['active', 'vat_country', 'iva_condition'])
    controlling_entity = fields.Char('Entidad controladora', help="Controlling entity",
        states={
            'readonly': ~Eval('active', True),
            },
        depends=['active'])
    controlling_entity_number = fields.Char('Nro. entidad controladora', help="Controlling entity",
        states={
            'readonly': ~Eval('active', True),
            },
        depends=['active'])
    
    tipo_documento = fields.Selection(TIPO_DOCUMENTO,
                                      'Tipo documento', 
                                      states={
                                          'readonly': ~Eval('active', True),
                                      }, required=True, depends=['active'])

    @staticmethod
    def default_vat_country():
        return 'AR'

    @classmethod
    def __setup__(cls):
        super(Party, cls).__setup__()
        cls._buttons.update({
            'get_afip_data': {},
        })
        cls._error_messages.update({
            'unique_vat_number': 'The VAT number must be unique in each country.',
            'vat_number_not_found': 'El CUIT no ha sido encontrado',
        })

    @classmethod
    def validate(cls, parties):
        for party in parties:
            if party.iva_condition != u'consumidor_final' and bool(party.vat_number):
                party.check_vat()

            if bool(party.vat_number) and bool(party.vat_country):
                data = cls.search([('vat_number','=', party.vat_number),
                                   ('vat_country','=', party.vat_country),
                                   ])
                if len(data) != 1:
                    cls.raise_user_error('unique_vat_number')

    # Button de AFIP
    @classmethod
    @ModelView.button_action('account_invoice_ar.wizard_get_afip_data')
    def get_afip_data(cls, parties):
        pass
예제 #25
0
class Sale:
    "Sale"
    __name__ = 'sale.sale'

    is_dhl_de_shipping = fields.Function(
        fields.Boolean('Is Shipping', readonly=True), 'get_is_dhl_de_shipping')

    dhl_de_product_code = fields.Selection(
        DHL_DE_PRODUCTS,
        'DHL DE Product Code',
        states=STATES,
        depends=['state', 'is_dhl_de_shipping'])
    dhl_de_export_type = fields.Selection(DHL_DE_EXPORT_TYPES,
                                          'DHL DE Export Type',
                                          states=INTERNATIONAL_STATES,
                                          depends=INTERNATIONAL_DEPENDS)
    dhl_de_export_type_description = fields.Char(
        'Export Type Description',
        states={
            'required':
            And(
                Eval('state').in_(['confirmed', 'processing', 'done']),
                Bool(Eval('is_dhl_de_shipping')),
                Bool(Eval('is_international_shipping'))),
            'readonly':
            Eval('state') == 'done',
        },
        depends=INTERNATIONAL_DEPENDS)
    dhl_de_terms_of_trade = fields.Selection(DHL_DE_INCOTERMS,
                                             'Terms of Trade (incoterms)',
                                             states=INTERNATIONAL_STATES,
                                             depends=INTERNATIONAL_DEPENDS)

    @classmethod
    def view_attributes(cls):
        return super(Sale, cls).view_attributes() + [
            ('//page[@id="dhl_de"]', 'states', {
                'invisible': ~Bool(Eval('is_dhl_de_shipping'))
            }),
            ('//group[@id="dhl_de_international"]', 'states', {
                'invisible': ~Bool(Eval('is_international_shipping'))
            })
        ]

    @staticmethod
    def default_dhl_de_product_code():
        Config = Pool().get('sale.configuration')
        config = Config(1)
        return config.dhl_de_product_code

    @staticmethod
    def default_dhl_de_export_type():
        Config = Pool().get('sale.configuration')
        config = Config(1)
        return config.dhl_de_export_type

    @staticmethod
    def default_dhl_de_terms_of_trade():
        Config = Pool().get('sale.configuration')
        config = Config(1)
        return config.dhl_de_terms_of_trade

    @classmethod
    @ModelView.button
    @Workflow.transition('quotation')
    def quote(cls, sales):
        """
        Downstream implementation of quote method which provides a default
        value to the dhl_de_export_type field.
        """
        for sale in sales:
            if sale.is_dhl_de_shipping and sale.is_international_shipping:
                sale.set_dhl_de_export_type_description()
                sale.save()

        super(Sale, cls).quote(sales)

    def set_dhl_de_export_type_description(self):
        """
        This method sets a default export type description if none is set
        """
        if self.dhl_de_export_type_description:
            return

        if self.description:
            self.dhl_de_export_type_description = self.description
        else:
            self.dhl_de_export_type_description = ', '.join(
                map(lambda line: line.type == 'line' and line.product.name,
                    self.lines))

    def get_is_dhl_de_shipping(self, name):
        """
        Ascertains if the sale is done using DHL (DE)
        """
        return self.carrier and self.carrier.carrier_cost_method == 'dhl_de'

    @fields.depends('is_dhl_de_shipping', 'carrier')
    def on_change_carrier(self):
        """
        Show/Hide dhl de Tab in view on change of carrier
        """
        super(Sale, self).on_change_carrier()

        self.is_dhl_de_shipping = self.carrier and \
            self.carrier.carrier_cost_method == 'dhl_de' or None

    def _get_shipment_sale(self, Shipment, key):
        """
        Downstream implementation which adds dhl-specific fields to the unsaved
        Shipment record.
        """
        ShipmentOut = Pool().get('stock.shipment.out')

        shipment = super(Sale, self)._get_shipment_sale(Shipment, key)

        if Shipment == ShipmentOut and self.is_dhl_de_shipping:
            shipment.dhl_de_product_code = self.dhl_de_product_code
            shipment.dhl_de_export_type = self.dhl_de_export_type
            shipment.dhl_de_export_type_description = \
                self.dhl_de_export_type_description
            shipment.dhl_de_terms_of_trade = self.dhl_de_terms_of_trade

        return shipment
예제 #26
0
class SaleLine:
    __name__ = 'sale.line'

    is_round_off = fields.Boolean('Round Off', readonly=True)

    delivery_mode = fields.Selection(
        [
            (None, ''),
            ('pick_up', 'Pick Up'),
            ('ship', 'Ship'),
        ],
        'Delivery Mode',
        states={
            'invisible':
            Eval('type') != 'line',
            'required':
            And(Eval('type') == 'line', Bool(Eval('product_type_is_goods')))
        },
        depends=['type', 'product_type_is_goods'])

    product_type_is_goods = fields.Function(
        fields.Boolean('Product Type is Goods?'), 'get_product_type_is_goods')

    @classmethod
    def __register__(cls, module_name):
        super(SaleLine, cls).__register__(module_name)

        TableHandler = backend.get('TableHandler')
        cursor = Transaction().cursor

        table = TableHandler(cursor, cls, module_name)

        table.not_null_action('delivery_mode', action='remove')

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

        # Hide product and unit fields.
        cls.product.states['invisible'] |= Bool(Eval('is_round_off'))
        cls.unit.states['invisible'] |= Bool(Eval('is_round_off'))
        cls.delivery_mode.states['invisible'] |= Bool(Eval('is_round_off'))
        cls.product.depends.insert(0, 'is_round_off')
        cls.unit.depends.insert(0, 'is_round_off')

    @fields.depends('product', 'unit', 'quantity', '_parent_sale.party',
                    '_parent_sale.currency', '_parent_sale.sale_date',
                    'delivery_mode', '_parent_sale.channel',
                    '_parent_sale.shipment_address', 'warehouse',
                    '_parent_sale.warehouse')
    def on_change_delivery_mode(self):
        """
        This method can be overridden by downstream modules to make changes
        according to delivery mode. Like change taxes according to delivery
        mode.
        """
        return {}

    @staticmethod
    def default_is_round_off():
        return False

    def get_invoice_line(self, invoice_type):
        SaleConfiguration = Pool().get('sale.configuration')
        InvoiceLine = Pool().get('account.invoice.line')

        if not self.is_round_off:
            return super(SaleLine, self).get_invoice_line(invoice_type)

        # The line is a round off line and apply the logic here.

        # Check if the invoice line already exists for the sale line
        # If yes, then no line needs to be created
        # XXX: What if the invoice was cancelled ?
        if self.invoice_lines:
            return []

        round_down_account = SaleConfiguration(1).round_down_account
        if not round_down_account:
            self.raise_user_error(
                '''Set round down account from Sale Configuration to
                add round off line''')

        invoice_line = InvoiceLine()
        invoice_line.origin = self
        invoice_line.account = round_down_account
        invoice_line.unit_price = self.unit_price
        invoice_line.description = self.description

        # For positive sales transactions (where the order is effectively
        # a positive total), the round_down is applied on out_invoice
        # and if overall order total is negative, then the round_down is
        # tied to credit note.
        if self.sale.total_amount >= Decimal('0'):
            if invoice_type == 'out_credit_note':
                # positive order looking for credit note
                return []
            invoice_line.quantity = self.quantity
        else:
            if invoice_type == 'out_invoice':
                # negative order looking for invoice
                return []
            invoice_line.quantity = -self.quantity

        return [invoice_line]

    @staticmethod
    def default_delivery_mode():
        Channel = Pool().get('sale.channel')
        User = Pool().get('res.user')

        user = User(Transaction().user)
        sale_channel = user.current_channel
        if Transaction().context.get('current_channel'):
            sale_channel = Channel(
                Transaction().context.get('current_channel'))
        return sale_channel and sale_channel.delivery_mode

    def get_warehouse(self, name):
        """
        Return the warehouse from the channel for orders being picked up and the
        backorder warehouse for orders with ship.
        """
        if self.sale.channel.source == 'pos' and \
                self.delivery_mode == 'ship' and \
                self.sale.channel.backorder_warehouse:
            return self.sale.channel.backorder_warehouse.id
        return super(SaleLine, self).get_warehouse(name)

    def serialize(self, purpose=None):
        """
        Serialize for the purpose of POS
        """
        if purpose == 'pos':
            return {
                'id': self.id,
                'description': self.description,
                'product': self.product and {
                    'id':
                    self.product.id,
                    'code':
                    self.product.code,
                    'rec_name':
                    self.product.rec_name,
                    'default_image':
                    self.product.default_image
                    and self.product.default_image.id,
                },
                'unit': self.unit and {
                    'id': self.unit.id,
                    'rec_name': self.unit.rec_name,
                },
                'unit_price': self.unit_price,
                'quantity': self.quantity,
                'amount': self.amount,
                'delivery_mode': self.delivery_mode
            }
        elif hasattr(super(SaleLine, self), 'serialize'):
            return super(SaleLine, self).serialize(purpose)  # pragma: no cover

    def get_product_type_is_goods(self, name):
        """
        Return True if product is of type goods
        """
        if self.product and self.product.type == 'goods':
            return True
        return False
예제 #27
0
class Sale:
    "Sale"
    __name__ = 'sale.sale'

    is_dpd_shipping = fields.Function(
        fields.Boolean('Is Shipping', readonly=True), 'get_is_dpd_shipping')

    dpd_product = fields.Selection(DPD_PRODUCTS,
                                   'DPD Product',
                                   states=STATES,
                                   depends=['state', 'is_dpd_shipping'])
    dpd_customs_terms = fields.Selection(
        [
            (None, ''),
            ('01', 'DAP, cleared'),
            ('02', 'DDP, delivered duty paid (incl. duties and excl. Taxes'),
            ('03', 'DDP, delivered duty paid (incl duties and taxes) 05 = ex '
             'works (EXW)'),
            ('06', 'DAP'),
        ],
        'DPD customs terms',
        states={
            'readonly':
            Eval('state') == 'done',
            'invisible':
            ~Eval('is_international_shipping'),
            'required':
            And(Bool(Eval('is_dpd_shipping')),
                Bool(Eval('is_international_shipping'))),
        },
        depends=['state', 'dpd_product'])

    @classmethod
    def view_attributes(cls):
        return super(Sale, cls).view_attributes() + [
            ('//page[@id="dpd"]', 'states', {
                'invisible': ~Bool(Eval('is_dpd_shipping'))
            })
        ]

    @staticmethod
    def default_dpd_product():
        Config = Pool().get('sale.configuration')
        config = Config(1)
        return config.dpd_product

    @fields.depends('is_dpd_shipping', 'carrier')
    def on_change_carrier(self):
        """
        Show/Hide DPD Tab in view on change of carrier
        """
        super(Sale, self).on_change_carrier()

        self.is_dpd_shipping = self.carrier and \
            self.carrier.carrier_cost_method == 'dpd' or None

    def get_is_dpd_shipping(self, name):
        """
        Check if shipping is from DPD
        """
        return self.carrier and self.carrier.carrier_cost_method == 'dpd'

    def _get_shipment_sale(self, Shipment, key):
        """
        Downstream implementation which adds dpd-specific fields to the unsaved
        Shipment record.
        """
        shipment = super(Sale, self)._get_shipment_sale(Shipment, key)

        if Shipment.__name__ == 'stock.shipment.out' and self.is_dpd_shipping:
            shipment.dpd_customs_terms = self.dpd_customs_terms
            shipment.dpd_product = self.dpd_product

        return shipment
예제 #28
0
# -*- coding: utf-8 -*-
"""
    sale.py

    :copyright: (c) 2015 by Openlabs Technologies & Consulting (P) Limited
    :license: BSD, see LICENSE for more details.
"""
from trytond.model import fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, Bool, And

__all__ = ['SaleLine', 'SaleConfiguration', 'Sale']
__metaclass__ = PoolMeta

STATE = ~And(Eval('type') == 'line', Bool(Eval('product')))
DEPENDS = ['type', 'product']


class SaleLine:
    __name__ = 'sale.line'

    return_policy_at_sale = fields.Many2One(
        'sale.return.policy',
        'Return Policy at Sale',
        states={'invisible': Eval('type') != 'line'},
        depends=['type'])

    effective_return_policy_at_sale = fields.Function(
        fields.Many2One('sale.return.policy',
                        'Effective Return Policy at Sale',
                        states={'invisible': Eval('type') != 'line'},
예제 #29
0
    'invisible': Not(In(Eval('ct_kind_analytic', ''), _PARTY + _PRODUCT)),
}

_DT_PRODUCT_STATES = {
    'invisible': Not(In(Eval('dt_kind_analytic', ''), _PRODUCT)),
}

_CT_PRODUCT_STATES = {
    'invisible': Not(In(Eval('ct_kind_analytic', ''), _PRODUCT)),
}

_ACC_PRODUCT_STATES = {
    'required':
    Bool(Eval('product')),
    'invisible':
    And(Not(In(Eval('dt_kind_analytic', ''), _PRODUCT)),
        Not(In(Eval('ct_kind_analytic', ''), _PRODUCT))),
}


class LineWest(ModelSQL, ModelView):
    "Lines of business operations west standart"
    _name = "ekd.account.move.line.west"
    _description = __doc__
    _inherits = {'ekd.account.move.line': 'line'}

    line = fields.Many2One('ekd.account.move.line',
                           'Entries',
                           ondelete="CASCADE",
                           states=_MOVE_STATES,
                           depends=_MOVE_DEPENDS)
    period = fields.Many2One('ekd.period', 'Period')
예제 #30
0
 def __setup__(cls):
     super(Template, cls).__setup__()
     cls.info_ratio.states['readonly'] = Eval('product_type_printery', 'otros') == 'papel',
     cls.list_price.states['readonly'] = And(Eval('product_type_printery', 'otros') == 'papel', Bool(Eval('use_info_unit')))