import time from random import random from datetime import datetime, timedelta from netforce.model import Model, fields, get_model from netforce.access import get_active_company, get_active_user, set_active_user FMT_DATE="%Y-%m-%d %H:%M:%S" class Visit(Model): _name="clinic.visit" _string="Visit" _audit_log=True _name_field="number" _multi_company=True def _get_print_date(self,ids,context={}): res={} for obj in self.browse(ids): res[obj.id]=datetime.now().strftime("%Y-%m-%d %H:%M:%S") return res def _get_all(self,ids,context={}): res={} for obj in self.browse(ids): cycle=obj.cycle_id color=cycle.color patient=obj.patient_id res[obj.id]={ 'cycle_color': color, 'sequence': '%s-%s'%(obj.time_start[0:10],cycle.sequence), #date-sequence 'patient_name': patient_id.name, 'patient_type_id': patient_id.type_id.id, } return res _fields={ "number": fields.Char("Number",required=True,search=True), "time_start": fields.DateTime("Start Time",required=True), "time_stop": fields.DateTime("End Time",required=True), "patient_id": fields.Many2One("clinic.patient","Patient",required=True,search=True,domain=[['state','=','admit']]), "doctor_id": fields.Many2One("clinic.staff","Doctor", domain=[['type','=','doctor']],search=True), "nurse_id": fields.Many2One("clinic.staff","Confirm By", domain=[['type','=','nurse']],search=True), "department_id": fields.Many2One("clinic.department", "Department",search=True), "comments": fields.One2Many("message","related_id","Comments"), "company_id": fields.Many2One("company","Company"), 'hd_cases': fields.One2Many('clinic.hd.case','visit_id',"HD Cases",readonly=True), "cycle_id": fields.Many2One("clinic.cycle","Cycle"), "state": fields.Selection([["draft","Draft"],['pending','Pending'],["confirmed","Confirmed"],["cancelled","Cancelled"]],"Status",required=True), "comments": fields.One2Many("message","related_id","Comments"), 'print_date': fields.Date('Print Date',function="_get_print_date"), 'cycle_item_id': fields.Many2One("clinic.cycle.item","Cycle Item"), #XXX on_delete="cascade" -> rm visit from cycle item 'sequence': fields.Char("Sequence",function="_get_all",function_multi=True,store=True), 'visit_date': fields.Date('Date',required=True), 'cycle_color': fields.Char('Color',function="_get_all",function_multi=True,store=True), 'note': fields.Text('Note'), 'branch_id': fields.Many2One("clinic.branch","Branch"), 'manual': fields.Boolean("Manual Tempolary Visit"), "patient_name": fields.Char("Patient Name", function="_get_all", store=True, search=True), "patient_type_id": fields.Char("Patient Type", function="_get_all", store=True, search=True), } def _get_number(self,context={}): while 1: seq_type='clinic_visit' seq_id=get_model("sequence").find_sequence(type=seq_type,context=context) if not seq_id: raise Exception("Can not found sequence %s"%seq_type) num=get_model("sequence").get_next_number(seq_id,context=context) if not num: return None user_id=get_active_user() set_active_user(1) res=self.search([["number","=",num]]) set_active_user(user_id) if not res: return num get_model("sequence").increment_number(seq_id,context=context) def _get_nurse(self,context={}): user_id=get_active_user() nurse_ids=get_model("clinic.staff").search([['user_id','=',user_id],['type','=','nurse']]) if nurse_ids: return nurse_ids[0] return None def _get_time_start(self,context={}): now=datetime.now() starttime=now.strftime("%Y-%m-%d %H:%M:%S") return starttime def _get_time_stop(self,context={}): hr=timedelta(seconds=3600) now=datetime.now() stoptime=(now+hr).strftime("%Y-%m-%d %H:%M:%S") return stoptime _defaults={ "state": "draft", 'time_start': _get_time_start, 'time_stop': _get_time_stop, 'visit_date': lambda *a: time.strftime("%Y-%m-%d"), "number": "/", "company_id": lambda *a: get_active_company(), 'nurse_id': _get_nurse, 'manual': False, } #_sql_constraints=("clinic_visit_key_uniq","unique(patient_id,visit_date,cycle_id,department_id)","Patient is already exist in this date"), _order="sequence" def new_dlz(self,patient_id,department_id): if not patient_id: raise Exception("No Patient to creat Dialyzer") if not department_id: raise Exception("No Department to creat Dialyzer") dlz_vals=get_model("clinic.dialyzer").default_get() dlz_vals['product_id']=dlz_vals['product_id'][0] dlz_vals['company_id']=dlz_vals['company_id'][0] dlz_vals['patient_id']=patient_id dlz_vals['department_id']=department_id dlz_id=get_model('clinic.dialyzer').create(dlz_vals) dialyzer=get_model("clinic.dialyzer").browse(dlz_id) dialyzer.validate() return dlz_id def get_dlz(self,visit_id): obj=self.browse(visit_id) patient=obj.patient_id dialyzers=get_model("clinic.dialyzer").search_browse([['patient_id','=',patient.id],['state','=','active']]) if not dialyzers: return {} ### for to new dlz from hd case dlz_id=self.new_dlz(patient.id, obj.department_id.id) dialyzer=get_model("clinic.dialyzer").browse(dlz_id) else: dialyzer=dialyzers[-1] use_time=dialyzer.use_time or 0 max_time=dialyzer.max_use_time or 0 if use_time > max_time: dialyzer.write({ 'state': 'expire', }) # get new dialyzer dlz_id=self.new_dlz(patient.id, obj.department_id.id) dialyzer=get_model("clinic.dialyzer").browse(dlz_id) use_time+=1 vals={ 'dialyzer_id': dialyzer.id, 'membrane_type': dialyzer.membrane_type or '', "dialyzer_type": dialyzer.dialyzer_type, "use_time": use_time, "max_use_time": dialyzer.max_use_time, "description": dialyzer.name or dialyzer.product_id.name or "", } return vals def confirm(self,ids,context={}): obj=self.browse(ids)[0] datenow=time.strftime("%Y-%m-%d") if obj.visit_date > datenow: raise Exception("Can not confirm visit %s: datenow is %s"%(obj.number or "", datenow)) number=obj.number if number=="/" or not number: branch=obj.department_id.branch_id context['branch_id']=branch.id number=self._get_number(context=context) vals={ 'number': number, 'state': 'confirmed', } user_id=get_active_user() staff=get_model("clinic.staff").search_browse([['user_id','=',user_id]]) if staff: vals['nurse_id']=staff[0].id obj.write(vals) hd_case_obj=get_model("clinic.hd.case") vals={ 'patient_id': obj.patient_id.id, 'patient_type_id': obj.patient_id.type_id.id, 'vascular_acc': obj.patient_id.vascular_acc.id, 'nurse_id': obj.nurse_id.id, 'department_id': obj.department_id.id, 'time_start': obj.time_start, 'time_stop': obj.time_stop, 'cycle_id' : obj.cycle_id.id, 'visit_id': obj.id, 'branch_id': obj.branch_id.id, 'lines':[], 'dialyzers': [], 'staffs': [], 'state': 'waiting_treatment', 'date': obj.visit_date, #XXX } random_sickbed=context.get("random_sickbed") if random_sickbed: ids=get_model('clinic.sickbed').search([['department_id','=',obj.department_id.id]]) i=int(random()*len(ids)) vals['sickbed_id']=ids[i] no_gen_dlz=context.get("no_dlz") st=get_model("clinic.setting").browse(1) if not no_gen_dlz and st.find_dlz and not obj.hd_cases: # force to remove dialyzer=self.get_dlz(obj.id) if dialyzer: vals['dialyzers'].append(('create',dialyzer)) else: vals['check_dlz']=False vals['staffs'].append(('create',{ 'staff_id': obj.doctor_id.id, 'type': 'doctor', 'priop': 'personal', })) # use exist hd_case (in case set to draft) hd_case_id=None if obj.hd_cases: hd_case=obj.hd_cases[0] # prevent duplicate staff: del old staff for staff in hd_case.staffs: staff.delete() hd_case.write(vals) hd_case_id=hd_case.id else: hd_case_id=hd_case_obj.create(vals,context=context) if context.get("called"): #XXX call outside return hd_case_id date=vals['time_start'][0:10] cycle=obj.cycle_id branch=obj.branch_id department=obj.department_id dom=[] if date: dom.append(['date','=',date]) if cycle: dom.append(['cycle_id','=',cycle.id]) if branch: dom.append(['branch_id','=',branch.id]) if department: dom.append(['department_id','=',department.id]) item_obj=get_model('clinic.cycle.item') item_ids=item_obj.search(dom) def get_schedule(date): dom=[] dom.append(['date','=',date]) if branch: dom.append(['branch_id','=',branch.id]) if department: dom.append(['department_id','=',department.id]) schedule=None schedules=get_model("clinic.schedule").search_browse(dom) if schedules: schedule=schedules[0] return schedule item_vals={ 'cycle_id': cycle.id, 'branch_id': branch.id, 'department_id': department.id, 'date': date, 'lines': [], } item_id=None if not item_ids: item_id=item_obj.create(item_vals) else: # clear old nurse in cycle item item_id=item_ids[0] item=item_obj.browse(item_id) #FIXME problem 1 staff can have many department user_id=get_active_user() set_active_user(1) # copy nurse from schedule(only draft) item=item_obj.browse(item_id) if not item.lines and item.state=='draft': schedule=get_schedule(date) if schedule: for line in schedule.lines: if line.cycle_id.id==cycle.id: nurse=line.nurse_id dpt=line.department_id item_vals['lines'].append(('create',{ 'nurse_id': nurse.id, 'level_id': nurse.level_id.id, 'department_id': dpt.id, 'categ_id': nurse.categ_id.id, })) item.write(item_vals) # copy nurse from previous cycle item if not item.lines: dom=[ ['branch_id','=',branch.id], ['department_id','=',department.id], ['cycle_id','=',cycle.id], ] for item2 in get_model("clinic.cycle.item").search_browse(dom): lines=[] for line in item2.lines: if not line: continue nr=line.nurse_id if not nr: continue dpt=line.department_id lines.append(('create', { 'nurse_id': nr.id, 'level_id': nr.level_id.id, 'department_id': dpt.id, 'categ_id': nr.categ_id.id, })) if lines: print("copy nurse from %s to %s"%(item2.name, item.name)) item.write({ 'lines': lines, }) break obj.write({ 'cycle_item_id': item_id, }) hd_case=hd_case_obj.browse(hd_case_id) hd_case.write({ 'cycle_item_id': item_id, }) set_active_user(user_id) return { 'next': { 'name': 'clinic_hd_case', 'mode': 'form', 'active_id': hd_case_id, }, 'flash': 'Visit has been confirmed', } def discard(self,ids,context={}): obj=self.browse(ids)[0] obj.write({"state":"cancelled"}) def reopen(self,ids,context={ }): obj=self.browse(ids)[0] obj.write({"state":"draf t"}) def onchange_patient(self,context={}): data=context['data'] patient_id=data['patient_id'] patient=get_model("clinic.patient").browse(patient_id) doctor=patient.doctor_id visits=self.search_browse([['patient_id','=',patient_id]],order="number desc") if visits: visit=visits[0] department_id=None if visit.department_id: department_id=visit.department_id.id elif patient.department_id: department_id=patient.department_id.id branch_id=None if visit.branch_id: branch_id=visit.branch_id.id elif patient.branch_id: branch_id=patient.branch_id.id data['department_id']=department_id data['branch_id']=branch_id else: department=patient.department_id branch=patient.branch_id data['department_id']=department.id data['branch_id']=branch.id data['doctor_id']=doctor.id return data def copy(self,ids,context={}) : obj=self.browse(ids[0]) vals={ 'patient_id': obj.patient_id.id, 'doctor_id': obj.doctor_id.id, 'nurse_id': obj.nurse_id.id, 'department_id': obj.department_id.id, 'branch_id': obj.department_id.branch_id.id, 'cycle_id': obj.cycle_id.id, 'time_start': obj.time_start, 'time_stop': obj.time_stop, 'visit_date': obj.visit_date, } new_id=self.create(vals,context=context) return { 'next':{ 'name': 'clinic_visit', 'mode': 'form', 'active_id': new_id, }, 'flash': 'Visit %s successfully'%(obj.number), } def delete(self,ids,context={}): for obj in self.browse(ids): if obj.state not in ('draft','pending'): raise Exception("Can not delete visit %s because state is not draft!"%obj.number) super().delete(ids,context=context) def get_data(self,context={}): ref_id=context.get("refer_id") if not ref_id: return {} ref_id=int(ref_id) obj=self.browse(ref_id) data={ 'number': obj.number, 'date_visit': obj.date_visit, 'department_name': obj.department_id.name or "", 'patient_name': obj.patient_id.name or "", 'doctor_name': obj.doctor_id.name or "", 'nurse_name': obj.nurse_id.name or "", 'print_date': time.strftime("%d/%m/%Y"), 'cycle_name': obj.cycle_id.name or "", } return data def onchange_cycle(self,context={}): data=context['data'] cycle_id=data['cycle_id'] date=data['visit_date'] if not date: date=data['time_start'][0:10] if cycle_id: cycle=get_model('clinic.cycle').browse(cycle_id) data['time_start']=date+' %s:00'%cycle.time_start data['time_stop']=date+' %s:00'%cycle.time_stop return data def onchange_date(self,context={}): data=context['data'] date=data['visit_date'] time_start=data['time_start'][11:] time_stop=data['time_stop'][11:] data['time_start']='%s %s'%(date,time_start) data['time_stop']='%s %s'%(date,time_stop) return data def onchange_datefrom(self,context={}): data=context['data'] data['visit_date']=data['time_start'][0:10] return data def to_draft(self,ids,context={}): for obj in self.browse(ids): for hd_case in obj.hd_cases: hd_case.to_draft() for line in hd_case.lines: line.delete() for ps in hd_case.staffs: ps.delete() obj.write({ 'state': 'draft', }) def gen_no(self,ids,context={}): obj=self.browse(ids)[0] if obj.number != '/' or obj.state not in ('draft','pending'): return branch=obj.department_id.branch_id context['branch_id']=branch.id number=self._get_number(context=context) obj.write({ 'number': number, }) return { 'next': { 'name': 'clinic_visit', 'mode': 'form', 'active_id': obj.id, }, 'flash': 'Generate number succesfully', } def cancel(self,ids,context={}): obj=self.browse(ids)[0] for hdcase in obj.hd_cases: hdcase.cancelled() obj.write({ 'state': 'cancelled', }) return { 'next': { 'name': 'clinic_visit', 'mode': 'form', 'active_id': obj.id, }, 'flash': 'Visit\'s %s has been cancelled'%obj.patient_id.name } def create(self, vals,context): new_id=super().create(vals,context=context) self.function_store([new_id]) return new_id def write(self,ids,vals,**kw): super().write(ids,vals,**kw) self.function_store(ids) def pending(self,ids,context={}): obj=self.browse(ids)[0] obj.write({ 'state': 'pending', }) def onchange_department(self,context={}): data=context['data'] dpt_id=data['department_id'] if dpt_id: dpt=get_model("clinic.department").browse(dpt_id) data['branch_id']=dpt.branch_id.id return data Visit.register()