class Work(DeactivableMixin, ModelSQL, ModelView): 'Work' __name__ = 'timesheet.work' name = fields.Char('Name', states={ 'invisible': Bool(Eval('origin')), 'required': ~Eval('origin'), }, depends=['origin'], help="The main identifier of the work.") origin = fields.Reference( 'Origin', selection='get_origin', states={ 'invisible': Bool(Eval('name')), 'required': ~Eval('name'), }, depends=['name'], help="Use to relate the time spent to other records.") duration = fields.Function( fields.TimeDelta('Timesheet Duration', 'company_work_time', help="Total time spent on this work."), 'get_duration') timesheet_start_date = fields.Date( 'Timesheet Start', domain=[ If( Eval('timesheet_start_date') & Eval('timesheet_end_date'), ('timesheet_start_date', '<=', Eval('timesheet_end_date')), ()), ], depends=['timesheet_end_date'], help="Restrict adding lines before the date.") timesheet_end_date = fields.Date( 'Timesheet End', domain=[ If( Eval('timesheet_start_date') & Eval('timesheet_end_date'), ('timesheet_end_date', '>=', Eval('timesheet_start_date')), ()), ], depends=['timesheet_start_date'], help="Restrict adding lines after the date.") company = fields.Many2One('company.company', 'Company', required=True, select=True, help="Make the work belong to the company.") timesheet_lines = fields.One2Many('timesheet.line', 'work', 'Timesheet Lines', depends=['active'], states={ 'readonly': Not(Bool(Eval('active'))), }, help="Spend time on this work.") # Self referring field to use for aggregation in graph view work = fields.Function(fields.Many2One('timesheet.work', 'Work'), 'get_work') @classmethod def __setup__(cls): super(Work, cls).__setup__() t = cls.__table__() cls._sql_constraints += [ ('origin_unique', Unique(t, t.origin, t.company), 'The origin must be unique per company.'), ] cls._error_messages.update({ 'mismatch_company': ('The company of the work "%(work)s" ' 'is different than the origin\'s company'), }) @classmethod def __register__(cls, module_name): table_h = cls.__table_handler__(module_name) table = cls.__table__() cursor = Transaction().connection.cursor() super(Work, cls).__register__(module_name) # Migration from 4.0: remove required on name table_h.not_null_action('name', 'remove') # Migration from 4.0: remove parent, left and right if table_h.column_exist('parent'): id2name = {} id2parent = {} cursor.execute(*table.select(table.id, table.parent, table.name)) for id_, parent, name in cursor: id2name[id_] = name id2parent[id_] = parent for id_, name in id2name.items(): parent = id2parent[id_] while parent: name = '%s\\%s' % (id2name[parent], name) parent = id2parent[parent] cursor.execute( *table.update([table.name], [name], where=table.id == id_)) table_h.drop_column('parent') table_h.drop_column('left') table_h.drop_column('right') # Migration from 4.0: remove timesheet_available if table_h.column_exist('timesheet_available'): cursor.execute(*table.delete( where=table.timesheet_available == False)) table_h.drop_column('timesheet_available') @staticmethod def default_company(): return Transaction().context.get('company') @classmethod def _get_origin(cls): 'Return list of Model names for origin Reference' return [] @classmethod def get_origin(cls): Model = Pool().get('ir.model') models = cls._get_origin() models = Model.search([ ('model', 'in', models), ]) return [('', '')] + [(m.model, m.name) for m in models] @classmethod def get_duration(cls, works, name): pool = Pool() Line = pool.get('timesheet.line') transaction = Transaction() cursor = transaction.connection.cursor() context = transaction.context table_w = cls.__table__() line = Line.__table__() ids = [w.id for w in works] durations = dict.fromkeys(ids, None) where = Literal(True) if context.get('from_date'): where &= line.date >= context['from_date'] if context.get('to_date'): where &= line.date <= context['to_date'] if context.get('employees'): where &= line.employee.in_(context['employees']) query_table = table_w.join(line, 'LEFT', condition=line.work == table_w.id) for sub_ids in grouped_slice(ids): red_sql = reduce_ids(table_w.id, sub_ids) cursor.execute(*query_table.select(table_w.id, Sum(line.duration), where=red_sql & where, group_by=table_w.id)) for work_id, duration in cursor.fetchall(): # SQLite uses float for SUM if duration and not isinstance(duration, datetime.timedelta): duration = datetime.timedelta(seconds=duration) durations[work_id] = duration return durations def get_work(self, name): return self.id def get_rec_name(self, name): if self.origin: return self.origin.rec_name else: return self.name @classmethod def search_rec_name(cls, name, clause): if clause[1].startswith('!') or clause[1].startswith('not '): bool_op = 'AND' else: bool_op = 'OR' return [ bool_op, ('name', ) + tuple(clause[1:]), ] + [('origin.rec_name', ) + tuple(clause[1:]) + (origin, ) for origin in cls._get_origin()] @classmethod def copy(cls, works, default=None): if default is None: default = {} else: default = default.copy() default.setdefault('timesheet_lines', None) return super(Work, cls).copy(works, default=default) @classmethod def validate(cls, works): super(Work, cls).validate(works) for work in works: if work.origin and not work._validate_company(): cls.raise_user_error('mismatch_company', { 'work': work.rec_name, }) def _validate_company(self): return True @classmethod def search_global(cls, text): for record, rec_name, icon in super(Work, cls).search_global(text): icon = icon or 'tryton-clock' yield record, rec_name, icon @property def hours(self): if not self.duration: return 0 return self.duration.total_seconds() / 60 / 60
class PartyPatient(ModelSQL, ModelView): 'Party' __name__ = 'party.party' upi = fields.Function(fields.Char('UPI', help='Unique Party Identifier'), 'get_upi_display', searcher='search_upi') firstname = fields.Char('First name', states=_STATES, depends=_DEPENDS, select=True) middlename = fields.Char('Middle Name', states=_STATES, depends=_DEPENDS, help="Middle name or names of Patient") maiden_name = fields.Char( 'Maiden Name', states={'invisible': Or(Not(In(Eval('marital_status'), ['m', 'c', 'w', 'd', 'x'])), Equal(Eval('sex'), 'm'))} ) mother_maiden_name = fields.Char("Mother's Maiden Name", states=_STATES, depends=_DEPENDS, help="Mother's Maiden Name") father_name = fields.Char("Father's Name", states=_STATES, depends=_DEPENDS, help="Father's Name") sex_display = fields.Function(fields.Char('Sex'), 'get_sex_display') # gender vs sex: According to the AMA Manual of Style : # Gender refers to the psychological/societal aspects of being male # or female, sex refers specifically to the physical aspects. # Do not interchange alt_ids = fields.Function(fields.Char('Alternate IDs'), 'get_alt_ids', searcher='search_alt_ids') medical_record_num = fields.Function( fields.Char('Medical Record Num.'), 'get_alt_ids', searcher='search_alt_ids') suffix = fields.Selection([ (None, ''), ('jr', 'Jr. - Junior'), ('sr', 'Sr. - Senior'), ('II', 'II - The Second'), ('III', 'III - The Third'), ], 'Suffix', states=_STATES, depends=_DEPENDS) marital_status_display = fields.Function(fields.Char('Marital Status'), 'get_marital_status_display') relatives = fields.One2Many('party.relative', 'party', 'Relatives') reverse_relatives = fields.One2Many('party.relative', 'relative', 'Related To', readonly=True) birth_country = fields.Many2One( 'country.country', 'Country of Birth', states={'invisible': Not(Bool(Eval('is_person')))}) birth_subdiv = fields.Many2One( 'country.subdivision', 'Place of Birth', depends=['birth_country'], domain=[('country', '=', Eval('birth_country'))], states={'invisible': Not(Bool(Eval('is_person')))}) birthplace = fields.Function(fields.Char('Place of Birth'), 'get_rec_name') current_age = fields.Function(fields.Char('Age'), 'get_current_age') @classmethod def __setup__(cls): super(PartyPatient, cls).__setup__() # Error Message cls._error_messages.update({ 'future_dob_error': 'Future Birth Error\n\nDate of birth cannot be in the future.', 'unidentified_or_altid': 'Indentity Verification Error\n\n' 'Please enter an Alternate ID or check Undentified.\n' }) # field behaviour modifications s = cls.name.states if cls.name.states else {} s['readonly'] = Bool(Eval('is_person')) cls.name.states = s.copy() cls.ref.states['readonly'] = True cls.lastname.select = True cls.sex.selection = [(None, '')] + SEX_OPTIONS cls.marital_status.selection = [(None, '')] + MARITAL_STATUSES cls.internal_user.states = { 'invisible': Not(Bool(Eval('is_healthprof'))), 'required': False, } cls.alternative_ids.states = { 'invisible': Not(Eval('is_person', False))} # field label modifications cls.ref.string = "UPI" cls.insurance.string = "Insurance Plans" cls.alternative_ids.string = 'Alternate IDs' cls.dob.string = 'Date of Birth' # help text mods cls.ref.help = "Unique Party Indentifier" cls.alias.help = "Pet-name or other name by which party is known" cls.internal_user.help = ' '.join([ 'In order for this health professional to use ' 'the system, an internal user account must be assigned. ' 'This health professional will have a user account in this ' 'instance only.']) @classmethod def validate(cls, parties): super(PartyPatient, cls).validate(parties) for party in parties: party.check_dob() if is_not_synchro(): party.check_party_warning() def check_dob(self): if self.dob and self.dob > date.today(): self.raise_user_error('future_dob_error') def check_party_warning(self): '''validates that a party being entered as verified has an alt-id if there is no alt-id, then the party should be labeled as unidentified ''' if (self.is_person and self.is_patient and len(self.alternative_ids) == 0 and not self.unidentified): self.raise_user_error('unidentified_or_altid') def get_rec_name(self, name): if name == 'birthplace': return ', '.join([x.name for x in filter(None, [self.birth_country, self.birth_subdiv])]) else: return self.name @staticmethod def default_alternative_identification(): return True @staticmethod def default_unidentified(): return False @staticmethod def default_birth_country(): country, = Pool().get('country.country').search([('code', '=', 'JM')]) return country.id @fields.depends('lastname', 'firstname', 'middlename') def on_change_with_name(self, *arg, **kwarg): namelist = [] if self.lastname: namelist.append(''.join([self.lastname, ','])) if self.firstname: namelist.append(self.firstname) if self.middlename: namelist.append(self.middlename) return ' '.join(namelist) @classmethod def get_upi_display(cls, instances, name): return dict([(i.id, 'NN-%s' % i.ref if i.is_patient and i.unidentified else i.ref) for i in instances]) @classmethod def search_upi(cls, field_name, clause): # TODO: Fix this to work for 'in' and 'like' clauses fld, operator, operand = clause if (isinstance(operand, six.string_types) and NNre.match(operand)): # searching for NN- records, so auto-append unidentified=True operand = u''.join(NNre.split(operand)) if operand == u'%%': operand = '%' return ['AND', ('ref', operator, operand), ('unidentified', '=', True)] else: return [replace_clause_column(clause, 'ref')] def get_sex_display(self, field_name): sex_dict = dict(SEX_OPTIONS) return sex_dict.get(self.sex, '') def get_alt_ids(self, field_name): here = ThisInstitution() id_type_map = dict(ALTERNATIVE_ID_TYPES) if (field_name == 'medical_record_num'): for altid in self.alternative_ids: if (altid.alternative_id_type == 'medical_record' and (altid.issuing_institution and altid.issuing_institution.id == here)): return altid.code return '--' else: altids = [] for altid in self.alternative_ids: if (altid.alternative_id_type == 'medical_record' and altid.issuing_institution and altid.issuing_institution.id == here): continue else: a_type = id_type_map.get(altid.alternative_id_type, altid.alternative_id_type) if (altid.alternative_id_type == 'medical_record' and altid.issuing_institution): a_type = '{} MRN'.format( altid.issuing_institution.name.name) elif altid.alternative_id_type == 'medical_record': a_type = 'Unknown MRN' altids.append('{} {}'.format(a_type, altid.code)) return '; '.join(altids) @classmethod def search_alt_ids(cls, field_name, clause): if field_name == 'medical_record_num': return ['AND', ('alternative_ids.alternative_id_type', '=', 'medical_record'), ('alternative_ids.code',)+tuple(clause[1:])] else: return [ 'AND', ('alternative_ids.alternative_id_type', '!=', 'medical_record'), ('alternative_ids.code', clause[1], clause[2])] def get_marital_status_display(s, n): return make_selection_display()(s, 'marital_status') @classmethod def generate_puid(cls): # Add a default random string in the ref field. # The STRSIZE constant provides the length of the HIN # The format of the UPC is XXXNNNXXX STRSIZE = 9 letters = ('ABCDEFGHJKLMNPRTUWXY') digits = '0123456789' # letters removed = IOQSVZ because they look too similar to numbers # or to other letters. hin = '' for x in range(STRSIZE): if (x < 3 or x > 5): hin = hin + random.choice(letters) else: hin = hin + random.choice(digits) return hin @classmethod def create(cls, vlist): Configuration = Pool().get('party.configuration') vlist = [x.copy() for x in vlist] for values in vlist: if not 'ref' in values or not values['ref']: values['ref'] = cls.generate_puid() if 'is_person' in values and not values['is_person']: values['ref'] = 'NP-' + values['ref'] if not values.get('code'): # Use the company name . Initially, use the name # since the company hasn't been created yet. institution_id = ThisInstitution() if institution_id: institution = Pool().get( 'gnuhealth.institution')(institution_id) suffix = institution.code else: suffix = Transaction().context.get('company.rec_name')\ or values['name'] values['code'] = '-'.join([str(x) for x in (uuid.uuid4(), suffix)]) values.setdefault('addresses', None) return super(PartyPatient, cls).create(vlist) @classmethod def get_current_age(cls, instances, name): c = Transaction().cursor tbl = cls.__table__() qry = "\n".join([ "SELECT a.id as id, " "CASE WHEN a.dob is Null THEN '--'::varchar " "ELSE regexp_replace(AGE(a.dob)::varchar, " "' ([ymd])[ayonthears ]+', '\\1 ', 'g') END as showage", "from " + str(tbl) + " as a", "where a.id in %s;"]) qry_parm = tuple(map(int, instances)) c.execute(qry, (qry_parm, )) outx = c.fetchall() outd = dict([x for x in outx]) return outd
def view_attributes(cls): return super(Product, cls).view_attributes() + [ ('//page[@id="customers"]', 'states', { 'invisible': Not(Bool(Eval('displayed_on_eshop'))) }) ]
class Forecast(Workflow, ModelSQL, ModelView): "Stock Forecast" __name__ = "stock.forecast" _rec_name = 'warehouse' warehouse = fields.Many2One('stock.location', 'Location', required=True, domain=[('type', '=', 'warehouse')], states={ 'readonly': Or(Not(Equal(Eval('state'), 'draft')), Bool(Eval('lines', [0]))), }, depends=['state']) destination = fields.Many2One('stock.location', 'Destination', required=True, domain=[('type', 'in', ['customer', 'production'])], states=STATES, depends=DEPENDS) from_date = fields.Date('From Date', required=True, states=STATES, depends=DEPENDS) to_date = fields.Date('To Date', required=True, states=STATES, depends=DEPENDS) lines = fields.One2Many('stock.forecast.line', 'forecast', 'Lines', states=STATES, depends=DEPENDS) company = fields.Many2One('company.company', 'Company', required=True, states={ 'readonly': Or(Not(Equal(Eval('state'), 'draft')), Bool(Eval('lines', [0]))), }, depends=['state']) state = fields.Selection([ ('draft', 'Draft'), ('done', 'Done'), ('cancel', 'Cancel'), ], 'State', readonly=True, select=True) active = fields.Function(fields.Boolean('Active'), 'get_active', searcher='search_active') @classmethod def __setup__(cls): super(Forecast, cls).__setup__() t = cls.__table__() cls._sql_constraints += [ ('check_from_to_date', Check(t, t.to_date >= t.from_date), '"To Date" must be greater than "From Date"'), ] cls._error_messages.update({ 'date_overlap': ('Forecast "%(first)s" overlaps with dates ' 'of forecast "%(second)s" in the same location.'), 'delete_cancel': ('Forecast "%s" must be cancelled before ' 'deletion.'), }) cls._order.insert(0, ('from_date', 'DESC')) cls._order.insert(1, ('warehouse', 'ASC')) cls._transitions |= set(( ('draft', 'done'), ('draft', 'cancel'), ('done', 'draft'), ('cancel', 'draft'), )) cls._buttons.update({ 'cancel': { 'invisible': Eval('state') != 'draft', }, 'draft': { 'invisible': Eval('state') == 'draft', }, 'confirm': { 'invisible': Eval('state') != 'draft', }, 'complete': { 'readonly': Eval('state') != 'draft', }, }) @classmethod def __register__(cls, module_name): Location = Pool().get('stock.location') TableHandler = backend.get('TableHandler') cursor = Transaction().cursor sql_table = cls.__table__() table = TableHandler(cursor, cls, module_name) migrate_warehouse = (not table.column_exist('warehouse') and table.column_exist('location')) super(Forecast, cls).__register__(module_name) # Add index on create_date table = TableHandler(cursor, cls, module_name) table.index_action('create_date', action='add') if migrate_warehouse: location2warehouse = {} def find_warehouse(location): if location.type == 'warehouse': return location.id elif location.parent: return find_warehouse(location.parent) cursor.execute(*sql_table.select(sql_table.id, sql_table.location)) for forecast_id, location_id in cursor.fetchall(): warehouse_id = location_id # default fallback if location_id in location2warehouse: warehouse_id = location2warehouse[location_id] else: location = Location(location_id) warehouse_id = find_warehouse(location) or location_id location2warehouse[location_id] = warehouse_id cursor.execute( *sql_table.update(columns=[sql_table.warehouse], values=[warehouse_id], where=sql_table.id == forecast_id)) table.not_null_action('warehouse', action=cls.warehouse.required and 'add' or 'remove') table.drop_column('location', True) # Migration from 2.0 delete stock moves forecasts = cls.search([]) cls.delete_moves(forecasts) @staticmethod def default_state(): return 'draft' @classmethod def default_destination(cls): Location = Pool().get('stock.location') locations = Location.search(cls.destination.domain) if len(locations) == 1: return locations[0].id @staticmethod def default_company(): return Transaction().context.get('company') def get_active(self, name): pool = Pool() Date = pool.get('ir.date') return self.to_date >= Date.today() @classmethod def search_active(cls, name, clause): pool = Pool() Date = pool.get('ir.date') today = Date.today() operators = { '=': '>=', '!=': '<', } reverse = { '=': '!=', '!=': '=', } if clause[1] in operators: if clause[2]: return [('to_date', operators[clause[1]], today)] else: return [('to_date', operators[reverse[clause[1]]], today)] else: return [] @classmethod def validate(cls, forecasts): super(Forecast, cls).validate(forecasts) for forecast in forecasts: forecast.check_date_overlap() def check_date_overlap(self): cursor = Transaction().cursor if self.state != 'done': return forcast = self.__table__() cursor.execute( *forcast.select(forcast.id, where=(((forcast.from_date <= self.from_date) & (forcast.to_date >= self.from_date)) | ((forcast.from_date <= self.to_date) & (forcast.to_date >= self.to_date)) | ((forcast.from_date >= self.from_date) & (forcast.to_date <= self.to_date))) & (forcast.warehouse == self.warehouse.id) & (forcast.destination == self.destination.id) & (forcast.company == self.company.id) & (forcast.id != self.id))) forecast_id = cursor.fetchone() if forecast_id: second = self.__class__(forecast_id[0]) self.raise_user_error('date_overlap', { 'first': self.rec_name, 'second': second.rec_name, }) @classmethod def delete(self, forecasts): # Cancel before delete self.cancel(forecasts) for forecast in forecasts: if forecast.state != 'cancel': self.raise_user_error('delete_cancel', forecast.rec_name) super(Forecast, self).delete(forecasts) @classmethod @ModelView.button @Workflow.transition('draft') def draft(cls, forecasts): pass @classmethod @ModelView.button @Workflow.transition('done') def confirm(cls, forecasts): pass @classmethod @ModelView.button @Workflow.transition('cancel') def cancel(cls, forecasts): pass @classmethod @ModelView.button_action('stock_forecast.wizard_forecast_complete') def complete(cls, forecasts): pass @staticmethod def create_moves(forecasts): 'Create stock moves for the forecast ids' for forecast in forecasts: if forecast.state == 'done': for line in forecast.lines: line.create_moves() @staticmethod def delete_moves(forecasts): 'Delete stock moves for the forecast ids' Line = Pool().get('stock.forecast.line') Line.delete_moves([l for f in forecasts for l in f.lines]) @classmethod def copy(cls, forecasts, default=None): Line = Pool().get('stock.forecast.line') if default is None: default = {} default = default.copy() default['lines'] = None new_forecasts = [] for forecast in forecasts: new_forecast, = super(Forecast, cls).copy([forecast], default=default) Line.copy([x for x in forecast.lines], default={ 'forecast': new_forecast.id, }) new_forecasts.append(new_forecast) return new_forecasts
class SaleOpportunityHistory(ModelSQL, ModelView): 'Sale Opportunity History' __name__ = 'sale.opportunity.history' date = fields.DateTime('Change Date') opportunity = fields.Many2One('sale.opportunity', 'Sale Opportunity') user = fields.Many2One('res.user', 'User') party = fields.Many2One('party.party', 'Party', datetime_field='date') address = fields.Many2One('party.address', 'Address', datetime_field='date') company = fields.Many2One('company.company', 'Company', datetime_field='date') employee = fields.Many2One('company.employee', 'Employee', datetime_field='date') start_date = fields.Date('Start Date') end_date = fields.Date('End Date', states={ 'invisible': Not(In(Eval('state'), ['converted', 'cancelled', 'lost'])), }, depends=['state']) description = fields.Char('Description') comment = fields.Text('Comment') lines = fields.Function(fields.One2Many('sale.opportunity.line', None, 'Lines', datetime_field='date'), 'get_lines') amount = fields.Numeric('Amount', digits=(16, Eval('currency_digits', 2)), depends=['currency_digits']) currency = fields.Function(fields.Many2One('currency.currency', 'Currency'), 'get_currency') currency_digits = fields.Function(fields.Integer('Currency Digits'), 'get_currency_digits') state = fields.Selection(STATES, 'State') probability = fields.Integer('Conversion Probability') lost_reason = fields.Text('Reason for loss', states={ 'invisible': Not(Equal(Eval('state'), 'lost')), }, depends=['state']) @classmethod def __setup__(cls): super(SaleOpportunityHistory, cls).__setup__() cls._order.insert(0, ('date', 'DESC')) def get_currency(self, name): return self.company.currency.id def get_currency_digits(self, name): return self.company.currency.digits @classmethod def table_query(cls): Opportunity = Pool().get('sale.opportunity') opportunity_history = Opportunity.__table_history__() columns = [ Min(Column(opportunity_history, '__id')).as_('id'), opportunity_history.id.as_('opportunity'), Min(Coalesce(opportunity_history.write_date, opportunity_history.create_date)).as_('date'), Coalesce(opportunity_history.write_uid, opportunity_history.create_uid).as_('user'), ] group_by = [ opportunity_history.id, Coalesce(opportunity_history.write_uid, opportunity_history.create_uid), ] for name, field in cls._fields.iteritems(): if name in ('id', 'opportunity', 'date', 'user'): continue if hasattr(field, 'set'): continue column = Column(opportunity_history, name) columns.append(column.as_(name)) group_by.append(column) return opportunity_history.select(*columns, group_by=group_by) def get_lines(self, name): Line = Pool().get('sale.opportunity.line') # We will always have only one id per call due to datetime_field lines = Line.search([ ('opportunity', '=', self.opportunity.id), ]) return [l.id for l in lines] @classmethod def read(cls, ids, fields_names=None): res = super(SaleOpportunityHistory, cls).read(ids, fields_names=fields_names) # Remove microsecond from timestamp for values in res: if 'date' in values: if isinstance(values['date'], basestring): values['date'] = datetime.datetime( *time.strptime(values['date'], '%Y-%m-%d %H:%M:%S.%f')[:6]) values['date'] = values['date'].replace(microsecond=0) return res
class Recibo(Workflow, ModelSQL, ModelView): "cooperative.partner.recibo" __name__ = "cooperative.partner.recibo" date = fields.Date('Fecha', states={'readonly': (Eval('state') != 'draft')}, required=True) amount = fields.Numeric('Monto', digits=(16, 2), states={'readonly': (Eval('state') != 'draft')}, required=True) partner = fields.Many2One('cooperative.partner', 'Socio', required=True, states={'readonly': (Eval('state') != 'draft')}) state = fields.Selection([ ('draft', 'Borrador'), ('confirmed', 'Confirmado'), ('paid', 'Pagado'), ('cancel', 'Cancelado'), ], 'State', readonly=True) number = fields.Char('Numero', size=None, readonly=True, select=True) description = fields.Char('Descripcion', size=None, states=_STATES, depends=_DEPENDS) ## Integrando con asientos party = fields.Function( fields.Many2One('party.party', 'Entidad', required=True, states=_STATES, depends=_DEPENDS, on_change_with=['partner']), 'on_change_with_party') #company = fields.Many2One('company.company', 'Company', required=True, # states=_STATES, select=True, domain=[ # ('id', If(Eval('context', {}).contains('company'), '=', '!='), # Eval('context', {}).get('company', -1)), # ], # depends=_DEPENDS) company = fields.Many2One('company.company', 'Coooperativa', required=True, states=_STATES, select=True, depends=_DEPENDS) accounting_date = fields.Date('Fecha de Contabilizacion', states=_STATES, depends=_DEPENDS) confirmed_move = fields.Many2One('account.move', 'Asiento de Confirmacion', readonly=True) paid_move = fields.Many2One('account.move', 'Asiento de Pago', readonly=True, states={ 'invisible': Eval('state').in_(['draft', 'confirmed']), }) journal = fields.Many2One('account.journal', 'Diario', states=_STATES, depends=_DEPENDS) currency = fields.Many2One('currency.currency', 'Moneda', required=True, states={ 'readonly': ((Eval('state') != 'draft') | (Eval('lines') & Eval('currency'))), }, depends=['state', 'lines']) periodo_liquidado = fields.Char('Periodo Liquidado', required=True) fecha_pago = fields.Date('Fecha de Pago', required=True) #Para concepto de Monotributo pago_monotributo = fields.Boolean('Pago de monotributo') valor_monotributo = fields.Numeric( 'Valor del monotributo', digits=(16, 2), states={'invisible': Not(Bool(Eval('pago_monotributo')))}) mes_monotributo = fields.Selection( [('', ''), ('Enero', 'Enero'), ('Febrero', 'Febrero'), ('Marzo', 'Marzo'), ('Abril', 'Abril'), ('Mayo', 'Mayo'), ('Junio', 'Junio'), ('Julio', 'Julio'), ('Agosto', 'Agosto'), ('Septiembre', 'Septiembre'), ('Octubre', 'Octubre'), ('Noviembre', 'Noviembre'), ('Diciembre', 'Diciembre')], 'Mes del Monotributo', states={'invisible': Not(Bool(Eval('pago_monotributo')))}, ) #Para pago de cuotas cobro_cuota = fields.Boolean('Cobro de cuota') valor_cuota = fields.Numeric( 'Valor de la cuota', digits=(16, 2), states={'invisible': Not(Bool(Eval('cobro_cuota')))}) mes_cuota = fields.Selection( [('', ''), ('Enero', 'Enero'), ('Febrero', 'Febrero'), ('Marzo', 'Marzo'), ('Abril', 'Abril'), ('Mayo', 'Mayo'), ('Junio', 'Junio'), ('Julio', 'Julio'), ('Agosto', 'Agosto'), ('Septiembre', 'Septiembre'), ('Octubre', 'Octubre'), ('Noviembre', 'Noviembre'), ('Diciembre', 'Diciembre')], 'Mes de la Cuota', states={'invisible': Not(Bool(Eval('cobro_cuota')))}, ) #Para otros conceptos (AUH, etc) pago_otros = fields.Boolean('Pago de adicional') concepto_otros = fields.Char( 'Nombre del concepto adicional', states={'invisible': Not(Bool(Eval('pago_otros')))}) valor_otros = fields.Numeric( 'Valor del concepto adicional', digits=(16, 2), states={'invisible': Not(Bool(Eval('pago_otros')))}) #Otros conceptos lineas_conceptos_recibo = fields.One2Many( 'cooperative.partner.recibo.lineaconceptorecibo', 'recibo', 'Conceptos a incluir en el recibo') total = fields.Function( fields.Numeric('Total', digits=(16, 2), on_change_with=[ 'amount', 'pago_monotributo', 'cobro_cuota', 'valor_cuota', 'valor_monotributo', 'total', 'lineas_conceptos_recibo' ]), 'on_change_with_total') total_en_letras = fields.Function(fields.Char('Total en letras'), 'get_sing_number') @classmethod def __setup__(cls): super(Recibo, cls).__setup__() cls._transitions |= set(( ('draft', 'confirmed'), ('draft', 'cancel'), ('confirmed', 'draft'), ('confirmed', 'paid'), ('confirmed', 'cancel'), ('cancel', 'draft'), )) cls._buttons.update({ 'cancel': { 'invisible': ~Eval('state').in_(['draft']), }, 'draft': { 'invisible': ~Eval('state').in_(['cancel']), }, 'paid': { 'invisible': ~Eval('state').in_(['confirmed']), }, 'confirmed': { 'invisible': ~Eval('state').in_(['draft']), }, }) @classmethod @ModelView.button @Workflow.transition('draft') def draft(cls, recibos): Move = Pool().get('account.move') moves = [] for recibo in recibos: if recibo.confirmed_move: moves.append(recibo.confirmed_move) if moves: with Transaction().set_user(0, set_context=True): Move.delete(moves) @classmethod @ModelView.button @Workflow.transition('confirmed') def confirmed(cls, recibos): Move = Pool().get('account.move') moves = [] for recibo in recibos: recibo.journal = Pool().get('account.journal').search([ ('code', '=', 'EXP') ])[0] recibo.save() recibo.set_number() moves.append(recibo.create_confirmed_move()) cls.write(recibos, { 'state': 'confirmed', }) Move.post(moves) @classmethod @ModelView.button @Workflow.transition('paid') def paid(cls, recibos): Move = Pool().get('account.move') moves = [] for recibo in recibos: moves.append(recibo.create_paid_move()) cls.write(recibos, { 'state': 'paid', }) Move.post(moves) @classmethod @ModelView.button @Workflow.transition('cancel') def cancel(cls, recibos): cls.write(recibos, { 'state': 'cancel', }) @staticmethod def default_state(): return 'draft' @staticmethod def default_description(): return 'Retornos a cuenta de excedentes' @staticmethod def default_date(): Date_ = Pool().get('ir.date') return Date_.today() @staticmethod def default_fecha_pago(): Date_ = Pool().get('ir.date') return Date_.today() @staticmethod def default_amount(): return Decimal(0) @staticmethod def default_valor_cuota(): return Decimal(0) @staticmethod def default_valor_monotributo(): return Decimal(0) @staticmethod def default_valor_otros(): return Decimal(0) @staticmethod def default_company(): return Transaction().context.get('company') @staticmethod def default_currency(): Company = Pool().get('company.company') if Transaction().context.get('company'): company = Company(Transaction().context['company']) return company.currency.id def on_change_with_party(self, name=None): if self.partner: return self.partner.party.id def on_change_with_total(self, name=None): if self.pago_monotributo: total = Decimal(self.amount) + Decimal(self.valor_monotributo) else: total = Decimal(self.amount) if self.cobro_cuota: total -= Decimal(self.valor_cuota) if self.lineas_conceptos_recibo: for linea in self.lineas_conceptos_recibo: if linea.valor: total += Decimal(linea.valor) #if self.pago_otros: # total += Decimal(self.valor_otros) return total def set_number(self): ''' Set number to the receipt ''' pool = Pool() FiscalYear = pool.get('account.fiscalyear') Date = pool.get('ir.date') Sequence = pool.get('ir.sequence') if self.number: return accounting_date = self.accounting_date or self.date fiscalyear_id = FiscalYear.find(self.company.id, date=accounting_date) fiscalyear = FiscalYear(fiscalyear_id) sequence = fiscalyear.get_sequence('receipt') #if not sequence: # self.raise_user_error('no_invoice_sequence', { # 'invoice': self.rec_name, # 'period': period.rec_name, # }) with Transaction().set_context(date=self.date or Date.today()): number = Sequence.get_id(sequence.id) vals = {'number': number} self.write([self], vals) def _get_move_line(self, date, amount, account_id): ''' Return move line ''' Currency = Pool().get('currency.currency') res = {} if self.currency.id != self.company.currency.id: with Transaction().set_context(date=self.date): res['amount_second_currency'] = Currency.compute( self.company.currency, amount, self.currency) res['amount_second_currency'] = abs(res['amount_second_currency']) res['second_currency'] = self.currency.id else: res['amount_second_currency'] = Decimal('0.0') res['second_currency'] = None if amount >= Decimal('0.0'): res['debit'] = Decimal('0.0') res['credit'] = amount else: res['debit'] = -amount res['credit'] = Decimal('0.0') res['account'] = account_id res['maturity_date'] = date res['description'] = self.description res['party'] = self.party.id return res def create_move(self, move_lines): pool = Pool() Move = pool.get('account.move') Period = pool.get('account.period') accounting_date = self.accounting_date or self.date period_id = Period.find(self.company.id, date=accounting_date) move, = Move.create([{ 'journal': self.journal.id, 'period': period_id, 'date': self.date, # 'origin': str(self), 'lines': [('create', move_lines)], }]) return move def create_confirmed_move(self): ''' Create account move for the receipt and return the created move ''' pool = Pool() Date = pool.get('ir.date') move_lines = [] val = self._get_move_line(Date.today(), self.amount, self.party.account_payable.id) move_lines.append(val) # issue #4461 # En vez de usar la cuenta "a cobrar" del party, deberia ser la # cuenta Retornos Asociados (5242) siempre fija, que esta seteada como # Expense (Gasto). account_receivable = self.party.account_receivable.search([ ('rec_name', 'like', '%5242%') ])[0] val = self._get_move_line(Date.today(), -self.amount, account_receivable.id) move_lines.append(val) move = self.create_move(move_lines) self.write([self], { 'confirmed_move': move.id, }) return move def create_paid_move(self): ''' Create account move for the receipt and return the created move ''' pool = Pool() Date = pool.get('ir.date') move_lines = [] val = self._get_move_line(Date.today(), self.amount, self.journal.credit_account.id) move_lines.append(val) val = self._get_move_line(Date.today(), -self.amount, self.party.account_payable.id) move_lines.append(val) move = self.create_move(move_lines) self.write([self], { 'paid_move': move.id, }) return move def get_sing_number(self, name=None): "Convert numbers in its equivalent string text representation in spanish" from singing_girl import Singer singer = Singer() return singer.sing(self.total)
def __setup__(cls): super(Template, cls).__setup__() cls.products.states['readonly'] = Not(Eval('variante', False))
class notacreditoStart(ModelView): 'notacredito Start' __name__ = 'sigcoop_wizard_ventas.notacredito.start' tipoemi = fields.Selection([ ('otro','Otro'), ('porid','Por numero de ID'), ('portarifa', 'Por Tarifa') ], 'Tipo de Emision', required=True) desdeid = fields.Integer('Desde ID', states={'required': Equal(Eval('tipoemi'),'porid')}) hastaid = fields.Integer('Hasta ID', states={'required': Equal(Eval('tipoemi'),'porid')}) servicio = fields.Many2One('product.category', 'Tipo de servicio', required=True, on_change=['servicio', 'mismocesp']) servicio_char = fields.Char('servicio_char') periodo = fields.Many2One('sigcoop_periodo.periodo', 'Periodo', states={'required': Equal(Eval('tipoemi'),'portarifa')}, domain=[ ('category', '=', Eval('servicio'))]) lista_precios = fields.Many2One('product.price_list', 'Tarifa', states={'required': Equal(Eval('tipoemi'),'portarifa')}, domain = [ ('servicio', '=', Eval('servicio')), ('tarifa_oculta', '=', False )]) consumo_cero = fields.Boolean('NC de Facturas con consumo cero', select=False, states={'readonly': Not(Equal(Eval('servicio_char'),'Energia') | Equal(Eval('servicio_char'),'Agua')) }) mismocesp = fields.Boolean('Usar CESP y Fecha de la factura', select=False, states={'readonly': Not(Equal(Eval('servicio_char'),'Energia') | Equal(Eval('servicio_char'),'Agua')) }) numerocesp = fields.Many2One('account.cesp', 'C.E.S.P.', states={'required': Equal(Eval('servicio_char'),'Energia') | Equal(Eval('servicio_char'),'Agua'), 'readonly': Or(Bool(Eval('mismocesp')), Not(Equal(Eval('servicio_char'),'Energia') | Equal(Eval('servicio_char'),'Agua'))), }) fecha_nc = fields.Date('Fecha de Nota de Credito', states={'required': Equal(Eval('servicio_char'),'Energia') | Equal(Eval('servicio_char'),'Agua'), 'readonly': Bool(Eval('mismocesp')), }) def on_change_servicio(self): serv='' ret={} if (self.servicio and self.servicio.name): serv=self.servicio.name if (self.servicio.name!='Energia') or (self.servicio.name!='Agua'): ret['mismocesp']=False ret['servicio_char']=serv return ret
def view_attributes(cls): return super().view_attributes() + [ ('//group[@id="tas"]', 'states', { 'invisible': Not(Bool(Equal(Eval('type'), 'tas'))), }), ]
class Invoice(metaclass=PoolMeta): __name__ = 'account.invoice' payment_type_kind = fields.Function(fields.Selection(KINDS, 'Kind of payment type', states={ 'invisible': True, }, ), 'on_change_with_payment_type_kind') payment_type = fields.Many2One('account.payment.type', 'Payment Type', domain=[ ('kind', 'in', ['both', Eval('payment_type_kind')]), ], states={ 'readonly': Not(Bool(Eval('state').in_(['draft', 'validated']))), }, depends=['payment_type_kind', 'state']) @classmethod def __setup__(cls): super().__setup__() cls.payment_direct_debit.states = { 'invisible': True, } @fields.depends('type', 'untaxed_amount', 'lines') def on_change_with_payment_type_kind(self, name=None): if self.untaxed_amount: if self.type == 'out': if self.untaxed_amount >= ZERO: return 'receivable' else: return 'payable' elif self.type == 'in': if self.untaxed_amount >= ZERO: return 'payable' else: return 'receivable' return 'receivable' if self.type == 'out' else 'payable' @fields.depends('party', 'company', 'type', 'untaxed_amount', 'lines') def on_change_with_payment_type(self, name=None): if (hasattr(self, 'payment_type') and self.payment_type and self.payment_type.kind == 'both'): return self.payment_type.id kind = self.on_change_with_payment_type_kind() if (hasattr(self, 'payment_type') and self.payment_type and self.payment_type.kind == kind): return self.payment_type.id if not self.untaxed_amount: return (self.payment_type.id if (hasattr(self, 'payment_type') and self.payment_type) else None) for party in [ self.party, self.company.party if self.company else None]: if not party: continue if self.type == 'out': if kind == 'receivable': name = 'customer_payment_type' else: name = 'supplier_payment_type' elif self.type == 'in': if kind == 'payable': name = 'supplier_payment_type' else: name = 'customer_payment_type' payment_type = getattr(party, name) if payment_type: return payment_type.id return None def _get_move_line(self, date, amount): line = super(Invoice, self)._get_move_line(date, amount) if self.payment_type: line.payment_type = self.payment_type return line
class Forecast(Workflow, ModelSQL, ModelView): "Stock Forecast" __name__ = "stock.forecast" warehouse = fields.Many2One( 'stock.location', 'Location', required=True, domain=[('type', '=', 'warehouse')], states={ 'readonly': Or(Not(Equal(Eval('state'), 'draft')), Bool(Eval('lines', [0]))), }, depends=['state']) destination = fields.Many2One( 'stock.location', 'Destination', required=True, domain=[('type', 'in', ['customer', 'production'])], states=STATES, depends=DEPENDS) from_date = fields.Date('From Date', required=True, states=STATES, depends=DEPENDS) to_date = fields.Date('To Date', required=True, states=STATES, depends=DEPENDS) lines = fields.One2Many( 'stock.forecast.line', 'forecast', 'Lines', states=STATES, depends=DEPENDS) company = fields.Many2One( 'company.company', 'Company', required=True, states={ 'readonly': Or(Not(Equal(Eval('state'), 'draft')), Bool(Eval('lines', [0]))), }, depends=['state']) state = fields.Selection( FORECAST_STATES, 'State', readonly=True, select=True) active = fields.Function(fields.Boolean('Active'), 'get_active', searcher='search_active') @classmethod def __setup__(cls): super(Forecast, cls).__setup__() t = cls.__table__() cls._sql_constraints += [ ('check_from_to_date', Check(t, t.to_date >= t.from_date), '"To Date" must be greater than "From Date"'), ] cls._error_messages.update({ 'date_overlap': ('Forecast "%(first)s" overlaps with dates ' 'of forecast "%(second)s" in the same location.'), 'delete_cancel': ('Forecast "%s" must be cancelled before ' 'deletion.'), }) cls._order.insert(0, ('from_date', 'DESC')) cls._order.insert(1, ('warehouse', 'ASC')) cls._transitions |= set(( ('draft', 'done'), ('draft', 'cancel'), ('done', 'draft'), ('cancel', 'draft'), )) cls._buttons.update({ 'cancel': { 'invisible': Eval('state') != 'draft', 'depends': ['state'], }, 'draft': { 'invisible': Eval('state') == 'draft', 'depends': ['state'], }, 'confirm': { 'invisible': Eval('state') != 'draft', 'depends': ['state'], }, 'complete': { 'readonly': Eval('state') != 'draft', 'depends': ['state'], }, }) cls._active_field = 'active' @classmethod def __register__(cls, module_name): super(Forecast, cls).__register__(module_name) # Add index on create_date table = cls.__table_handler__(module_name) table.index_action('create_date', action='add') @staticmethod def default_state(): return 'draft' @classmethod def default_destination(cls): Location = Pool().get('stock.location') locations = Location.search(cls.destination.domain) if len(locations) == 1: return locations[0].id @staticmethod def default_company(): return Transaction().context.get('company') def get_active(self, name): pool = Pool() Date = pool.get('ir.date') return self.to_date >= Date.today() @classmethod def search_active(cls, name, clause): pool = Pool() Date = pool.get('ir.date') today = Date.today() operators = { '=': '>=', '!=': '<', } reverse = { '=': '!=', '!=': '=', } if clause[1] in operators: if clause[2]: return [('to_date', operators[clause[1]], today)] else: return [('to_date', operators[reverse[clause[1]]], today)] else: return [] def get_rec_name(self, name): return self.warehouse.rec_name @classmethod def search_rec_name(cls, name, clause): return [('warehouse.rec_name',) + tuple(clause[1:])] @classmethod def validate(cls, forecasts): super(Forecast, cls).validate(forecasts) for forecast in forecasts: forecast.check_date_overlap() def check_date_overlap(self): if self.state != 'done': return transaction = Transaction() connection = transaction.connection transaction.database.lock(connection, self._table) forcast = self.__table__() cursor = connection.cursor() cursor.execute(*forcast.select(forcast.id, where=(((forcast.from_date <= self.from_date) & (forcast.to_date >= self.from_date)) | ((forcast.from_date <= self.to_date) & (forcast.to_date >= self.to_date)) | ((forcast.from_date >= self.from_date) & (forcast.to_date <= self.to_date))) & (forcast.warehouse == self.warehouse.id) & (forcast.destination == self.destination.id) & (forcast.company == self.company.id) & (forcast.id != self.id))) forecast_id = cursor.fetchone() if forecast_id: second = self.__class__(forecast_id[0]) self.raise_user_error('date_overlap', { 'first': self.rec_name, 'second': second.rec_name, }) @classmethod def delete(cls, forecasts): # Cancel before delete cls.cancel(forecasts) for forecast in forecasts: if forecast.state != 'cancel': cls.raise_user_error('delete_cancel', forecast.rec_name) super(Forecast, cls).delete(forecasts) @classmethod @ModelView.button @Workflow.transition('draft') def draft(cls, forecasts): pass @classmethod @ModelView.button @Workflow.transition('done') def confirm(cls, forecasts): pass @classmethod @ModelView.button @Workflow.transition('cancel') def cancel(cls, forecasts): pass @classmethod @ModelView.button_action('stock_forecast.wizard_forecast_complete') def complete(cls, forecasts): pass @staticmethod def create_moves(forecasts): 'Create stock moves for the forecast ids' pool = Pool() Line = pool.get('stock.forecast.line') to_save = [] for forecast in forecasts: if forecast.state == 'done': for line in forecast.lines: line.moves += tuple(line.get_moves()) to_save.append(line) Line.save(to_save) @staticmethod def delete_moves(forecasts): 'Delete stock moves for the forecast ids' Line = Pool().get('stock.forecast.line') Line.delete_moves([l for f in forecasts for l in f.lines])
class Sale: "Sale" __name__ = 'sale.sale' is_international_shipping = fields.Function( fields.Boolean("Is International Shipping"), 'on_change_with_is_international_shipping') weight = fields.Function( fields.Float( "Weight", digits=(16, Eval('weight_digits', 2)), depends=['weight_digits'], ), 'get_weight') weight_uom = fields.Function(fields.Many2One('product.uom', 'Weight UOM'), 'get_weight_uom') weight_digits = fields.Function(fields.Integer('Weight Digits'), 'on_change_with_weight_digits') available_carrier_services = fields.Function( fields.One2Many("carrier.service", None, 'Available Carrier Services'), getter="on_change_with_available_carrier_services") carrier_service = fields.Many2One( "carrier.service", "Carrier Service", domain=[('id', 'in', Eval('available_carrier_services'))], states={ "invisible": Not(Bool(Eval('carrier'))), "readonly": Eval('state') != 'draft', }, depends=['carrier', 'available_carrier_services', 'state']) carrier_cost_method = fields.Function( fields.Char('Carrier Cost Method'), "on_change_with_carrier_cost_method") @classmethod @ModelView.button_action('shipping.wizard_sale_apply_shipping') def apply_shipping(cls, sales): pass @fields.depends("carrier") def on_change_with_carrier_cost_method(self, name=None): if self.carrier: return self.carrier.carrier_cost_method def on_change_lines(self): """Pass a flag in context which indicates the get_sale_price method of carrier not to calculate cost on each line change """ with Transaction().set_context({'ignore_carrier_computation': True}): super(Sale, self).on_change_lines() @fields.depends("carrier") def on_change_with_available_carrier_services(self, name=None): if self.carrier: return map(int, self.carrier.services) return [] @classmethod def __setup__(cls): super(Sale, cls).__setup__() cls._error_messages.update({ 'warehouse_address_missing': 'Warehouse address is missing', }) cls._buttons.update({ 'apply_shipping': { "invisible": ~Eval('state').in_(['draft', 'quotation', 'confirmed']) } }) cls.__rpc__.update({'apply_shipping_rate': RPC(instantiate=0)}) @fields.depends('weight_uom') def on_change_with_weight_digits(self, name=None): if self.weight_uom: return self.weight_uom.digits return 2 def get_weight_uom(self, name): """ Returns weight uom for the sale """ ModelData = Pool().get('ir.model.data') return ModelData.get_id('product', 'uom_pound') def get_weight(self, name): """ Returns sum of weight associated with each line """ return sum( map(lambda line: line.get_weight(self.weight_uom, silent=True), self.lines)) @fields.depends('party', 'shipment_address', 'warehouse') def on_change_with_is_international_shipping(self, name=None): """ Return True if international shipping """ from_address = self._get_ship_from_address(silent=True) if self.shipment_address and from_address and \ from_address.country and self.shipment_address.country and \ from_address.country != self.shipment_address.country: return True return False def _get_ship_from_address(self, silent=False): """ Usually the warehouse from which you ship """ if not self.warehouse.address and not silent: return self.raise_user_error('warehouse_address_missing') return self.warehouse and self.warehouse.address def add_shipping_line(self, shipment_cost, description, carrier=None, carrier_service=None): """ This method takes shipping_cost and description as arguments and writes a shipping line. It deletes any previous shipping lines which have a shipment_cost. :param shipment_cost: The shipment cost calculated according to carrier :param description: Shipping line description """ Sale = Pool().get('sale.sale') carrier = carrier or self.carrier carrier_service = carrier_service and self.carrier_service Sale.write( [self], { 'lines': [ ( 'create', [{ 'type': 'line', 'product': carrier.carrier_product.id, 'description': description, 'quantity': 1, # XXX 'unit': carrier.carrier_product.sale_uom.id, 'unit_price': shipment_cost, 'shipment_cost': shipment_cost, 'amount': shipment_cost, 'taxes': [], 'sequence': 9999, # XXX }]), ('delete', [ line for line in self.lines if line.shipment_cost is not None ]), ], # reset the amount caches or function # fields will continue to return cached values 'untaxed_amount_cache': None, 'tax_amount_cache': None, 'total_amount_cache': None, }) # reset the order total cache if self.state not in ('draft', 'quote'): Sale.store_cache([self]) def _get_carrier_context(self): "Pass sale in the context" context = super(Sale, self)._get_carrier_context() context = context.copy() context['sale'] = self.id return context def apply_shipping_rate(self, rate): """ This method applies shipping rate. Rate is a dictionary with following minimum keys: { 'display_name': Name to display, 'carrier_service': carrier.service active record, 'cost': cost, 'cost_currency': currency.currency active record, 'carrier': carrier active record, } It also creates a shipment line by deleting all existing ones. The rate could optionally have integer ids of service, carrier and currency. """ Currency = Pool().get('currency.currency') Carrier = Pool().get('carrier') CarrierService = Pool().get('carrier.service') self.carrier = Carrier(int(rate['carrier'])) self.carrier_service = CarrierService(int(rate['carrier_service'])) \ if rate['carrier_service'] else None self.save() cost_currency = Currency(int(rate['cost_currency'])) shipment_cost = cost_currency.round(rate['cost']) if self.currency != cost_currency: shipment_cost = Currency.compute(cost_currency, shipment_cost, self.currency) self.add_shipping_line( shipment_cost, rate['display_name'], self.carrier, self.carrier_service, ) def get_shipping_rates(self, carriers=None, silent=False): """ Gives a list of rates from carriers provided. If no carriers provided, return rates from all the carriers. List contains dictionary with following minimum keys: [ { 'display_name': Name to display, 'carrier_service': carrier.service active record, 'cost': cost, 'cost_currency': currency.currency active repord, 'carrier': carrier active record, }.. ] """ Carrier = Pool().get('carrier') if carriers is None: carriers = Carrier.search([]) rates = [] for carrier in carriers: rates.extend(self.get_shipping_rate(carrier, silent=silent)) return rates def get_shipping_rate(self, carrier, carrier_service=None, silent=False): """ Gives a list of rates from provided carrier and carrier service. List contains dictionary with following minimum keys: [ { 'display_name': Name to display, 'carrier_service': carrier.service active record, 'cost': cost, 'cost_currency': currency.currency active repord, 'carrier': carrier active record, }.. ] """ Company = Pool().get('company.company') if carrier.carrier_cost_method == 'product': currency = Company(Transaction().context['company']).currency rate_dict = { 'carrier_service': carrier_service, 'cost': carrier.carrier_product.list_price, 'cost_currency': currency, 'carrier': carrier, } display_name = carrier.rec_name rate_dict['display_name'] = display_name return [rate_dict] return [] @classmethod def get_allowed_carriers_domain(cls): """This method returns domain to seach allowed carriers Downstream modules can inherit and update customize this domain. """ return [] def create_shipment(self, shipment_type): with Transaction().set_context(ignore_carrier_computation=True): shipments = super(Sale, self).create_shipment(shipment_type) if shipment_type == 'out' and shipments: for shipment in shipments: if shipment.carrier: continue shipment.carrier = self.carrier shipment.carrier_service = self.carrier_service shipment.save() return shipments
def view_attributes(cls): return super(Template, cls).view_attributes() + [ ('//page[@id="counting"]', 'states', { 'invisible': Not(Equal(Eval('type'), 'goods')), }) ]
class Iss(ModelSQL, ModelView): 'Injury Surveillance System Registration' __name__ = 'gnuhealth.iss' name = fields.Many2One('gnuhealth.patient.evaluation', 'Evaluation', required=True, help='Related Patient Evaluation') injury_date = fields.Date('Injury Date', help="Usually the same as the Evaluation") registration_date = fields.Date('Registration Date') code = fields.Char('Code', help='Injury Code', required=True) operational_sector = fields.Many2One( 'gnuhealth.operational_sector', 'O. Sector', help="Operational Sector in which happened the injury") latitude = fields.Numeric('Latidude', digits=(3, 14)) longitude = fields.Numeric('Longitude', digits=(4, 14)) urladdr = fields.Char( 'OSM Map', help="Maps the Accident / Injury location on Open Street Map") healthcenter = fields.Many2One('gnuhealth.institution', 'Institution') patient = fields.Function(fields.Char('Patient'), 'get_patient', searcher='search_patient') patient_sex = fields.Function(fields.Char('Gender'), 'get_patient_sex') patient_age = fields.Function(fields.Char('Age'), 'get_patient_age') complaint = fields.Function(fields.Char('Chief Complaint'), 'get_patient_complaint') injury_type = fields.Selection([ (None, ''), ('accidental', 'Accidental / Unintentional'), ('violence', 'Violence'), ('attempt_suicide', 'Suicide Attempt'), ('motor_vehicle', 'Motor Vehicle'), ], 'Injury Type', required=True, sort=False) mva_mode = fields.Selection( [ (None, ''), ('pedestrian', 'Pedestrian'), ('bicycle', 'Bicycle'), ('motorbike', 'Motorbike'), ('car', 'Car'), ('van', 'Van / Pickup / Jeep'), ('truck', 'Truck / Heavy vehicle'), ('bus', 'Bus'), ('train', 'Train'), ('taxi', 'Taxi'), ('boat', 'Boat / Ship'), ('aircraft', 'Aircraft'), ('other', 'Other'), ('unknown', 'Unknown'), ], 'Mode', help="Motor Vehicle Accident Mode", sort=False, states={'required': Equal(Eval('injury_type'), 'motor_vehicle')}) mva_position = fields.Selection( [ (None, ''), ('driver', 'Driver'), ('passenger', 'Passenger'), ('outside', 'Outside / on the back'), ('bystander', 'Bystander'), ('unspecified_vehicle', 'Unspecified vehicle'), ('unknown', 'Unknown'), ], 'User Position', help="Motor Vehicle Accident user position", sort=False, states={'required': Equal(Eval('injury_type'), 'motor_vehicle')}) mva_counterpart = fields.Selection( [ (None, ''), ('pedestrian', 'Pedestrian'), ('bicycle', 'Bicycle'), ('motorbike', 'Motorbike'), ('car', 'Car'), ('van', 'Van / Pickup / Jeep'), ('truck', 'Truck / Heavy vehicle'), ('bus', 'Bus'), ('train', 'Train'), ('taxi', 'Taxi'), ('boat', 'Boat / Ship'), ('aircraft', 'Aircraft'), ('other', 'Other'), ('unknown', 'Unknown'), ], 'Counterpart', help="Motor Vehicle Accident Counterpart", sort=False, states={'required': Equal(Eval('injury_type'), 'motor_vehicle')}) safety_gear = fields.Selection( [ (None, ''), ('yes', 'Yes'), ('no', 'No'), ('unknown', 'Unknown'), ], 'Safety Gear', help="Use of Safety Gear - Helmet, safety belt...", sort=False, states={'required': Equal(Eval('injury_type'), 'motor_vehicle')}) alcohol = fields.Selection( [ (None, ''), ('yes', 'Yes'), ('no', 'No'), ('suspected', 'Suspected'), ('unknown', 'Unknown'), ], 'Alcohol', required=True, help="Is there evidence of alcohol use by the injured person" " in the 6 hours before the accident ?", sort=False) drugs = fields.Selection( [ (None, ''), ('yes', 'Yes'), ('no', 'No'), ('suspected', 'Suspected'), ('unknown', 'Unknown'), ], 'Other Drugs', required=True, help="Is there evidence of drug use by the injured person" " in the 6 hours before the accident ?", sort=False) injury_details = fields.Text('Details') # Add victim-perpretator relationship for violence-related injuries victim_perpetrator = fields.Selection( [ (None, ''), ('parent', 'Parent'), ('spouse', 'Wife / Husband'), ('girlboyfriend', 'Girl / Boyfriend'), ('relative', 'Other relative'), ('acquaintance', 'Acquaintance / Friend'), ('official', 'Official / Legal'), ('stranger', 'Stranger'), ('other', 'other'), ], 'Relationship', help="Victim - Perpetrator relationship", sort=False, states={'required': Equal(Eval('injury_type'), 'violence')}) violence_circumstances = fields.Selection( [ (None, ''), ('fight', 'Fight'), ('robbery', 'Robbery'), ('drug', 'Drug Related'), ('sexual', 'Sexual Assault'), ('gang', 'Gang Activity'), ('other_crime', 'Committing a crime (other)'), ('other', 'Other'), ('unknown', 'Unknown'), ], 'Context', help="Precipitating Factor", sort=False, states={'required': Equal(Eval('injury_type'), 'violence')}) injury_method = fields.Selection( [ (None, ''), ('blunt', 'Blunt object'), ('push', 'Push/bodily force'), ('sharp', 'Sharp objects'), ('gun', 'Gun shot'), ('sexual', 'Sexual Assault'), ('choking', 'Choking/strangulation'), ('other', 'Other'), ('unknown', 'Unknown'), ], 'Method', help="Method of Injury", sort=False, states={'required': Equal(Eval('injury_type'), 'violence')}) # Place of occurrance . Not used in motor vehicle accidents place_occurrance = fields.Selection( [ (None, ''), ('home', 'Home'), ('street', 'Street'), ('institution', 'Institution'), ('school', 'School'), ('commerce', 'Commercial Area'), ('publicbuilding', 'Public Building'), ('recreational', 'Recreational Area'), ('transportation', 'Public transportation'), ('sports', 'Sports event'), ('unknown', 'Unknown'), ], 'Place', help="Place of occurrance", sort=False, states={'required': Not(Equal(Eval('injury_type'), 'motor_vehicle'))}) disposition = fields.Selection([ (None, ''), ('treated_sent', 'Treated and Sent Home'), ('admitted', 'Admitted to Ward'), ('observation', 'Admitted to Observation'), ('died', 'Died'), ('daa', 'Discharge Against Advise'), ('transferred', 'Transferred'), ('doa', 'Dead on Arrival'), ], 'Disposition', help="Place of occurrance", sort=False, required=True) def get_patient(self, name): return self.name.patient.rec_name def get_patient_sex(self, name): return self.name.patient.name.gender def get_patient_age(self, name): return self.name.patient.name.age def get_patient_complaint(self, name): return self.name.chief_complaint @fields.depends('latitude', 'longitude') def on_change_with_urladdr(self): # Generates the URL to be used in OpenStreetMap # The address will be mapped to the URL in the following way # If the latitud and longitude of the Accident / Injury # are given, then those parameters will be used. ret_url = '' if (self.latitude and self.longitude): ret_url = 'http://openstreetmap.org/?mlat=' + \ str(self.latitude) + '&mlon=' + str(self.longitude) return ret_url @classmethod def search_patient(cls, name, clause): res = [] value = clause[2] res.append(('name.patient', clause[1], value)) return res @classmethod def __setup__(cls): super(Iss, cls).__setup__() t = cls.__table__() cls._sql_constraints = [ ('code_uniq', Unique(t, t.code), 'This ISS registration Code already exists'), ] @classmethod def view_attributes(cls): return [ ('//group[@id="motor_vehicle_accident"]', 'states', { 'invisible': Not(Equal(Eval('injury_type'), 'motor_vehicle')), }), ('//group[@id="violent_injury"]', 'states', { 'invisible': Not(Equal(Eval('injury_type'), 'violence')), }), ('//group[@id="iss_place"]', 'states', { 'invisible': Equal(Eval('injury_type'), 'motor_vehicle'), }), ]
from werkzeug.exceptions import NotFound from flask.ext.babel import format_currency from trytond.model import ModelView, ModelSQL, fields from trytond.pyson import Eval, Not, Bool from trytond.transaction import Transaction from trytond.pool import Pool, PoolMeta __all__ = [ 'Product', 'ProductsImageSet', 'ProductsRelated', 'ProductCategory', 'WebSite', 'WebsiteCategory', 'ProductTemplate', ] __metaclass__ = PoolMeta DEFAULT_STATE = {'invisible': Not(Bool(Eval('displayed_on_eshop')))} DEFAULT_STATE2 = { 'invisible': Not(Bool(Eval('displayed_on_eshop'))), 'required': Bool(Eval('displayed_on_eshop')), } class ProductTemplate: __name__ = "product.template" products_displayed_on_eshop = fields.Function( fields.One2Many('product.product', None, 'Products (Disp. on eShop)'), 'get_products_displayed_on_eshop' ) def get_products_displayed_on_eshop(self, name=None):
class QueueEntry(ModelSQL, ModelView): 'Queue Entry' __name__ = 'gnuhealth.patient.queue_entry' active = fields.Boolean('Active') triage_entry = fields.Many2One('gnuhealth.triage.entry', 'Triage Entry', states={'readonly': Eval('id', 0) > 0, 'required': ~Eval('appointment')}, select=True) appointment = fields.Many2One( 'gnuhealth.appointment', 'Appointment', select=True, states={'readonly': Eval('id', 0) > 0, 'required': ~Eval('triage_entry')}) encounter = fields.Many2One('gnuhealth.encounter', 'Encounter', states={'invisible': True}) busy = fields.Boolean('Busy', states={'readonly': True}, select=True) called_by_me = fields.Function(fields.Boolean('Last Called By Me', states={'readonly': True, 'invisible': Not(Eval('called_by_me', False)) }, select=True) , 'get_called_by_me') called_by = fields.Function(fields.Char('Last Called By', states={'readonly': True}, select=True) , 'get_called_by') line_notes = fields.Text('Line notes', help="Quick note about this line/patient") encounter_components = fields.Function( fields.Char('Encounter Components'), 'get_encounter_component_set') encounter_component_count = fields.Function( fields.Integer('Component Count'), 'get_encounter_component_set') entry_state = fields.Function(fields.Selection(QUEUE_ENTRY_STATES, 'State'), 'get_qentry_state', searcher='search_qentry_state') triage_status = fields.Function(fields.Char('triage status'), 'get_triage_status', searcher='search_triage_status') name = fields.Function(fields.Char('Name'), 'get_patient_name', searcher='search_patient_name') upi_mrn_id = fields.Function(fields.Char('UPI/MRN/ID#'), 'get_upi_mrn_id', searcher='search_upi_mrn_id') sex = fields.Function(fields.Selection(SEX_OPTIONS, 'Sex'), 'get_sex', searcher='search_sex') age = fields.Function(fields.Char('Age'), 'get_age') primary_complaint = fields.Function(fields.Char('Primary Complaint'), 'get_primary_complaint', searcher='search_primary_complaint') notes = fields.Function(fields.Text('Notes/Info'), 'get_notes_info') queue_notes = fields.One2Many('gnuhealth.patient.queue_entry_note', 'queue_entry', 'Queue Notes', states={'invisible': True}) last_call = fields.DateTime('Last Called', select=True) priority = fields.Integer('Priority', states={'readonly': True}) last_touch = fields.Function(fields.DateTime('Last Seen', format='%H:%M'), 'get_last_touch') last_toucher = fields.Function(fields.Char('Modification User'), 'get_last_touch') specialty = fields.Function(fields.Many2One('gnuhealth.specialty', 'Specialty'), 'get_specialty', searcher='search_specialty') timehere = fields.Function(fields.Char('Time Here'), 'get_time_here') visit_reason = fields.Function(fields.Many2One('gnuhealth.pathology', 'Reason for Visit'), getter='get_visit_reason') @staticmethod def default_busy(): return False @staticmethod def default_active(): return True @staticmethod def default_priority(): return TRIAGE_MAX_PRIO @classmethod def __setup__(cls): super(QueueEntry, cls).__setup__() cls.write_date.string = 'Last Modified' cls._order = [('priority', 'ASC'), ('last_call', 'ASC'), ('create_date', 'ASC')] cls._buttons.update( btn_inspect={}, btn_call={'readonly': Or(Eval('busy', False), Equal('99', Eval('entry_state', '0')))}, btn_dismiss={'readonly': Not(Eval('busy', False)), 'invisible': Not(Eval('called_by_me', False))}, btn_setup_appointment={ 'invisible': Or(Bool(Eval('appointment')), ~Equal('20', Eval('entry_state', '0'))) }) cls._sql_constraints += [ ('triage_uniq', 'UNIQUE(triage_entry)', 'Triage entry already in the queue'), ('appointment_uniq', 'UNIQUE(appointment)', 'Appointment already in the queue')] @classmethod def _swapout(cls, vdict, is_write=True): if vdict.get('line_notes', False): note = ('create', [{'note': vdict.pop('line_notes')}]) # if is_write: # note = ('create', [note]) vdict.setdefault('queue_notes', []).append(note) if vdict.get('busy', False): vdict['last_call'] = datetime.now() return vdict @classmethod def write(cls, instances, values, *args): # overload to handle the following situation: # if something is written in line-notes, create a QueueEntryNote # object with that as the note. To do that we will arglist = iter((instances, values) + args) log_entries = [] for recs, vals in zip(arglist, arglist): vals = cls._swapout(vals) if 'busy' in vals: # call or dismiss new_busy = vals['busy'] for rec in recs: log_entries.append( {'queue_entry': rec.id, 'entry_state': rec.entry_state, 'action': 'call' if new_busy else 'dismiss'}) retval = super(QueueEntry, cls).write(instances, values, *args) QueueCallLog.create(log_entries) return retval @classmethod def create(cls, vlist): # overload to create a QueueEntryNote if a line_note is included newvlist = [cls._swapout(v, False) for v in vlist] return super(QueueEntry, cls).create(newvlist) def get_patient_name(self, name): if self.appointment: return self.appointment.patient.name.name elif self.triage_entry: return self.triage_entry.name else: return '[No Name]' def get_last_touch(self, name): if name == 'last_touch': return self.write_date and self.write_date or self.create_date elif name == 'last_toucher': return self.write_uid.name if self.write_uid else None return '' def get_triage_status(self, name): return self.triage_entry.status if self.triage_entry else '' @classmethod def search_triage_status(cls, name, clause): fld, operator, operand = clause return [('triage_entry', '!=', None) ('triage_entry.status', operator, operand)] @classmethod def get_time_here(cls, instances, name): def iget_start_end(i, now=None): triage = i.triage_entry appt = i.appointment # Work out start time if triage: start = i.triage_entry.create_date elif appt: state_changes = [x for x in appt.state_changes if x.target_state == 'arrived'] if state_changes: start = state_changes[0].create_date else: start = appt.create_date else: start = i.create_date # Work out End Time if appt: if appt.state in APPT_DONE_STATES: state_changes = [x for x in appt.state_changes if x.target_state in APPT_DONE_STATES] if state_changes: end = state_changes[-1].create_date else: end = appt.write_date else: end = now elif triage: if i.entry_state == '99': end = triage.end_time else: end = now elif i.entry_state == '99': end = i.write_date else: end = now return (start, end) Now = datetime.now() def dmapper(i): return (int(i), get_elapsed_time(*iget_start_end(i, Now))) return dict(map(dmapper, instances)) @classmethod def search_patient_name(cls, name, clause): fld, operator, operand = clause if name == 'name': dom = ['OR'] for fld in ('triage_entry.name', 'triage_entry.patient.name.name', 'appointment.patient.name.name'): dom.append((fld, operator, operand)) return dom def get_upi_mrn_id(self, name): if self.appointment: return '%s / %s' % (self.appointment.upi, self.appointment.medical_record_num) elif self.triage_entry: return self.triage_entry.id_display return '' @classmethod def search_upi_mrn_id(cls, name, clause): fld, operator, operand = clause out = ['OR'] + [(f, operator, operand) for f in ('triage_entry.id_number', 'appointment.patient.puid', 'triage_entry.patient.puid', 'triage_entry.patient.medical_record_num')] return out # get_encounter_component_set = returns a csv string with the most # recent component listed first def get_encounter_component_set(self, name): if self.encounter: if name == 'encounter_component_count': return len(self.encounter.components) elif name == 'encounter_components': complist = [x.component_type for x in self.encounter.components] return ', '.join(reversed(complist)) if name == 'encounter_component_count': return 0 else: # name == 'encounter_components': return '' # search_component_set : a domain that searches for queue items # with encounters that have component types entered # search_component_count: return a domain to search for queue entries # based on the number of components the associated encounter has # get_qentry_state: return one from QUEUE_ENTRY_STATES based # on the state of the associated appointment and encounter def get_qentry_state(self, name): if self.appointment: if self.appointment.state == 'arrived': return '30' elif self.appointment.state == 'processing': return '40' elif self.appointment.state in APPT_DONE_STATES: return '99' elif self.triage_entry: triage_entry = self.triage_entry if self.triage_entry.done: if (triage_entry.status in TRIAGE_REG_STATES[:2] and not triage_entry.post_appointment): return '20' else: return '99' elif triage_entry.status in TRIAGE_REG_STATES: return '20' elif triage_entry.status == 'triage': return '12' return '10' # search_qentry_state: domain that searches queueEntries based # the specified state entered. @classmethod def search_qentry_state(cls, name, clause): field, operator, operand = clause if operator == '=': # the easy one and maybe the only one we'll need since # entry_state is a selection field if operand == '10': return ['OR', ('triage_entry.status', '=', 'pending'), ('appointment.state', '=', 'confirmed')] elif operand == '12': return [('triage_entry.status', '=', 'triage')] elif operand == '20': return [('triage_entry.status', 'in', TRIAGE_REG_STATES)] elif operand == '30': return [('appointment.state', '=', 'arrived')] elif operand == '40': return [('appointment.state', '=', 'processing')] else: return ['OR', ('appointment.state', 'in', APPT_DONE_STATES), ['AND', ('appointment', '=', None), ['OR', ['AND', ('triage_entry.done', '=', True), ('triage_entry.status', 'not in', TRIAGE_REG_STATES[:2])], ['AND', ('triage_entry.done', '=', True), ('triage_entry.post_appointment', '!=', None)]]]] elif operator == '!=': if operand == '99': # i.e. those that are not done return ['OR', ('appointment.state', 'not in', APPT_DONE_STATES), ['AND', ('appointment', '=', None), ['OR', ('triage_entry.done', '=', False), [('triage_entry.done', '=', True), ('triage_entry.status', 'in', TRIAGE_REG_STATES[:2]), ('triage_entry.post_appointment', '=', None)]]]] if operand == '10': return [ 'OR', ('triage_entry.status', 'in', ['triage'] + TRIAGE_REG_STATES), ('appointment.state', 'in', ['arrived', 'processing'])] def get_sex(self, name): if self.appointment and self.appointment.patient: return self.appointment.patient.name.sex elif self.triage_entry: return self.triage_entry.sex else: return '--' @classmethod def search_sex(cls, name, clause): fld, operator, operand = clause return ['OR', ('triage_entry.sex', operator, operand), ('appointment.patient.name.sex', operator, operand)] def get_age(self, name): if self.appointment: return self.appointment.age else: try: return self.triage_entry.age except AttributeError: return '--' # @classmethod # def search_age(cls, name, clause): # pass def get_notes_info(self, name): details = [] qnotes = [] if self.queue_notes: qnotes = map(lambda x: u' - '.join([x.note, x.byline]), self.queue_notes) details.extend([qnotes.pop(0), '-' * 20]) if self.encounter: details.extend(['Encounter started: %s' % ( localtime(self.encounter.start_time).strftime('%F %T'),), ' %s' % self.encounter.short_summary]) elif self.appointment: a = self.appointment details.extend( [u' '.join(x) for x in [ (u'Appointment: ', localtime(a.appointment_date).strftime('%F %T')), (u' Specialty: ', a.speciality.name), (u' Status: ', a.state)]]) if a.visit_reason: details.insert(-2, ' '.join((u' Reason for visit:', a.visit_reason.rec_name))) # details.append('') # else: if self.triage_entry: details.append('Triage, first contact: %s,\n status: %s' % ( localtime( self.triage_entry.create_date).strftime('%F %T'), self.triage_entry.status_display)) details.extend([' %s' % x for x in filter(None, [self.triage_entry.complaint, self.triage_entry.notes])]) if qnotes: details.extend(['-' * 20] + qnotes) return u'\n'.join(details) @classmethod def get_primary_complaint(cls, instances, name): outd = {} for i in instances: ix = i.id outd[ix] = '' if i.encounter: outd[ix] = i.encounter.primary_complaint if i.triage_entry and not outd[ix]: outd[ix] = i.triage_entry.complaint return outd @classmethod def search_primary_complaint(cls, name, clause): subclause = tuple(clause[1:]) tclause = ('triage_entry.complaint', ) + subclause eclause = ('encounter.primary_complaint', ) + subclause return ['OR', tclause, eclause] def get_specialty(self, name): if self.appointment: return self.appointment.speciality.id else: # return '[Triage]' return None @classmethod def search_specialty(cls, name, clause): subclause = tuple(clause[1:]) newclause = ('appointment.speciality', ) + subclause return ['AND', ('appointment', '!=', None), newclause] # Button Functions for : # Inspect: Does the same as call except doesn't create new records nor # does it update the busy flag on the queue entry # Call: sets busy=True for the selected queue item and opens the # Triage, Appointment or Encounter object associated # If the required related Appointment or Encounter no exist # create it. # Dismiss: Sets busy=False for the selected queue item. @classmethod @ModelView.button_action('health_triage_queue.act_queue_inspect_starter') def btn_inspect(cls, queue_entries): pass @classmethod @ModelView.button_action('health_triage_queue.act_queue_call_starter') def btn_call(cls, queue_entries): user = Transaction().user queue_model = Pool().get('gnuhealth.patient.queue_entry') patients_called_by_user = queue_model.search( ['AND', ('busy', '=', True), ('write_uid', '=', user)]) if len(patients_called_by_user) >= MAX_QUEUE_CALL: patient_names = [] for num, patient in enumerate(patients_called_by_user): (last_name, first_name) = patient.name.split(',') patient_names.append( ' {}. {} {}'.format(num + 1, first_name, last_name)) msg = ['You have exceeded the maximum number of', 'patients that you can call at once. Please', 'finish up and dismiss some of them before', 'calling anyone else', '', 'The ones you have called are:'] msg.extend(patient_names) cls.raise_user_error('\n'.join(msg)) # cls.write(queue_entries, {'busy': True}) # we want to set this to True, but do we want to do it here # or should we do it after the thing launched has been saved or # somehow touched? pass @classmethod @ModelView.button_action('health_triage_queue.act_queue_dismiss_starter') def btn_dismiss(cls, queue_entries): pass @classmethod @ModelView.button_action('health_triage_queue.wiz_queue_appointment_setup') def btn_setup_appointment(cls, queue_entries): pass @classmethod def appointment_arrive_trigger(cls, appointments, trigger): # create a queue entry item for each appointment with state=arrived # 1st, find the appointments already queued already = cls.search_read( [('appointment', 'in', map(int, appointments))], fields_names=['appointment', 'id']) alreadict = dict([(x['appointment'], x['id']) for x in already]) vals = [{'appointment': a.id, 'priority': APM.get(a.urgency, 0), 'busy': False} for a in appointments if a.id not in alreadict] cls.create(vals) def get_visit_reason(self, name): '''get reason for visit''' if self.appointment and self.appointment.visit_reason: return self.appointment.visit_reason.id return None def get_called_by(self, name): '''gets the user who call the selected patient''' return self.write_uid.name if self.write_uid else '' def get_called_by_me(self, name): '''Determines if the carrent selected patient has been called by the current user. Returns true if yes and false otherwise''' user = Transaction().user return self.write_uid.id == user if self.write_uid else False
class Appointment(metaclass=PoolMeta): __name__ = 'gnuhealth.appointment' event = fields.Many2One('calendar.event', 'CalDAV Event', readonly=True, help="Calendar Event", states={'invisible': Not(Bool(Eval('event')))}) appointment_date_end = fields.DateTime('End Date and Time') @classmethod def create(cls, vlist): pool = Pool() Event = pool.get('calendar.event') Patient = pool.get('gnuhealth.patient') Healthprof = pool.get('gnuhealth.healthprofessional') vlist = [x.copy() for x in vlist] for values in vlist: # Check if the event exists (eg, created from a caldav client) # If so, then do not create it again. if 'event' in values: break if values['state'] == 'confirmed': if values['healthprof']: healthprof = Healthprof(values['healthprof']) if (healthprof.name.internal_user and healthprof.name.internal_user.calendar): patient = Patient(values['patient']) appointment_date_end = None if values.get('appointment_date_end'): appointment_date_end = \ values['appointment_date_end'] events = Event.create([{ 'dtstart': values['appointment_date'], 'dtend': appointment_date_end, 'calendar': healthprof.name.internal_user.calendar.id, 'summary': patient.name.rec_name, 'description': values['comments'], }]) values['event'] = events[0].id return super(Appointment, cls).create(vlist) @classmethod def write(cls, appointments, values): pool = Pool() Event = pool.get('calendar.event') Patient = pool.get('gnuhealth.patient') Healthprof = pool.get('gnuhealth.healthprofessional') for appointment in appointments: #Update caldav event if appointment.event and ('healthprof' not in values): if 'appointment_date' in values: Event.write([appointment.event], { 'dtstart': values['appointment_date'], }) if 'appointment_date_end' in values: Event.write([appointment.event], { 'dtend': values['appointment_date_end'], }) if 'patient' in values: patient = Patient(values['patient']) Event.write([appointment.event], { 'summary': patient.name.rec_name, }) if 'comments' in values: Event.write([appointment.event], { 'description': values['comments'], }) else: #Move the event to the new health professional if appointment.event and ('healthprof' in values): current_event = [appointment.event] if appointment.healthprof.name.internal_user: healthprof = Healthprof(values['healthprof']) if healthprof.name.internal_user.calendar: #Health professional has calendar patient = appointment.patient.name.rec_name comments = '' if 'comments' in values: comments = values['comments'] else: comments = appointment.comments if 'appointment_date' in values: appointment_date = values['appointment_date'] else: appointment_date = appointment.appointment_date if 'appointment_date_end' in values: appointment_date_end = values[ 'appointment_date_end'] else: appointment_date_end = appointment.appointment_date_end events = Event.create([{ 'dtstart': appointment_date, 'dtend': appointment_date_end, 'calendar': healthprof.name.internal_user.calendar.id, 'summary': patient, 'description': comments, }]) values['event'] = events[0].id # Delete the event from the current health professional # after it has been transfer to the new healthpfof Event.delete(current_event) return super(Appointment, cls).write(appointments, values) @classmethod def delete(cls, appointments): Event = Pool().get('calendar.event') for appointment in appointments: if appointment.event: Event.delete([appointment.event]) return super(Appointment, cls).delete(appointments)
""" password = PasswordField(_('New Password'), [ validators.DataRequired(), validators.EqualTo('confirm', message=_('Passwords must match'))]) confirm = PasswordField(_('Repeat Password')) class ChangePasswordForm(NewPasswordForm): """ Form to change the password """ old_password = PasswordField(_('Old Password'), [validators.DataRequired()]) STATES = { 'readonly': Not(Bool(Eval('active'))), } class ProfileForm(Form): """User Profile Form""" display_name = TextField( 'Display Name', [validators.DataRequired(), ], description="Your display name" ) timezone = SelectField( 'Timezone', choices=[(tz, tz) for tz in pytz.common_timezones], coerce=unicode, description="Your timezone" ) email = TextField(
class OrderPoint(ModelSQL, ModelView): """ Order Point Provide a way to define a supply policy for each product on each locations. Order points on warehouse are considered by the supply scheduler to generate purchase requests. """ __name__ = 'stock.order_point' product = fields.Many2One('product.product', 'Product', required=True, select=True, domain=[ ('type', '=', 'goods'), ('consumable', '=', False), ('purchasable', 'in', If(Equal(Eval('type'), 'purchase'), [True], [True, False])), ], depends=['type']) warehouse_location = fields.Many2One('stock.location', 'Warehouse Location', select=True, domain=[('type', '=', 'warehouse')], states={ 'invisible': Not( Equal(Eval('type'), 'purchase')), 'required': Equal(Eval('type'), 'purchase'), }, depends=['type']) storage_location = fields.Many2One('stock.location', 'Storage Location', select=True, domain=[('type', '=', 'storage')], states={ 'invisible': Not(Equal(Eval('type'), 'internal')), 'required': Equal(Eval('type'), 'internal'), }, depends=['type']) location = fields.Function(fields.Many2One('stock.location', 'Location'), 'get_location', searcher='search_location') provisioning_location = fields.Many2One( 'stock.location', 'Provisioning Location', domain=[('type', 'in', ['storage', 'view'])], states={ 'invisible': Not(Equal(Eval('type'), 'internal')), 'required': ((Eval('type') == 'internal') & (Eval('min_quantity', None) != None)), }, depends=['type', 'min_quantity']) overflowing_location = fields.Many2One( 'stock.location', 'Overflowing Location', domain=[('type', 'in', ['storage', 'view'])], states={ 'invisible': Eval('type') != 'internal', 'required': ((Eval('type') == 'internal') & (Eval('max_quantity', None) != None)), }, depends=['type', 'max_quantity']) type = fields.Selection([('internal', 'Internal'), ('purchase', 'Purchase')], 'Type', select=True, required=True) min_quantity = fields.Float( 'Minimal Quantity', digits=(16, Eval('unit_digits', 2)), states={ # required for purchase and production types 'required': Eval('type') != 'internal', }, domain=[ 'OR', ('min_quantity', '=', None), ('min_quantity', '<=', Eval('target_quantity', 0)), ], depends=['unit_digits', 'target_quantity', 'type']) target_quantity = fields.Float( 'Target Quantity', required=True, digits=(16, Eval('unit_digits', 2)), domain=[ [ 'OR', ('min_quantity', '=', None), ('target_quantity', '>=', Eval('min_quantity', 0)), ], [ 'OR', ('max_quantity', '=', None), ('target_quantity', '<=', Eval('max_quantity', 0)), ], ], depends=['unit_digits', 'min_quantity', 'max_quantity']) max_quantity = fields.Float( 'Maximal Quantity', digits=(16, Eval('unit_digits', 2)), states={ 'invisible': Eval('type') != 'internal', }, domain=[ 'OR', ('max_quantity', '=', None), ('max_quantity', '>=', Eval('target_quantity', 0)), ], depends=['unit_digits', 'type', 'target_quantity']) company = fields.Many2One('company.company', 'Company', required=True, domain=[ ('id', If(In('company', Eval('context', {})), '=', '!='), Eval('context', {}).get('company', -1)), ]) unit = fields.Function(fields.Many2One('product.uom', 'Unit'), 'get_unit') unit_digits = fields.Function(fields.Integer('Unit Digits'), 'get_unit_digits') @classmethod def __register__(cls, module_name): cursor = Transaction().connection.cursor() sql_table = cls.__table__() table = cls.__table_handler__(module_name) # Migration from 4.2 table.drop_constraint('check_max_qty_greater_min_qty') table.not_null_action('min_quantity', 'remove') table.not_null_action('max_quantity', 'remove') target_qty_exist = table.column_exist('target_quantity') super(OrderPoint, cls).__register__(module_name) # Migration from 4.2 if not target_qty_exist: cursor.execute(*sql_table.update( [sql_table.target_quantity, sql_table.max_quantity], [sql_table.max_quantity, Null])) @staticmethod def default_type(): return "purchase" @fields.depends('product', '_parent_product.default_uom') def on_change_product(self): self.unit = None self.unit_digits = 2 if self.product: self.unit = self.product.default_uom self.unit_digits = self.product.default_uom.digits def get_unit(self, name): return self.product.default_uom.id def get_unit_digits(self, name): return self.product.default_uom.digits @classmethod def validate(cls, orderpoints): super(OrderPoint, cls).validate(orderpoints) cls.check_concurrent_internal(orderpoints) cls.check_uniqueness(orderpoints) @classmethod def check_concurrent_internal(cls, orders): """ Ensure that there is no 'concurrent' internal order points. I.E. no two order point with opposite location for the same product and same company. """ internals = cls.search([ ('id', 'in', [o.id for o in orders]), ('type', '=', 'internal'), ]) if not internals: return for location_name in ['provisioning_location', 'overflowing_location']: query = [] for op in internals: if getattr(op, location_name, None) is None: continue arg = [ 'AND', ('product', '=', op.product.id), (location_name, '=', op.storage_location.id), ('storage_location', '=', getattr(op, location_name).id), ('company', '=', op.company.id), ('type', '=', 'internal') ] query.append(arg) if query and cls.search(['OR'] + query): raise OrderPointValidationError( gettext('stock_supply' '.msg_order_point_concurrent_%s_internal' % location_name)) @staticmethod def _type2field(type=None): t2f = { 'purchase': 'warehouse_location', 'internal': 'storage_location', } if type is None: return t2f else: return t2f[type] @classmethod def check_uniqueness(cls, orders): """ Ensure uniqueness of order points. I.E that there is no several order point for the same location, the same product and the same company. """ query = ['OR'] for op in orders: field = cls._type2field(op.type) arg = [ 'AND', ('product', '=', op.product.id), (field, '=', getattr(op, field).id), ('id', '!=', op.id), ('company', '=', op.company.id), ] query.append(arg) if cls.search(query): raise OrderPointValidationError( gettext('stock_supply.msg_order_point_unique')) def get_rec_name(self, name): return "%s @ %s" % (self.product.name, self.location.name) @classmethod def search_rec_name(cls, name, clause): return [ 'OR', ('location.rec_name', ) + tuple(clause[1:]), ('product.rec_name', ) + tuple(clause[1:]), ] def get_location(self, name): if self.type == 'purchase': return self.warehouse_location.id elif self.type == 'internal': return self.storage_location.id @classmethod def search_location(cls, name, domain=None): clauses = ['OR'] for type, field in cls._type2field().items(): clauses.append([ ('type', '=', type), (field, ) + tuple(domain[1:]), ]) return clauses @staticmethod def default_company(): return Transaction().context.get('company')
class OrderPoint(ModelSQL, ModelView): """ Order Point Provide a way to define a supply policy for each product on each locations. Order points on warehouse are considered by the supply scheduler to generate purchase requests. """ __name__ = 'stock.order_point' product = fields.Many2One('product.product', 'Product', required=True, select=True, domain=[ ('type', '=', 'goods'), ('consumable', '=', False), ('purchasable', 'in', If(Equal(Eval('type'), 'purchase'), [True], [True, False])), ], depends=['type']) warehouse_location = fields.Many2One('stock.location', 'Warehouse Location', select=True, domain=[('type', '=', 'warehouse')], states={ 'invisible': Not(Equal(Eval('type'), 'purchase')), 'required': Equal(Eval('type'), 'purchase'), }, depends=['type']) storage_location = fields.Many2One('stock.location', 'Storage Location', select=True, domain=[('type', '=', 'storage')], states={ 'invisible': Not(Equal(Eval('type'), 'internal')), 'required': Equal(Eval('type'), 'internal'), }, depends=['type']) location = fields.Function(fields.Many2One('stock.location', 'Location'), 'get_location', searcher='search_location') provisioning_location = fields.Many2One( 'stock.location', 'Provisioning Location', domain=[('type', 'in', ['storage', 'view'])], states={ 'invisible': Not(Equal(Eval('type'), 'internal')), 'required': Equal(Eval('type'), 'internal'), }, depends=['type']) type = fields.Selection( [('internal', 'Internal'), ('purchase', 'Purchase')], 'Type', select=True, required=True) min_quantity = fields.Float('Minimal Quantity', required=True, digits=(16, Eval('unit_digits', 2)), depends=['unit_digits']) max_quantity = fields.Float('Maximal Quantity', required=True, digits=(16, Eval('unit_digits', 2)), depends=['unit_digits']) company = fields.Many2One('company.company', 'Company', required=True, domain=[ ('id', If(In('company', Eval('context', {})), '=', '!='), Eval('context', {}).get('company', -1)), ]) unit = fields.Function(fields.Many2One('product.uom', 'Unit'), 'get_unit') unit_digits = fields.Function(fields.Integer('Unit Digits'), 'get_unit_digits') @classmethod def __setup__(cls): super(OrderPoint, cls).__setup__() t = cls.__table__() cls._sql_constraints += [ ('check_max_qty_greater_min_qty', Check(t, t.max_quantity >= t.min_quantity), 'Maximal quantity must be bigger than Minimal quantity'), ] cls._error_messages.update({ 'unique_op': ('Only one order point is allowed ' 'for each product-location pair.'), 'concurrent_internal_op': ('You can not define ' 'two order points on the same product ' 'with opposite locations.'), }) @classmethod def __register__(cls, module_name): TableHandler = backend.get('TableHandler') # Migration from 2.2 table = TableHandler(cls, module_name) table.drop_constraint('check_min_max_quantity') super(OrderPoint, cls).__register__(module_name) @staticmethod def default_type(): return "purchase" @fields.depends('product') def on_change_product(self): self.unit = None self.unit_digits = 2 if self.product: self.unit = self.product.default_uom self.unit_digits = self.product.default_uom.digits def get_unit(self, name): return self.product.default_uom.id def get_unit_digits(self, name): return self.product.default_uom.digits @classmethod def validate(cls, orderpoints): super(OrderPoint, cls).validate(orderpoints) cls.check_concurrent_internal(orderpoints) cls.check_uniqueness(orderpoints) @classmethod def check_concurrent_internal(cls, orders): """ Ensure that there is no 'concurrent' internal order points. I.E. no two order point with opposite location for the same product and same company. """ internals = cls.search([ ('id', 'in', [o.id for o in orders]), ('type', '=', 'internal'), ]) if not internals: return query = ['OR'] for op in internals: arg = ['AND', ('product', '=', op.product.id), ('provisioning_location', '=', op.storage_location.id), ('storage_location', '=', op.provisioning_location.id), ('company', '=', op.company.id), ('type', '=', 'internal')] query.append(arg) if cls.search(query): cls.raise_user_error('concurrent_internal_op') @staticmethod def _type2field(type=None): t2f = { 'purchase': 'warehouse_location', 'internal': 'storage_location', } if type is None: return t2f else: return t2f[type] @classmethod def check_uniqueness(cls, orders): """ Ensure uniqueness of order points. I.E that there is no several order point for the same location, the same product and the same company. """ query = ['OR'] for op in orders: field = cls._type2field(op.type) arg = ['AND', ('product', '=', op.product.id), (field, '=', getattr(op, field).id), ('id', '!=', op.id), ('company', '=', op.company.id), ] query.append(arg) if cls.search(query): cls.raise_user_error('unique_op') def get_rec_name(self, name): return "%s@%s" % (self.product.name, self.location.name) @classmethod def search_rec_name(cls, name, clause): res = [] names = clause[2].split('@', 1) res.append(('product.template.name', clause[1], names[0])) if len(names) != 1 and names[1]: res.append(('location', clause[1], names[1])) return res def get_location(self, name): if self.type == 'purchase': return self.warehouse_location.id elif self.type == 'internal': return self.storage_location.id @classmethod def search_location(cls, name, domain=None): ids = [] for type, field in cls._type2field().iteritems(): args = [('type', '=', type)] for _, operator, operand in domain: args.append((field, operator, operand)) ids.extend([o.id for o in cls.search(args)]) return [('id', 'in', ids)] @staticmethod def default_company(): return Transaction().context.get('company')
from trytond.model import ModelView, Workflow, ModelSQL, fields, Check, Unique from trytond.wizard import Wizard, StateView, StateTransition, Button from trytond.pyson import Not, Equal, Eval, Or, Bool, If from trytond import backend from trytond.transaction import Transaction from trytond.pool import Pool from trytond.tools import reduce_ids, grouped_slice __all__ = [ 'Forecast', 'ForecastLine', 'ForecastLineMove', 'ForecastCompleteAsk', 'ForecastCompleteChoose', 'ForecastComplete' ] STATES = { 'readonly': Not(Equal(Eval('state'), 'draft')), } DEPENDS = ['state'] class Forecast(Workflow, ModelSQL, ModelView): "Stock Forecast" __name__ = "stock.forecast" _rec_name = 'warehouse' warehouse = fields.Many2One('stock.location', 'Location', required=True, domain=[('type', '=', 'warehouse')], states={ 'readonly': Or(Not(Equal(Eval('state'), 'draft')),
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 Invoice: __metaclass__ = PoolMeta __name__ = 'account.invoice' payment_type_kind = fields.Function( fields.Selection( [ ('payable', 'Payable'), ('receivable', 'Receivable'), ], 'Kind of payment type', states={ 'invisible': True, }, ), 'on_change_with_payment_type_kind') payment_type = fields.Many2One( 'account.payment.type', 'Payment Type', domain=[ ('kind', '=', Eval('payment_type_kind')), ], states={ 'readonly': Not(Bool(Eval('state').in_(['draft', 'validated']))), }, depends=['payment_type_kind', 'state']) @fields.depends('type', 'untaxed_amount', 'lines') def on_change_with_payment_type_kind(self, name=None): if self.untaxed_amount: if self.type == 'out': if self.untaxed_amount >= ZERO: return 'receivable' else: return 'payable' elif self.type == 'in': if self.untaxed_amount >= ZERO: return 'payable' else: return 'receivable' return 'receivable' if self.type == 'out' else 'payable' @fields.depends('party', 'company', 'type', 'untaxed_amount', 'lines', 'payment_type', methods=['payment_type_kind']) def on_change_with_payment_type(self, name=None): kind = self.on_change_with_payment_type_kind() if (self.payment_type and self.payment_type.kind == kind): return self.payment_type.id if not self.untaxed_amount: return None if self.party: if self.type == 'out': if (self.untaxed_amount >= ZERO and self.party.customer_payment_type): return self.party.customer_payment_type.id elif (self.untaxed_amount < ZERO and self.party.supplier_payment_type): return self.party.supplier_payment_type.id elif self.type == 'in': if (self.untaxed_amount >= ZERO and self.party.supplier_payment_type): return self.party.supplier_payment_type.id elif (self.untaxed_amount < ZERO and self.party.customer_payment_type): return self.party.customer_payment_type.id if self.company: if self.type == 'out': if (self.untaxed_amount >= ZERO and self.company.party.customer_payment_type): return self.company.party.customer_payment_type.id elif (self.untaxed_amount < ZERO and self.company.party.supplier_payment_type): return self.company.party.supplier_payment_type.id elif self.type == 'in': if (self.untaxed_amount >= ZERO and self.company.party.supplier_payment_type): return self.company.party.supplier_payment_type.id elif (self.untaxed_amount < ZERO and self.company.party.customer_payment_type): return self.company.party.customer_payment_type.id return None @classmethod def post(cls, invoices): pool = Pool() Date = pool.get('ir.date') Payment = pool.get('account.payment') PayLine = pool.get('account.move.line.pay', type='wizard') super(Invoice, cls).post(invoices) lines_to_pay = defaultdict(list) for invoice in invoices: if (invoice.payment_type and invoice.payment_type.payment_journal): for line in invoice.lines_to_pay: key = (invoice.payment_type, line.maturity_date) lines_to_pay[key].append(line.id) to_approve = [] for key, lines in lines_to_pay.iteritems(): payment_type, date = key session_id, _, _ = PayLine.create() payline = PayLine(session_id) payline.start.journal = payment_type.payment_journal payline.start.date = date or Date.today() payline.start.approve = True with Transaction().set_context(active_ids=lines): action, data = payline.do_pay(None) if payment_type.approve_payments: to_approve.extend(data['res_id']) PayLine.delete(session_id) if to_approve: Payment.approve(Payment.browse(to_approve))
# -*- encoding: utf-8 -*- #NOTE: Заявки на деньги "Document Request for money" from trytond.model import ModelView, ModelSQL, ModelStorage, fields from trytond.transaction import Transaction from trytond.report import Report from trytond.tools import safe_eval import time from decimal import Decimal, ROUND_HALF_EVEN from trytond.pyson import In, If, Get, Eval, Not, Equal, Bool, Or, And import time import datetime from ekd_state_document import _STATE_REQUEST _REQUEST_STATES = { 'readonly': Not(In(Eval('state_doc'), ['empty', 'draft'])), } _REQUEST_DEPENDS = ['state_doc'] _LINE_STATES = { 'readonly': Equal(Eval('state_doc'), 'draft'), } _LINE_DEPENDS = ['state_doc'] _ISSUE_STATES = { 'readonly': Not(In(Eval('state_doc'), ['empty', 'draft', 'confirmed', 'payment'])), }
('spouse', 'spouse'), ('sibling', 'sibling'), ('grandparent', 'grandchild'), ('auntuncle', 'niecenephew'), ('cousin', 'cousin'), ('friend', 'friend'), ('coworker', 'coworker'), ('girlboyfriend', 'girlboyfriend'), ('employer', 'employee'), ('other', 'other'), ] NNre = re.compile('(%?)NN-(.*)', re.I) _STATES = { 'invisible': Not(Bool(Eval('is_person'))), } class PartyPatient(ModelSQL, ModelView): 'Party' __name__ = 'party.party' upi = fields.Function(fields.Char('UPI', help='Unique Party Identifier'), 'get_upi_display', searcher='search_upi') firstname = fields.Char('First name', states=_STATES, depends=_DEPENDS, select=True) middlename = fields.Char('Middle Name', states=_STATES, depends=_DEPENDS, help="Middle name or names of Patient") maiden_name = fields.Char( 'Maiden Name',
class DocumentRequestLine(ModelSQL, ModelView): "Document specifications of Request" _name = 'ekd.document.line.request' _description = __doc__ requestcash = fields.Many2One('ekd.document.head.request', 'Document Request', ondelete='CASCADE', select=1) type = fields.Selection([ ('line', 'Line'), ('subtotal', 'Subtotal'), ], 'Type', select=1, required=True, states={ 'invisible': Bool(Eval('standalone')), }) name = fields.Char('Description', states=_LINE_STATES, depends=_LINE_DEPENDS) note = fields.Text('Note', states=_LINE_STATES, depends=_LINE_DEPENDS) product = fields.Many2One('product.product', 'Product', states=_LINE_STATES, depends=_LINE_DEPENDS) uom = fields.Many2One('product.uom', 'Unit', states={ 'required': Bool(Eval('product')), 'readonly': Not(Equal(Eval('state'), 'draft')) }, domain=[('category', '=', (Eval('product'), 'product.default_uom.category'))], context={ 'category': (Eval('product'), 'product.default_uom.category') }) quantity = fields.Float('Quantity', digits=(16, Eval('currency_digits', 2)), states=_LINE_STATES, depends=_LINE_DEPENDS) unit_digits = fields.Function( fields.Integer('Unit Digits', on_change_with=['uom']), 'get_fields') unit_price = fields.Numeric('Price Unit', digits=(16, Eval('currency_digits', 2)), states=_LINE_STATES, depends=_LINE_DEPENDS) lines_received = fields.One2Many('ekd.document.line.payment', 'line_request', 'Line Amount Received') amount_request = fields.Numeric('Amount Request', digits=(16, Eval('currency_digits', 2)), states=_LINE_STATES, depends=_LINE_DEPENDS) amount_received = fields.Function( fields.Numeric('Amount Received', digits=(16, Eval('currency_digits', 2))), 'get_fields') amount_balance = fields.Function( fields.Numeric('Balance', digits=(16, Eval('currency_digits', 2)), readonly=True, on_change_with=['amount_request', 'amount_received']), 'get_fields') amount_payment = fields.Function(fields.Numeric( 'Amount Payment', digits=(16, Eval('currency_digits', 2))), 'get_fields', setter='set_fields') currency_digits = fields.Function(fields.Integer('Currency Digits'), 'get_currency_digits') state = fields.Selection([ ('draft', 'Draft'), ('request', 'Request'), ('confirmed', 'Confirmed'), ('payment', 'Payment'), ('partially', 'Partially'), ('fully', 'Fully'), ('done', 'Done'), ('deleted', 'Deleted'), ], 'State', readonly=True) def default_state(self): return 'draft' def default_type(self): return 'line' def default_currency_digits(self): return Transaction().context.get('currency_digits', 2) def get_fields(self, ids, names): if not ids: return {} res = {} for request in self.browse(ids): for name in names: res.setdefault(name, {}) res[name].setdefault(request.id, {}) if name == 'amount_balance': res[name][ request. id] = request.amount_request - request.amount_received elif name == 'unit_digits': if request.uom: res[name][request.id] = request.uom.digits else: res[name][request.id] = 2 elif name == 'amount_payment': amount_payment = Decimal('0.0') for line_received in request.lines_received: if line_received.state == 'payment': amount_payment += line_received.amount_payment res[name][request.id] = amount_payment # res[name][request.id] = request.amount_request-request.amount_received elif name == 'amount_received': amount_received = Decimal('0.0') for line_received in request.lines_received: if line_received.state == 'done': amount_received += line_received.amount_payment res[name][request.id] = amount_received return res def set_fields(self, id, name, value): if not value: return def get_currency_digits(self, ids, name): res = {} for line in self.browse(ids): res[line. id] = line.requestcash.currency and line.requestcash.currency.digits or 2 return res def on_change_with_amount_balance(self, vals): if vals.get('amount_request') and vals.get('amount_received'): return vals.get('amount_request') - vals.get('amount_received') elif vals.get('amount_request'): return vals.get('amount_request') else: return Decimal('0.0')
class PartyRelative(ModelSQL, ModelView): 'Relative/NOK/Employer' __name__ = 'party.relative' party = fields.Many2One('party.party', 'Patient', required=True, ondelete='CASCADE') relative = fields.Many2One( 'party.party', 'Relative', ondelete='CASCADE', domain=[('id', '!=', Eval('party'))], states={'invisible': Not(Eval('is_party', False)), 'required': Eval('is_party', False), 'readonly': Eval('id', 0) > 0}) relationship = fields.Selection(RELATIONSHIP_LIST, 'Relationship', help='Relationship of contact to patient') relationship_display = fields.Function(fields.Char('Relationship'), 'get_relationship_display') relative_summary = fields.Function(fields.Text('Relative Summary', states={'invisible': Or(Eval('id', 0) <= 0, ~Eval('is_party', False))}), 'get_relative_val') phone_number = fields.Function(fields.Char('Phone/Mobile'), 'get_relative_val') party_relative_summary = fields.Function(fields.Text('Relative Summary'), 'get_relative_val') party_phone_number = fields.Function(fields.Char('Phone/Mobile'), 'get_relative_val') relationship_reverse = fields.Function(fields.Selection(RELATIONSHIP_LIST, 'Relationship'), 'get_reverse_relationship') is_party = fields.Boolean('Relative is a party', help='Check to select the party that represents' ' this relative', states={'readonly': Eval('id', 0) > 0}) relative_name = fields.Function(fields.Char('Relative'), 'get_relative_name', searcher='search_relative_name') relative_lastname = fields.Char('Last name', states=NOTPARTY_RSTATES) relative_firstname = fields.Char('Given name(s)', states=NOTPARTY_RSTATES) relative_sex = fields.Selection([(None, '')] + SEX_OPTIONS, 'Sex', states=NOTPARTY_RSTATES) relative_country = fields.Many2One('country.country', 'Country', states=NOTPARTY_STATES) relative_state = fields.Many2One('country.subdivision', 'Parish/Province', domain=[('country', '=', Eval('relative_country'))], states=NOTPARTY_STATES) relative_address = fields.Text('Address details', states=NOTPARTY_STATES) relative_phone = fields.Char('Phone/Mobile number(s)', states=NOTPARTY_STATES, help='Separate multiple numbers with comma (,)') @staticmethod def default_is_party(): return False @staticmethod def default_relative_country(): country = Pool().get('country.country') jm, = country.search([('code', '=', 'JM')]) return jm.id def get_relative_val(self, field_name): if field_name in ['phone_number', 'party_phone_number', 'relative_summary', 'party_relative_summary']: # return a formatted text summary for the NOK # to include phone(s), email, address[0] sexdict = dict([(None, '')] + SEX_OPTIONS) if field_name.startswith('party'): partyobj = self.party elif self.is_party: partyobj = self.relative else: # work out the required field using the internal fields if 'phone_number' in field_name: return self.relative_phone else: # summary, we'll include sex and address rdata = [('Sex', sexdict.get(self.relative_sex, '')), ('Address', '')] if self.relative_address and self.relative_state and self.relative_country: rdata.append( ('', '%s\n%s, %s' % (self.relative_address, self.relative_state.name, self.relative_country.name))) partyobj = False v = '\n'.join([': '.join(x) for x in rdata]) if partyobj: rdata = [] contact_types = ['phone', 'mobile', 'email'] for mech in partyobj.contact_mechanisms: if mech.type in contact_types: rdata.append((mech.type.capitalize(), mech.value)) if 'phone_number' in field_name: v = ', '.join([y for x,y in rdata if x in ['Phone', 'Mobile']]) else: rdata.insert(0, ('Sex', sexdict.get(partyobj.sex, ''))) num_addresses = len(partyobj.addresses) - 1 if num_addresses >= 0: rdata.append(('Address', '')) rdata.append(('', partyobj.addresses[0].simple_address)) if num_addresses: rdata.append(('...', '(and %d more)' % num_addresses)) v = '\n'.join([': '.join(x) for x in rdata]) else: # return the singular value from the NOK if we can try: v = getattr(self.relative, field_name) except AttributeError, e: print repr(e) v = None return v
METRIC_CONV = {'length': (1 / 2.54), 'weight': 2.20462262} URINALYSIS = { 'default': [('neg', 'negative'), ('trace', 'trace'), ('+', '+'), ('++', '2+'), ('+++', '3+'), ('++++', '4+'), ('+++++', '5+')], 'nitrite': [('neg.', 'negative'), ('trace', 'trace'), ('small', 'small'), ('moderate', 'moderate'), ('large', 'large'), ('large+', 'large+')] } PYSON_MALE = Equal(Eval('encounter.patient.sex', ''), 'm'), PYSON_FEMALE = Equal(Eval('encounter.patient.sex', ''), 'f'), PYSON_MENARCH = Eval('encounter.patient.childbearing_age', False) STATE_NO_MENSES = { 'readonly': Not(Eval('childbearing_age', True)), 'invisible': Not(Eval('childbearing_age', True)) } for key in STATE_NO_MENSES: if key in SIGNED_STATES: STATE_NO_MENSES[key] = Or(STATE_NO_MENSES[key], SIGNED_STATES[key]) class EncounterAnthro(BaseComponent): 'Anthropometry' __name__ = 'gnuhealth.encounter.anthropometry' weight = fields.Float('Weight (kg)', help='Weight in Kilos', states=SIGNED_STATES) height = fields.Float('Height (cm)',
class ApacheII(ModelSQL, ModelView): 'Apache II scoring' __name__ = 'gnuhealth.icu.apache2' name = fields.Many2One('gnuhealth.inpatient.registration', 'Registration Code', required=True) score_date = fields.DateTime('Date', help="Date of the score", required=True) age = fields.Integer('Age', help='Patient age in years') temperature = fields.Float('Temperature', help='Rectal temperature') mean_ap = fields.Integer('MAP', help='Mean Arterial Pressure') heart_rate = fields.Integer('Heart Rate') respiratory_rate = fields.Integer('Respiratory Rate') fio2 = fields.Float('FiO2') pao2 = fields.Integer('PaO2') paco2 = fields.Integer('PaCO2') aado2 = fields.Integer('A-a DO2') ph = fields.Float('pH') serum_sodium = fields.Integer('Sodium') serum_potassium = fields.Float('Potassium') serum_creatinine = fields.Float('Creatinine') arf = fields.Boolean('ARF', help='Acute Renal Failure') wbc = fields.Float('WBC', help="White blood cells x 1000 - if you" " want to input 4500 wbc / ml, type in 4.5") hematocrit = fields.Float('Hematocrit') gcs = fields.Integer( 'GSC', help='Last Glasgow Coma Scale' ' You can use the GSC calculator from the Patient Evaluation Form.') chronic_condition = fields.Boolean( 'Chronic condition', help='Organ Failure or immunocompromised patient') hospital_admission_type = fields.Selection( [(None, ''), ('me', 'Medical or emergency postoperative'), ('el', 'elective postoperative')], 'Hospital Admission Type', states={ 'invisible': Not(Bool(Eval('chronic_condition'))), 'required': Bool(Eval('chronic_condition')) }, sort=False) apache_score = fields.Integer('Score') #Default FiO2 PaO2 and PaCO2 so we do the A-a gradient #calculation with non-null values @fields.depends('fio2', 'pao2', 'paco2') def on_change_with_aado2(self): # Calculates the Alveolar-arterial difference # based on FiO2, PaCO2 and PaO2 values if (self.fio2 and self.paco2 and self.pao2): return (713 * self.fio2) - (self.paco2 / 0.8) - self.pao2 @fields.depends('age', 'temperature', 'mean_ap', 'heart_rate', 'respiratory_rate', 'fio2', 'pao2', 'aado2', 'ph', 'serum_sodium', 'serum_potassium', 'serum_creatinine', 'arf', 'wbc', 'hematocrit', 'gcs', 'chronic_condition', 'hospital_admission_type') def on_change_with_apache_score(self): # Calculate the APACHE SCORE from the variables in the total = 0 # Age if (self.age): if (self.age > 44 and self.age < 55): total = total + 2 elif (self.age > 54 and self.age < 65): total = total + 3 elif (self.age > 64 and self.age < 75): total = total + 5 elif (self.age > 74): total = total + 6 # Temperature if (self.temperature): if ((self.temperature >= 38.5 and self.temperature < 39) or (self.temperature >= 34 and self.temperature < 36)): total = total + 1 elif (self.temperature >= 32 and self.temperature < 34): total = total + 2 elif ((self.temperature >= 30 and self.temperature < 32) or (self.temperature >= 39 and self.temperature < 41)): total = total + 3 elif (self.temperature >= 41 or self.temperature < 30): total = total + 4 # Mean Arterial Pressure (MAP) if (self.mean_ap): if ((self.mean_ap >= 110 and self.mean_ap < 130) or (self.mean_ap >= 50 and self.mean_ap < 70)): total = total + 2 elif (self.mean_ap >= 130 and self.mean_ap < 160): total = total + 3 elif (self.mean_ap >= 160 or self.mean_ap < 50): total = total + 4 # Heart Rate if (self.heart_rate): if ((self.heart_rate >= 55 and self.heart_rate < 70) or (self.heart_rate >= 110 and self.heart_rate < 140)): total = total + 2 elif ((self.heart_rate >= 40 and self.heart_rate < 55) or (self.heart_rate >= 140 and self.heart_rate < 180)): total = total + 3 elif (self.heart_rate >= 180 or self.heart_rate < 40): total = total + 4 # Respiratory Rate if (self.respiratory_rate): if ((self.respiratory_rate >= 10 and self.respiratory_rate < 12) or (self.respiratory_rate >= 25 and self.respiratory_rate < 35)): total = total + 1 elif (self.respiratory_rate >= 6 and self.respiratory_rate < 10): total = total + 2 elif (self.respiratory_rate >= 35 and self.respiratory_rate < 50): total = total + 3 elif (self.respiratory_rate >= 50 or self.respiratory_rate < 6): total = total + 4 # FIO2 if (self.fio2): # If Fi02 is greater than 0.5, we measure the AaDO2 gradient # Otherwise, we take into account the Pa02 value if (self.fio2 >= 0.5): if (self.aado2 >= 200 and self.aado2 < 350): total = total + 2 elif (self.aado2 >= 350 and self.aado2 < 500): total = total + 3 elif (self.aado2 >= 500): total = total + 4 else: if (self.pao2 >= 61 and self.pao2 < 71): total = total + 1 elif (self.pao2 >= 55 and self.pao2 < 61): total = total + 3 elif (self.pao2 < 55): total = total + 4 # Arterial pH if (self.ph): if (self.ph >= 7.5 and self.ph < 7.6): total = total + 1 elif (self.ph >= 7.25 and self.ph < 7.33): total = total + 2 elif ((self.ph >= 7.15 and self.ph < 7.25) or (self.ph >= 7.6 and self.ph < 7.7)): total = total + 3 elif (self.ph >= 7.7 or self.ph < 7.15): total = total + 4 # Serum Sodium if (self.serum_sodium): if (self.serum_sodium >= 150 and self.serum_sodium < 155): total = total + 1 elif ((self.serum_sodium >= 155 and self.serum_sodium < 160) or (self.serum_sodium >= 120 and self.serum_sodium < 130)): total = total + 2 elif ((self.serum_sodium >= 160 and self.serum_sodium < 180) or (self.serum_sodium >= 111 and self.serum_sodium < 120)): total = total + 3 elif (self.serum_sodium >= 180 or self.serum_sodium < 111): total = total + 4 # Serum Potassium if (self.serum_potassium): if ((self.serum_potassium >= 3 and self.serum_potassium < 3.5) or (self.serum_potassium >= 5.5 and self.serum_potassium < 6)): total = total + 1 elif (self.serum_potassium >= 2.5 and self.serum_potassium < 3): total = total + 2 elif (self.serum_potassium >= 6 and self.serum_potassium < 7): total = total + 3 elif (self.serum_potassium >= 7 or self.serum_potassium < 2.5): total = total + 4 # Serum Creatinine if (self.serum_creatinine): arf_factor = 1 if (self.arf): # We multiply by 2 the score if there is concomitant ARF arf_factor = 2 if ((self.serum_creatinine < 0.6) or (self.serum_creatinine >= 1.5 and self.serum_creatinine < 2)): total = total + 2 * arf_factor elif (self.serum_creatinine >= 2 and self.serum_creatinine < 3.5): total = total + 3 * arf_factor elif (self.serum_creatinine >= 3.5): total = total + 4 * arf_factor # Hematocrit if (self.hematocrit): if (self.hematocrit >= 46 and self.hematocrit < 50): total = total + 1 elif ((self.hematocrit >= 50 and self.hematocrit < 60) or (self.hematocrit >= 20 and self.hematocrit < 30)): total = total + 2 elif (self.hematocrit >= 60 or self.hematocrit < 20): total = total + 4 # WBC ( x 1000 ) if (self.wbc): if (self.wbc >= 15 and self.wbc < 20): total = total + 1 elif ((self.wbc >= 20 and self.wbc < 40) or (self.wbc >= 1 and self.wbc < 3)): total = total + 2 elif (self.wbc >= 40 or self.wbc < 1): total = total + 4 # Immnunocompromised or severe organ failure if (self.chronic_condition): if (self.hospital_admission_type == 'me'): total = total + 5 else: total = total + 2 return total
# -*- encoding: utf-8 -*-. #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. 'Address' from trytond.model import ModelView, ModelSQL, fields from trytond.transaction import Transaction from trytond.pyson import If, Greater, Eval, Not, Bool, Eval STATES = { 'readonly': Not(Bool("active")), } class Bank(ModelSQL, ModelView): "Bank" _name = 'ekd.party.bank' _description = __doc__ name = fields.Char('Name', size=None, states=STATES) shortname = fields.Char('ShortName', size=None, states=STATES) city = fields.Char('City', size=None, states=STATES) zip = fields.Char('Zip', size=6, states=STATES) phone = fields.Char('Phones', size=None, states=STATES) address = fields.Char('Address', size=None, states=STATES) rkc = fields.Char('RKC', size=9, states=STATES) okpo = fields.Char('OKPO', size=8, states=STATES) corr_account = fields.Char('Corr Account', size=None, states=STATES) bic = fields.Char('BIC', size=9, states=STATES) start_date = fields.Date('Date Start') change_date = fields.Date('Date Change') end_date = fields.Date('Date End')