import time from calendar import monthrange from netforce.model import Model, fields, get_model from netforce.utils import get_file_path from . import utils class PaymentMatching(Model): _name="clinic.payment.matching" _string="Payment Matching" _transient=True _fields={ 'name': fields.Char("Name"), "date": fields.Date("Month"), "date_from": fields.Date("From", required=True), "date_to": fields.Date("To", required=True), 'file_id': fields.Many2One('document','File',domain=[['categ_id.code','=','MP']]), "period_id": fields.Many2One("clinic.period.line","Period"), 'department_id': fields.Many2One("clinic.department","Department"), 'branch_id': fields.Many2One("clinic.branch","Branch"), "inv_state": fields.Selection([("draft","Draft"),("waiting_approval","Waiting Approval"),("waiting_payment","Waiting Payment"),("paid","Paid"),("voided","Voided")],"Status"), "view_type": fields.Selection([("invoice","Invoice"),("matching","Matching")],"View Type"), '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"), 'inv_ids': fields.Text("Invoice ids"), } def _get_date_from(self,context={}): year,month,day=time.strftime("%Y-%m-%d").split("-") return '%s-%s-%s'%(year,month,day) 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,day) def default_get(self,field_names=None,context={},**kw): defaults=context.get("defaults",{}) date_from=defaults.get("date_from", self._get_date_from()) date_to=defaults.get("date_to", self._get_date_to()) yearnow=date_from.split("-")[0] for period in get_model('clinic.period').search_browse([['name','=',yearnow]]): for line in period.lines: if line.state=='open': period_id=line.id date_from=line.date_start date_to=line.date_stop break patient_type_id=None pcode='SSO' for ptype in get_model('clinic.patient.type').search_read([['default','=',True]],['code']): pcode=ptype['code'] patient_type_id=ptype['id'] hdcode_id=None for hid in get_model("clinic.hospital").search([]): hdcode_id=hid break res={ 'period_id': period_id, 'date': time.strftime("%Y-%m-%d"), 'date_from': date_from, 'date_to': date_to, #'inv_state': 'waiting_payment', 'view_type': 'invoice', 'patient_type_id': patient_type_id, 'pcode': pcode, 'hcode_id': hdcode_id, } return res def onchange_period(self,context={}): data=context['data'] period_id=data['period_id'] period=get_model('clinic.period.line').browse(period_id) data['date_from']=period.date_start data['date_to']=period.date_stop 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 get_line(self,ids,context={}): obj=self.browse(ids)[0] if not obj.file_id.file: raise Exception("File not found!") fname=obj.file_id.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 get_report_data(self,ids,context={}): defaults=self.default_get(context=context) print('defaults ', defaults) date_from=defaults.get('date_from') date_to=defaults.get('date_to') branch_id=None department_id=None inv_state=defaults.get('inv_state') view_type=defaults.get('view_type') pcode='' obj=None if ids: obj=self.browse(ids)[0] date_from=obj.date_from date_to=obj.date_to branch_id=obj.branch_id.id department_id=obj.department_id.id inv_state=obj.inv_state view_type=obj.view_type pcode=obj.pcode lines=[] invoices=[] total_invoice=0 total_match_invoice=0 total_epo=0 total_srv=0 total_fee=0 total_amount=0 def get_invoices(): invoices=[] dom=[ ['date','>=',date_from], ['date','<=',date_to], ] if inv_state: dom.append(['state','=',inv_state]) if branch_id and not department_id: dom.append(['department_id.branch_id','=',branch_id]) elif department_id: dom.append(['department_id','=',department_id]) print('dom ', dom) field_names=['date','number','amount_total','amount_due','patient_id','state'] for inv in get_model('account.invoice').search_read(dom,field_names): vals={ 'id': inv['id'], 'patient_id': None, 'patient_name': '', 'patient_hn': '', } for field_name in field_names: if field_name=='patient_id' and inv['patient_id']: patient=get_model('clinic.patient').browse(inv['patient_id'][0]) vals['patient_id']=patient.id vals['patient_name']=patient.name vals['patient_nospace_name']=patient.name_check vals['patient_cid']=patient.card_no vals['patient_hn']=patient.hn_no else: vals[field_name]=inv[field_name] vals[field_name]=inv[field_name] invoices.append(vals) return invoices inv_match_ids=[] if view_type=='invoice': lines=get_invoices() total_invoice=len(lines) else: if obj and obj.pcode=='SSO': invoices=get_invoices() total_invoice=len(invoices) rlines=obj.get_line() no=1 for rline in rlines: date_treatment=rline.get("dttran") date=date_treatment[0:10] time=date_treatment[11:] if not time: continue epo=rline.get('epoadm29') or 0 fee=rline.get('amount23') or 0 srv=rline.get('allow37') or 0 name=rline.get("name14") name_nospace=name.replace(" ","") pid=rline.get('pid') hn=rline.get('hn') hn=''.join([x for x in hn if x.isdigit()]) total_fee+=fee total_epo+=epo total_srv+=srv amount=fee+epo+srv total_amount+=amount line_vals={ 'no': no, 'date':date, 'patient_name': name, 'pid': pid, 'hn': hn, 'fee': fee, 'srv': srv, 'epo': epo, 'amount': amount, } for item_amt in ['fee','srv','epo']: for inv in invoices: if inv['patient_id']: # check card no first then HN finally patient name if pid==inv['patient_cid'] or hn==inv['patient_hn'] or name_nospace==inv['patient_nospace_name']: #inv_amt=inv['amount_due'] inv_amt=inv['amount_total'] inv_date=inv['date'] if inv_date==date and inv_amt==line_vals[item_amt]: line_vals['inv_%s'%(item_amt)]=inv['number'] line_vals['inv_%s_id'%(item_amt)]=inv['id'] line_vals['inv_%s_state'%(item_amt)]=inv['state'] if inv['state']=='waiting_payment': inv_match_ids.append(inv['id']) total_match_invoice+=1 break lines.append(line_vals) no+=1 elif obj and obj.pcode=='UC': invoices=get_invoices() total_invoice=len(invoices) rlines=obj.get_line() no=1 for rline in rlines: #{'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=(rline['dttran'] or "").split("T") fee=0 if rline.get('amount'): fee=float(rline['amount']) total_fee+=fee hn=rline['hn'] hn=hn.replace(" ", "") pname='' pname_check='' pid='' for pt in get_model("clinic.patient").search_browse([['hn_no','=',hn]]): pname=pt.name or "" pname_check=pt.name_check or "" pid=pt.card_no or "" vals={ 'date':date, 'patient_name': pname, 'pid': pid, 'hn': hn, 'fee': fee, 'srv': 0, 'epo': 0, 'inv_id': None, 'inv_number': '', 'inv_state': '', 'no': no, } for inv in invoices: if inv['patient_id']: if pid==inv['patient_cid'] or hn==inv['patient_hn'] or pname_check==inv['patient_nospace_name']: if date==inv['date'] and fee==inv['amount_due']: vals['inv_id']=inv['id'] vals['inv_number']=inv['number'] vals['inv_state']=inv['state'] if inv['state']=='waiting_payment': inv_match_ids.append(inv['id']) total_match_invoice+=1 break lines.append(vals) no+=1 pc=0 if total_invoice: pc=(total_match_invoice/total_invoice)*100 #if inv_match_ids and obj: #obj.write({ #'inv_ids': str(inv_match_ids), #}) data={ 'lines': lines, 'date_from': date_from, 'date_to': date_to, 'total_item': len(lines), 'total_fee': total_fee, 'total_epo': total_epo, 'total_srv': total_srv, 'total_invoice': total_invoice, 'total_match_invoice': total_match_invoice, 'pc_match': pc, 'pc_unmatch': 100-pc, 'total_unmatch_invoice': total_invoice-total_match_invoice, 'total_amount': total_amount, 'view_type': view_type, 'pcode': pcode, } return data PaymentMatching.register()