import time from calendar import monthrange from datetime import datetime, timedelta from netforce.model import Model, fields, get_model from netforce.access import get_active_company from . import utils DRT=0 HD_STATE={ "draft":"Draft", 'waiting_treatment':'Waiting Treatment', "in_progress":"In Progress", "completed":"Finish Treatment", 'paid':'Paid', "waiting_payment":"Waiting Payment", "discountinued":"Discountinued", "cancelled":"Cancelled" } DAYS={ 'mon': 0, 'tue': 1, 'wed': 2, 'thu': 3, 'fri': 4, 'sat': 5, 'sun': 6, } class VisitBoard(Model): _name="clinic.visit.board" _string="Visit Board" _transient=True _name_field="date" _fields={ "date": fields.Date("Month", required=False), "date_from": fields.Date("From", required=True), "date_to": fields.Date("To", required=True), 'patient_id': fields.Many2One("clinic.patient","Patient",domain=[['state','=','admit']]), 'cycle_id': fields.Many2One("clinic.cycle","Cycle"), 'doctor_id': fields.Many2One("clinic.staff","Doctor",domain=[["type","=","doctor"]]), 'department_id': fields.Many2One("clinic.department","Department"), 'branch_id': fields.Many2One("clinic.branch","Branch"), "state": fields.Selection([["draft","Draft"],['pending','Pending'],["confirmed","Confirmed"],["cancelled","Cancelled"]],"Status",required=True), } def default_get(self,field_names=None,context={},**kw): defaults=context.get("defaults",{}) date=defaults.get('date',time.strftime("%Y-%m-%d")) date_from=defaults.get("date_from",time.strftime("%Y-%m-%d")) date_to=defaults.get("date_to") if not date_to: date_to=(datetime.now()+timedelta(days=DRT)).strftime("%Y-%m-%d") branch_id=defaults.get("branch_id") department_id=defaults.get("department_id") res=get_model('select.company').get_select() if res: if not branch_id: branch_id=res['branch_id'] if not department_id: if res.get('department_ids'): department_id=res['department_ids'][0] else: department_id=res['department_id'] res={ 'date': date, 'date_from': date_from, 'date_to': date_to, 'branch_id': branch_id, 'department_id': department_id, 'state': 'pending', } print('clinic.visit.board.defaults ', defaults) return res def get_report_data(self,ids,context={}): company_id=get_active_company() company=get_model("company").browse(company_id) date_from=datetime.now().strftime("%Y-%m-%d") date_to=(datetime.now()+timedelta(days=DRT)).strftime("%Y-%m-%d") patient_id=None cycle_id=None doctor_id=None defaults=self.default_get(context=context) department_id=defaults.get("department_id",None) branch_id=defaults.get("branch_id",None) state=defaults.get("state",'pending') if ids: obj=self.browse(ids)[0] date_from=obj.date_from date_to=obj.date_to patient_id=obj.patient_id.id cycle_id=obj.cycle_id.id doctor_id=obj.doctor_id.id department_id=obj.department_id.id branch_id=obj.branch_id.id state=obj.state # auto generate visit day to day def auto_gen_visit(dom=[]): dom.append(['dispose','=',False]) def daterange(start_date, end_date): for n in range(int ((end_date - start_date).days)): yield start_date + timedelta(n) def convert_date(date_txt): try: if not date_txt: raise Exception("Date Empty") return datetime.strptime(date_txt,"%Y-%m-%d") except: raise Exception("Wrong Format Date") # check day of week of this day for date in daterange(convert_date(date_from),convert_date(date_to)+timedelta(days=1)): weekday=date.weekday() date_txt=date.strftime("%Y-%m-%d") datenow=time.strftime("%Y-%m-%d") if date_txt < datenow: print("continue ", date_txt, datenow) continue for pt in get_model("clinic.patient").search_browse(dom): for pc in pt.cycles: w=DAYS.get(pc.day,0) #default monday cycle=pc.cycle_id if not cycle: continue #raise Exception('cycle setting for %s is not correct!'%(pt.name)) department=pc.department_id if weekday==w: dom2=[ ['visit_date','=',date_txt], ['patient_id','=',pt.id], #['cycle_id','=',cycle.id], #XXX ['department_id','=',department.id], ] res=get_model("clinic.visit").search(dom2) # create visit auto if not res: vals={ 'patient_id': pt.id, 'department_id': department.id, 'cycle_id': cycle.id, 'doctor_id': pt.doctor_id.id, 'branch_id': department.branch_id.id, 'time_start': '%s %s:00'%(date_txt,cycle.time_start), 'time_stop': '%s %s:00'%(date_txt,cycle.time_stop), 'visit_date': date_txt, 'state': 'pending', } visit_id=get_model("clinic.visit").create(vals) print('create new visit %s for %s'%(visit_id,pt.name)) time_start='%s 00:00:00'%(date_from) time_stop='%s 23:59:59'%(date_to) dom=[] dom.append(['time_start','>=','%s'%time_start]) dom.append(['time_stop','<=','%s'%time_stop]) if patient_id: dom.append(['patient_id','=',patient_id]) if cycle_id: dom.append(['cycle_id','=',cycle_id]) if doctor_id: dom.append(['doctor_id','=',doctor_id]) if department_id: dom.append(['department_id','=',department_id]) if branch_id: dom.append(['branch_id','=',branch_id]) #gen visit if department_id: auto_gen_visit(dom=[['department_id','=',department_id]]) elif branch_id: auto_gen_visit(dom=[['branch_id','=',branch_id]]) lines=[] empty_line={ 'no': '', 'number': '', 'visit_id': None, 'visit_state': '', 'cycle_name': '', 'cycle_color': '', 'department_id': None, 'department_name': None, 'branch_id': None, 'branch_name': None, 'patient_id': None, 'patient_name': '', 'patient_type': '', 'patient_type_id': None, 'doctor_name': '', 'doctor_id': None, 'hd_case_number': '', 'hd_case_id': None, 'success_color': '', 'date':'', 'title': True, 'footer': False, 'details':'', 'hd_case_state': '', 'hn': '', } patient_types={t['id']:t['name'] for t in get_model("clinic.patient.type").search_read([[]],['name'])} cycle_names={t['id']:t['name'] for t in get_model("clinic.cycle").search_read([[]],['name'])} brch_names={t['id']:t['name'] for t in get_model("clinic.branch").search_read([[]],['name'])} dpt_names={t['id']:t['name'] for t in get_model("clinic.department").search_read([[]],['name'])} total_wait=0 total_done=0 total_cancel=0 types={} cycles={} no=1 dpt={} brch={} if state=='pending': dom+=[['state', 'in',[state,'confirmed']]] else: dom+=[['state', 'in',[state]]] print('dom ', dom) for visit in get_model("clinic.visit").search_browse(dom): if visit.state in ('draft','pending'): total_wait+=1 elif visit.state in ('confirmed'): total_done+=1 else: total_cancel+=1 hd_case_id=None hd_case_number='' hd_case_state='' visit_color='' sickbed_name='N/A' sickbed_id=None found_hdcase=False is_paid=False is_waiting=False if visit.hd_cases: hd_case=visit.hd_cases[0] if hd_case.state in ('waiting_payment', 'paid'): found_hdcase=True if hd_case.state=='waiting_payment': is_waiting=True elif hd_case.state=='paid': is_paid=True sickbed_name=hd_case.sickbed_id.name or "N/A" sickbed_id=hd_case.sickbed_id.id hd_case_id=hd_case.id, if hd_case.number=='/': hd_case_number='Waiting' else: hd_case_number=hd_case.number hd_case_state=hd_case.state if hd_case_state=='completed': #visit_color='#99ff99' visit_color='' elif hd_case_state=='in_progress': #visit_color='#f9e37d' visit_color='' elif hd_case_state=='cancelled': visit_color='#dbdbdb', hd_case_number="Cancelled" number=visit.number if number=='/': number='Waiting' cycle=visit.cycle_id patient=visit.patient_id if not patient.active: print('skip not active ', patient.name) continue branch=visit.branch_id department=visit.department_id if not branch: branch=department.branch_id hn_name=patient.hn_no or '-' visit_date=visit.visit_date if visit.state=='cancelled': visit_color='#dbdbdb', if visit.number=='/': number='Cancelled' else: number+='Cancelled' line={ 'number': number, 'hn_name': hn_name, 'visit_id': visit.id, 'sickbed_name': sickbed_name, 'sickbed_id': sickbed_id, 'cycle_name': cycle.name, 'cycle_color': cycle.color, 'department_id': department.id, 'department_name': department.name or '', 'branch_id': branch and branch.id or None, 'branch_name': branch and branch.name or '', 'patient_name': patient.name, 'patient_id': patient.id, 'patient_type': patient.type_id.name or "", 'patient_type_id': patient.type_id.id or None, 'doctor_name': visit.doctor_id.name, 'doctor_id': visit.doctor_id.id, 'hd_case_number': (hd_case_number or '').replace('HDC/',''), 'hd_case_state': hd_case_state, 'hd_case_state_txt':HD_STATE.get(hd_case_state,''), 'hd_case_id': hd_case_id, 'visit_color': visit_color, 'date': visit_date, 'title': False, 'footer': False, 'details':'', 'details1':'', 'details2':'', 'details3':'', 'details4':'', 'details5':'', 'no': no, 'note': visit.note, 'cost': 0, 'is_paid': is_paid, 'is_waiting': is_waiting, } if found_hdcase: line['cost']=hd_case.total_amount or 0 lines.append(line) no+=1 if not types.get(visit_date): ptype={} [ptype.setdefault(t,0) for t in patient_types.keys()] types[visit_date]=ptype types[visit_date][patient.type_id.id]+=1 if not cycles.get(visit_date): cycle_name={} [cycle_name.setdefault(cid,0) for cid in cycle_names.keys()] cycles[visit_date]=cycle_name cycles[visit_date][cycle.id]+=1 if not brch.get(visit_date): brch_name={} [brch_name.setdefault(cid,0) for cid in brch_names.keys()] brch[visit_date]=brch_name brch[visit_date][branch.id]+=1 if not dpt.get(visit_date): dpt_name={} [dpt_name.setdefault(cid,0) for cid in dpt_names.keys()] dpt[visit_date]=dpt_name dpt[visit_date][department.id]+=1 dates=[] index=0 total_qty=0 count=0 for line in lines: date=line['date'] if not date: continue if date not in dates: count=0 total_qty=0 line=empty_line.copy() for qty in types[date].values(): total_qty+=qty line['cycle_name']=utils.date2thai(date,format='%(Td)s %(d)s %(Tm)s',lang="th_TH2"), lines.insert(index,line) dates.append(date) if count==total_qty and not patient_id: index+=1 # footer line=empty_line.copy() patient_str='%s'%', '.join('%s: %s'%(patient_types[k],v) for k,v in types[date].items()) cycle_str='%s'%', '.join('%s: %s'%(cycle_names[k],v) for k,v in cycles[date].items()) brch_str='%s'%', '.join('%s: %s'%(brch_names[k],v) for k,v in brch[date].items()) dpt_str='%s'%', '.join('%s: %s'%(dpt_names[k],v) for k,v in dpt[date].items()) summary_str='%s'%', '.join(['รับไว้: %s'%total_wait,'จำหน่ายแล้ว: %s'%total_done, 'ยกเลิก: %s'%total_cancel]) line['details']='ทั้งหมด %s: %s'%(total_qty,', '.join([summary_str,cycle_str,patient_str])) line['details1']=brch_str line['details2']=summary_str line['details3']=cycle_str line['details4']=patient_str line['details5']=dpt_str line['footer']=True line['title']=False lines.insert(index,line) count+=1 index+=1 has_duration=False if date_from != date_to: has_duration=True data={ 'lines': lines, 'date': utils.date2thai(date_from,format='ประจำวัน%(Td)s ที่ %(d)s %(Tm)s %(BY)s'), 'company_name': company.name, 'company_parent_name': company.parent_id.name, 'has_duration': has_duration, 'date_from': utils.date2thai(date_from,format='%(d)s %(Tm)s %(By)s',lang="th_TH2"), 'date_to': utils.date2thai(date_to,format='%(d)s %(Tm)s %(By)s',lang="th_TH2"), } return data def onchange_date(self,context={}): data=context['data'] date=data['date'] year,month,day=date.split("-") weekday, total_day=monthrange(int(year), int(month)) data['date_from']="%s-%s-01"%(year,month) data['date_to']="%s-%s-%s"%(year,month,total_day) return data def onchange_datefrom(self,context={}): data=context['data'] data['date_to']=data['date_from'] return data def onchange_branch(self,context={}): data=context['data'] data['department_id']=None return data def confirm(self,ids,context={}): obj=self.browse(ids)[0] return { 'next': { 'refer_id': obj.id, 'name': 'clinic_popup_visit_confirm', } } VisitBoard.register()