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 __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)})
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'))), }), ]
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'), '')), ]
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')), }, })
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')), }, })
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')
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 __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')))
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
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'
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)
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')), }, })
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')
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), )
_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'),
def search_has_result(cls, field_name, clause): return [(And(Bool(Eval('date_tested')), Bool(Eval('lab_result_state'))), clause[1], clause[2])]
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:]), ]
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')))
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', })
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', } )]
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
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
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
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
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
# -*- 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'},
'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')
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')))