import time from calendar import monthrange from netforce.model import Model, fields, get_model from netforce.utils import get_file_path, get_data_path from netforce.database import get_connection from netforce.access import get_active_company from . import utils class MatchingPayment(Model): _name="clinic.matching.payment" _transient=True def _get_all(self,ids,context={}): res={} for obj in self.browse(ids): total_match=0 total_fee=0 total_srv=0 total_epo=0 for line in obj.lines: total_fee+=line.fee or 0 total_srv+=line.srv or 0 total_epo+=line.epo or 0 state=line.state or '' if state=='match': total_match+=1 res[obj.id]={ 'total': len(obj.lines), 'total_match': total_match, 'total_unmatch': len(obj.lines)-total_match, 'total_fee': total_fee, 'total_srv': total_srv, 'total_epo': total_epo, } return res _fields={ 'name': fields.Char("Name"), "date": fields.Date("Month"), "date_from": fields.Date("From", required=True), "date_to": fields.Date("To", required=True), 'file': fields.File("File"), 'patient_type_id': fields.Many2One("clinic.patient.type","Patient Type",required=True), 'pcode': fields.Char("Code",required=True), 'hcode_id': fields.Many2One("clinic.hospital","HCode"), 'lines': fields.One2Many("clinic.matching.payment.line","match_id", "Lines"), 'note': fields.Text("Note"), 'total': fields.Integer("Total",function="_get_all",function_multi=True), 'total_match': fields.Integer("Match",function="_get_all",function_multi=True), 'total_unmatch': fields.Integer("Unmatch",function="_get_all",function_multi=True), 'total_fee': fields.Float("FEE",function="_get_all",function_multi=True), 'total_srv': fields.Float("Service",function="_get_all",function_multi=True), 'total_epo': fields.Float("EPO",function="_get_all",function_multi=True), 'state': fields.Selection([['draft','Draft'],['approved','Approved']],'State'), } def _get_ptype(self,context={}): tids=get_model('clinic.patient.type').search([['default','=',True]]) tid=None if tids: tid=tids[0] return tid def _get_pcode(self,context={}): types=get_model('clinic.patient.type').search_browse([['default','=',True]]) if types: return types[0].code def _get_date_from(self,context={}): year,month=time.strftime("%Y-%m").split("-") return '%s-%s-01'%(year,month) def _get_date_to(self,context={}): year,month,day=time.strftime("%Y-%m-%d").split("-") weekday, total_day=monthrange(int(year), int(month)) return "%s-%s-%s"%(year,month,total_day) def _get_name(self,ids,context={}): return time.strftime("%Y/%m") _defaults={ 'date': lambda *a: time.strftime("%Y-%m-%d"), 'name': _get_name, 'date_from': _get_date_from, 'date_to': _get_date_to, 'patient_type_id': _get_ptype, 'pcode': _get_pcode, 'state': 'draft', } _order="date desc" def get_line(self,ids,context={}): obj=self.browse(ids)[0] if not obj.file: raise Exception("File not found!") fname=obj.file if obj.pcode=='SSO': hcode=obj.hcode_id.code or "" if not hcode: raise Exception("Wrong HCode") try: n,sf=fname.split(".") except Exception as e: print("ERROR: wrong file ", e) if sf not in ('xls','xlsx'): raise Exception("File should be xls or xlsx") fpath=get_file_path(fname) lines=utils.read_excel(fpath,show_datetime=True) elif obj.pcode=='UC': fpath=get_file_path(fname) node='HDBills' lines=utils.read_xml(fpath,node=node) hcode=fname.split("_")[0] else: raise Exception("Type %s is not support"%obj.pcode or "") if not lines: raise Exception("No data to match") return lines def match(self,ids,context={}): obj=self.browse(ids)[0] lines=obj.get_line() print("len.lines ", len(lines)) patient_type=obj.patient_type_id if not patient_type: raise Exception("not found patient type") contact=patient_type.contact_id if not contact: raise Exception("contact not found") matches1={} matches2={} matches3={} matches_uc={} dom=[] dom.append(['date',">=",obj.date_from]) dom.append(['date',"<=",obj.date_to]) dom.append(['partner_id',"=",contact.id]) dom.append(['state','=', 'waiting_payment']) invoices=get_model('account.invoice').search_browse(dom) print("len(invoices)", len(invoices)) for invoice in invoices: pname,hn,card_no='', '', '' if invoice.related_id: hdcase=invoice.related_id patient=hdcase.patient_id pname=patient.name_check or "" card_no=patient.card_no or "" hn=patient.hn_no elif invoice.ref: pname=invoice.ref or '' pname=pname.replace(" ","") # remove space else: pass fee,epo,srv=0, 0, 0 due_amount=0 for inv_line in invoice.lines: amount=inv_line.amount or 0 prod=inv_line.product_id categ_code='' categ=prod.categ_id if categ: categ_code=categ.code if categ_code=='FEE': fee+=amount elif categ_code=='SRV': srv+=amount elif categ_code=='EPO': epo+=amount else: due_amount+=amount vals={ 'invoice_id': invoice.id, 'fee': fee, 'epo': epo, 'srv': srv, } due_amount+=fee+epo+srv date=invoice.date req_vals=[date,due_amount] key1=':'.join([str(v) for v in [hn]+req_vals]) key2=':'.join([str(v) for v in [card_no]+req_vals]) key3=':'.join([str(v) for v in [pname]+req_vals]) # name no space key_uc=':'.join([str(v) for v in [hn,date,due_amount]]) # becareful!!! if not matches1.get(key1): matches1[key1]=vals if not matches2.get(key2): matches2[key2]=vals if not matches3.get(key3): matches3[key3]=vals if not matches_uc.get(key_uc): matches_uc[key_uc]=vals nf_hcode='' if obj.hcode_id: nf_hcode=obj.hcode_id.code records=[] if obj.pcode=='SSO': for line in lines: hcode=line.get('hcode18') if not hcode: hcode='0' hcode=int(hcode) hcode=str(hcode) if nf_hcode==hcode: epo=line.get('epoadm29') or 0 fee=line.get('amount23') or 0 srv=line.get('allow37') or 0 date_treatment=line.get("dttran") name=line.get("name14") name_nospace=name.replace(" ","") card_no=int(line.get('pid')) date=date_treatment[0:10] time=date_treatment[11:] #XXX if not time: print("wrong format") continue due_amount=fee+epo+srv req_vals=[date,due_amount] hn=line.get('hn') hn=''.join([x for x in hn if x.isdigit()]) key1=':'.join([str(v) for v in [hn]+req_vals]) key2=':'.join([str(v) for v in [card_no]+req_vals]) key3=':'.join([str(v) for v in [name_nospace]+req_vals]) record={ 'date':date, 'patient_name': name, 'pid': card_no, 'hn': hn, 'fee': fee, 'srv': srv, 'epo': epo, 'invoice_id': None, 'state': 'unmatch', } #if hn=='100794': #import pdb; pdb.set_trace() if matches1.get(key1): print("found ", key1) record.update({ 'invoice_id': matches1[key1]['invoice_id'], 'state': 'match', }) elif matches2.get(key2): print("found ", key2) record.update({ 'invoice_id': matches2[key2]['invoice_id'], 'state': 'match', }) elif matches3.get(key3): print("found ", key3) record.update({ 'invoice_id': matches3[key3]['invoice_id'], 'state': 'match', }) else: pass ## unmatch records.append(record) elif obj.pcode=='UC': records=[] for line in lines: #{'amount': '1500.0000', #'cstat': None, #'dttran': '2014-09-27T10:00:00', #'epostat': 'E', #'hdflag': 'COU', #'hdrate': '1500.0000', #'hn': '98511252', #'hreg': 'NHSO1', #'invno': '437941480', #'paid': '0.0000', #'paychk': '1', #'reimbpay': '0.0000', #'rid': '2190', #'station': '01'} date,time=(line['dttran'] or "").split("T") fee=0 if line.get('amount'): fee=float(line['amount']) hn=line['hn'] hn=hn.replace(" ", "") key_uc='' if date and time: key_uc='%s:%s:%s'%(line['hn'],date,fee,) pname='' pid='' for pt in get_model("clinic.patient").search_browse([['hn_no','=',hn]]): pname=pt.name or "" pid=pt.card_no or "" record={ 'date':date, 'name': pname, 'pid': pid, 'hn': hn, 'fee': fee, 'srv': 0, 'epo': 0, 'invoice_id': None, 'state': 'unmatch', } if matches_uc.get(key_uc): record.update({ 'invoice_id': matches1[key_uc]['invoice_id'], 'state': 'match', }) else: pass #print("not found") records.append(record) if obj.hcode_id and not records: raise Exception("Nothing to match! for %s"%(obj.hcode_id.name or "")) if not records: raise Exception("Nothing to match! Please verify your file and your filter condition.") return records 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) data['name']='%s/%s'%(year,month) return data def onchange_ptype(self,context={}): data=context['data'] type_id=data['patient_type_id'] if type_id: t=get_model('clinic.patient.type').browse(type_id) data['pcode']=t.code or "" return data def do_import(self,ids,context={}): st=get_model("clinic.setting").browse(1) if not st.import_account_id: raise Exception("Import account not found (Ratchawat Setting -> Accounting)") obj=self.browse(ids)[0] partner=obj.patient_type_id.contact_id company_id=get_active_company() vals={ "partner_id": partner.id, "company_id": company_id, "type": "in", "pay_type": "invoice", 'date': time.strftime("%Y-%m-%d"), "account_id": st.import_account_id.id, 'invoice_lines': [], 'rd_cust': True, #XXX } for line in obj.lines: inv=line.invoice_id if inv: vals['invoice_lines'].append(('create',{ 'invoice_id': inv.id, 'amount': inv.amount_due or 0, })) if inv.related_id: hdcase=inv.related_id if hdcase: hdcase.write({ 'state': 'paid', }) if not vals['invoice_lines']: raise Exception("Nothing to import") payment_id=get_model("account.payment").create(vals,context={"type":"in"}) return { 'next': { 'name': 'payment', 'mode': 'form', 'active_id': payment_id, }, 'flash': 'Create Payment successfully', } def do_match(self,ids,context={}): obj=self.browse(ids)[0] records=obj.match() lines=[] if obj.pcode=='SSO': for record in records: state=record['state'] or '' vals={ 'date': record['date'], 'hn': record['hn'], 'pid': record['pid'], 'name': record['patient_name'], 'epo': record['epo'], 'srv': record['srv'], 'fee': record['fee'], 'invoice_id': record['invoice_id'], 'state': state, } lines.append(('create', vals)) elif obj.pcode=='UC': for record in records: state=record['state'] or '' vals={ 'date': record['date'], 'hn': record['hn'], 'pid': record['pid'], 'name': record['name'], 'fee': record['fee_amt'], 'invoice_id': record['invoice_id'], 'state': state, } lines.append(('create', vals)) for line in obj.lines: line.delete() obj.write({ 'lines': lines, }) def update_id(self,ids,context={}): obj=self.browse(ids)[0] lines=obj.get_line() pts={} for line in lines: pid=line.get("pid") name=line.get("name14") hn=line.get("hn") if not pts.get(name): pts[name]=pid for pt in get_model('clinic.patient').search_browse([]): pid=pts.get(pt.name) if pid: if pt.card_no: pid=''.join([str(x) for x in pt.card_no if x.isnumeric()]) print(pt.name, 'pid ', pid) else: pid=int(pid) print("pid ", pid) pt.write({ 'card_no': pid, }) print("Done!") def get_report_data(self,ids,context={}): lines=[] if ids: obj=self.browse(ids)[0] lines=obj.match() data={ 'lines': lines, } return data def match_old(self,ids,context={}): obj=self.browse(ids)[0] lines=obj.get_line() db=get_connection() db.execute("truncate m2m_clinic_hd_case_expense_clinic_matching_payment;") matches1={} matches2={} matches3={} if obj.pcode=='SSO': for line in lines: hcode=line.get('hcode18') if not hcode: hcode='0' hcode=int(hcode) hcode=str(hcode) if obj.hcode==hcode: lsrv_amt=line.get('epoadm29') or 0 lfee_amt=line.get('amount23') or 0 lmdc_amt=line.get('allow37') or 0 dttran=line.get("dttran") name=line.get("name14") pid=line.get('pid') date=dttran[0:10] time=dttran[11:] #XXX if not time: print("wrong format") continue hn=line.get('hn') hn=''.join([x for x in hn if x.isdigit()]) key1='%s:%s:%s:%s:%s'%( hn, date, lfee_amt, lsrv_amt, lmdc_amt, ) key2='%s:%s:%s:%s:%s'%( pid, date, lfee_amt, lsrv_amt, lmdc_amt, ) key3='%s:%s:%s:%s:%s'%( name, date, lfee_amt, lsrv_amt, lmdc_amt, ) vals={ 'pid': pid, 'name': name, 'date': date, 'fee_amt': lfee_amt, 'service_amt': lsrv_amt, 'epo_amt': lmdc_amt, } if not matches1.get(key1): matches1[key1]=vals if not matches2.get(key2): matches2[key2]=vals if not matches3.get(key3): matches2[key2]=vals elif obj.pcode=='UC': for line in lines: #{'amount': '1500.0000', #'cstat': None, #'dttran': '2014-09-27T10:00:00', #'epostat': 'E', #'hdflag': 'COU', #'hdrate': '1500.0000', #'hn': '98511252', #'hreg': 'NHSO1', #'invno': '437941480', #'paid': '0.0000', #'paychk': '1', #'reimbpay': '0.0000', #'rid': '2190', #'station': '01'} date,time=(line['dttran'] or "").split("T") amt=line['amount'] or "0" amt=float(amt) if date and time: key1='%s-%s-%s'%( line['hn'], date, amt, ) if not matches1.get(key1): matches1[key1]={ 'invno': line['invno'], } note="" exp_ids=[] dom=[] dom.append(['date',">=",obj.date_from]) dom.append(['date',"<=",obj.date_to]) dom.append(['patient_id.type_id',"=",obj.patient_type_id.id]) dom.append(['state','!=', 'completed']) for exp in get_model('clinic.hd.case.expense').search_browse(dom): exp_ids.append(exp.id) pt=exp.patient_id if obj.pcode=='UC': hdcase=exp.hd_case_id date=hdcase.date fee_amt=0 for line in hdcase.lines: categ=line.product_categ_id if categ.code=='FEE': fee_amt+=line.amount or 0 key='%s-%s-%s'%(pt.hn_no,date,amt) found=matches1.get(key) if found: exp.write({ 'state': 'match', }) else: note+="not found %s\n"%key elif obj.pcode=='SSO': key1='%s:%s:%s:%s:%s'%( pt.hn_no, exp.date, exp.fee_amt and exp.fee_amt or 0, exp.srv_amt and exp.srv_amt or 0, exp.mdc_amt and exp.mdc_amt or 0, ) key2='%s:%s:%s:%s:%s'%( pt.name or "", exp.date, exp.fee_amt and exp.fee_amt or 0, exp.srv_amt and exp.srv_amt or 0, exp.mdc_amt and exp.mdc_amt or 0, ) found=matches1.get(key1) or matches2.get(key2) if found: hdcase=exp.hd_case_id if hdcase: for inv in hdcase.invoices: pass #if #pass exp.write({ 'state': 'match', }) else: note+="not found %s, %s\n"%(key1,key2) obj.write({ 'expenes': [('add',exp_ids)], 'note': note, }) print("Done!") flash='Succesfully' if not exp_ids: flash="No match" return { 'next': { 'name': 'clinic_matching_payment', 'mode': 'form', 'active_id': obj.id, }, 'flash': flash, } def onchange_invoice(self,context={}): data=context['data'] path=context['path'] line=get_data_path(data,path,parent=True) if line.get("invoice_id"): line['state']='match' else: line['state']='' return data def clear_line(self,ids,context={}): obj=self.browse(ids)[0] line_ids=[line.id for line in obj.lines] get_model("clinic.matching.payment.line").delete(line_ids) print("Cleared %s"%(line_ids)) MatchingPayment.register()