diff --git a/netforce_clinic/models/__init__.py b/netforce_clinic/models/__init__.py index 9e9cc5f..0bfacc5 100644 --- a/netforce_clinic/models/__init__.py +++ b/netforce_clinic/models/__init__.py @@ -114,7 +114,7 @@ from . import make_apt_line from . import matching_payment from . import matching_payment_line from . import matching_payment_popup -from . import invoice_payment +from . import clinic_invoice_payment from . import invoice_payment_line from . import matching_hdcase from . import matching_hdcase_line @@ -143,3 +143,4 @@ from . import print_labor_cost_line from . import conv_bal from . import conv_sale_invoice from . import account_move_line +from . import invoice_payment diff --git a/netforce_clinic/models/account_move_line.py b/netforce_clinic/models/account_move_line.py index 96c24a6..3e52aaf 100644 --- a/netforce_clinic/models/account_move_line.py +++ b/netforce_clinic/models/account_move_line.py @@ -1,7 +1,29 @@ -from netforce.model import Model +from netforce.model import Model, get_model class AccountMoveLine(Model): _inherit="account.move.line" + def reconcile(self,ids,context={}): + print("MoveLine.reconcile",ids) + rec_id=get_model("account.reconcile").create({}) + all_ids=ids[:] + for line in self.browse(ids): + rec=line.reconcile_id + if not rec: + continue + for rline in rec.lines: + all_ids.append(rline.id) + all_ids=list(set(all_ids)) + acc_id=None + # skip to check account + hdcase_reconcile=context.get("hdcase_reconcile") + if not hdcase_reconcile: + for obj in self.browse(all_ids): + if not acc_id: + acc_id=obj.account_id.id + else: + if obj.account_id.id!=acc_id: + raise Exception("Can only reconcile transactions of same account") + self.write(all_ids,{"reconcile_id":rec_id}) AccountMoveLine.register() diff --git a/netforce_clinic/models/account_payment.py b/netforce_clinic/models/account_payment.py index 6fd9236..362fe40 100644 --- a/netforce_clinic/models/account_payment.py +++ b/netforce_clinic/models/account_payment.py @@ -222,7 +222,6 @@ class AccountPayment(Model): else: inv_line_id=None if inv_line_id: - #customize reconcile_ids.append([pay_line_id,inv_line_id]) for invline in inv.lines: tax=invline.tax_id @@ -492,17 +491,17 @@ class AccountPayment(Model): get_model("account.move.line").create(line_vals) get_model("account.move").post([move_id]) obj.write({"move_id":move_id,"state":"posted"}) - #Cutomize for rec_lines in reconcile_ids: - get_model("account.move.line").reconcile(rec_lines) + get_model("account.move.line").reconcile(rec_lines,context=context) obj.create_prepay_invoice() def post(self,ids,context={}): obj=self.browse(ids)[0] res=None - if obj.hdcase_reconcile: - obj.clinic_post() - if obj.rd_cust: + hdcase_reconcile=context.get('hdcase_reconcile') + if hdcase_reconcile and obj.pay_type=="invoice": + obj.clinic_post(context=context) + elif obj.rd_cust: res={} print("RD Customize") desc="Recieved %s"%obj.partner_id.name diff --git a/netforce_clinic/models/clinic_invoice_payment.py b/netforce_clinic/models/clinic_invoice_payment.py new file mode 100644 index 0000000..6442e07 --- /dev/null +++ b/netforce_clinic/models/clinic_invoice_payment.py @@ -0,0 +1,196 @@ +import time + +from netforce.model import Model, fields, get_model +from netforce.utils import get_data_path +from netforce.access import get_active_company, get_active_user + +class InvoicePayment(Model): + _name="clinic.invoice.payment" + _string="Payment Invoice" + + def _get_all(self,ids,context={}): + res={} + for obj in self.browse(ids): + total=0 + total_fee=0 + total_srv=0 + total_epo=0 + for line in obj.lines: + matching=line.matching_id + for mline in matching.lines: + if mline.state!='match': + continue + fee=mline.fee or 0 + total+=fee + total_fee+=fee + srv=mline.srv or 0 + total+=srv + total_srv+=srv + epo=mline.epo or 0 + total+=epo + total_epo+=epo + res[obj.id]={ + 'total': total, + 'total_epo': total_epo, + 'total_fee': total_fee, + 'total_srv': total_srv, + } + return res + + _fields={ + 'name': fields.Char("Name",required=True), + 'lines': fields.One2Many("clinic.invoice.payment.line","invoice_payment_id", "Lines"), + 'total': fields.Float("Total",function="_get_all",function_multi=True), + 'total_fee': fields.Float("FEE",function="_get_all",function_multi=True), + 'total_epo': fields.Float("EPO",function="_get_all",function_multi=True), + 'total_srv': fields.Float("Service",function="_get_all",function_multi=True), + 'state': fields.Selection([['draft','Draft'],['waiting_approve','Waiting Approval'],['approved','Approved'],['done','Done']],'State'), + 'date': fields.Date("Date"), + 'user_id': fields.Many2One("base.user","Approver"), + 'partner_id': fields.Many2One("partner","Contact"), + 'payment_id': fields.Many2One("account.payment","Payment"), + } + + _defaults={ + 'state': 'draft', + 'date': lambda *a: time.strftime("%Y-%m-%d"), + } + + def send_to_payment(self,ids,context={}): + count=0 + for obj in self.browse(ids): + res=obj.make_payment() + count+=1 + obj.write({ + 'state': 'done', + }) + # support list view + if count<=1: + return res + + def approve(self,ids,context={}): + for obj in self.browse(ids): + obj.write({ + 'state': 'approved', + 'user_id': get_active_user(), + }) + + def make_payment(self,ids,context={}): + obj=self.browse(ids)[0] + invoice_lines=[] + for line in obj.lines: + for mline in line.matching_id.lines: + invoice=mline.invoice_id + state=mline.state + if invoice and state=='match': + vals={ + 'invoice_id': invoice.id, + 'amount': invoice.amount_due or 0, + } + invoice_lines.append(('create', vals)) + if not invoice_lines: + raise Exception("Nothing to approve") + 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.partner_id + company_id=get_active_company() + datenow=obj.date or time.strftime("%Y-%m-%d") + memo='Payment; %s'%(partner.name) + vals={ + "partner_id": partner.id, + "company_id": company_id, + "type": "in", + "pay_type": "invoice", + 'date': datenow, + "account_id": st.import_account_id.id, + 'invoice_lines': invoice_lines, + 'rd_cust': True, #XXX + 'memo': memo, + } + payment_id=get_model("account.payment").create(vals,context={"type":"in"}) + obj.write({ + 'payment_id': payment_id, + }) + return { + 'next': { + 'name': 'payment', + 'mode': 'form', + 'active_id': payment_id, + }, + 'flash': 'Create Payment successfully', + } + + + def update_amount(self,context={}): + data=context['data'] + data['total']=0 + for line in data['lines']: + data['total']+=line['amount'] or 0 + return data + + def onchange_matching(self,context={}): + data=context['data'] + path=context['path'] + line=get_data_path(data,path,parent=True) + matching_id=line['matching_id'] + matching=get_model('clinic.matching.payment').browse(matching_id) + line['srv']=matching['total_srv'] or 0 + line['epo']=matching['total_epo'] or 0 + line['fee']=matching['total_fee'] or 0 + line['amount']=line['fee']+line['epo']+line['srv'] + data=self.update_amount(context=context) + return data + + def to_draft(self,ids,context={}): + for obj in self.browse(ids): + obj.write({ + 'state': 'draft', + }) + + def submit(self,ids,context={}): + obj=self.browse(ids)[0] + obj.write({ + 'state': 'waiting_approve', + }) + + def post(self,ids,context={}): + obj=self.browse(ids)[0] + obj.write({ + 'state': 'done', + }) + print("Post") + return { + 'next': { + 'name': 'clinic_invoice_payment', + 'mode': 'form', + 'active_id': obj.id, + }, + 'flash': 'Posted.An message will send to you after finish', + } + + def post_invoice(self,ids,context={}): + print("post_invoice") + + def reject(self,ids,context={}): + # send msg to user + for obj in self.browse(ids): + obj.write({ + 'state': 'draft', + }) + + def view_payment(self,ids,context={}): + obj=self.browse(ids)[0] + payment_id=None + if obj.payment_id: + payment_id=obj.payment_id.id + return { + 'next': { + 'name': 'payment', + 'mode': 'form', + 'active_id': payment_id, + }, + } + +InvoicePayment.register() diff --git a/netforce_clinic/models/hd_case.py b/netforce_clinic/models/hd_case.py index 10cd6f1..0fb7213 100644 --- a/netforce_clinic/models/hd_case.py +++ b/netforce_clinic/models/hd_case.py @@ -169,7 +169,7 @@ class HDCase(Model): set_active_user(user_id) return res - def _get_req_fee(self,ids,context={}): + def _get_req_button(self,ids,context={}): res={} for obj in self.browse(ids): total_amt=0 @@ -186,7 +186,12 @@ class HDCase(Model): paid=0 if due_amt>0: paid=1 - res[obj.id]=paid + res[obj.id]={ + 'to_pay': 0, + 'to_claim': 0, + 'req_fee': paid, + } + print("res ", res) return res def _get_hct_msg(self,ids,context={}): @@ -272,7 +277,9 @@ class HDCase(Model): 'nu': fields.Char("N/U"), "invoice_policy": fields.Selection([("fee","Only Fee"),("fee_mdc","Fee & Medicine")],"Government pay for:"), "invoice_option": fields.Selection([("fee_mdc_plus","Combine Fee & Medicine"),("fee_mdc_split","Split Fee & Medicine")],"Invoice:"), - 'req_fee': fields.Integer("Request Expense",function="_get_req_fee"), + 'req_fee': fields.Integer("Request Expense",function="_get_req_button",function_multi=True,store=True), + 'to_pay': fields.Integer("Request Expense",function="_get_req_button",function_multi=True,store=True), + 'to_claim': fields.Integer("Request Expense",function="_get_req_button",function_multi=True,store=True), 'hd_case_id': fields.Many2One("clinic.hd.case","HD",function="_get_all",function_multi=True), # XXX 'company_id': fields.Many2One("company","Company"), 'branch_id': fields.Many2One("clinic.branch","Branch"), @@ -704,7 +711,7 @@ class HDCase(Model): "inv_type": "invoice", "tax_type": "tax_in", 'due_date': due_date, - "ref": obj.number, + "ref": '%s (%s)'%(patient.name or '',patient.number or ''), "related_id": "clinic.hd.case,%s"%obj.id, "currency_id": currency_id, "company_id": company_id, diff --git a/netforce_clinic/models/invoice_payment.py b/netforce_clinic/models/invoice_payment.py index 6442e07..034b8af 100644 --- a/netforce_clinic/models/invoice_payment.py +++ b/netforce_clinic/models/invoice_payment.py @@ -1,196 +1,41 @@ -import time - -from netforce.model import Model, fields, get_model -from netforce.utils import get_data_path -from netforce.access import get_active_company, get_active_user +from netforce.model import Model, get_model class InvoicePayment(Model): - _name="clinic.invoice.payment" - _string="Payment Invoice" + _inherit="invoice.payment" - def _get_all(self,ids,context={}): - res={} - for obj in self.browse(ids): - total=0 - total_fee=0 - total_srv=0 - total_epo=0 - for line in obj.lines: - matching=line.matching_id - for mline in matching.lines: - if mline.state!='match': - continue - fee=mline.fee or 0 - total+=fee - total_fee+=fee - srv=mline.srv or 0 - total+=srv - total_srv+=srv - epo=mline.epo or 0 - total+=epo - total_epo+=epo - res[obj.id]={ - 'total': total, - 'total_epo': total_epo, - 'total_fee': total_fee, - 'total_srv': total_srv, - } - return res - - _fields={ - 'name': fields.Char("Name",required=True), - 'lines': fields.One2Many("clinic.invoice.payment.line","invoice_payment_id", "Lines"), - 'total': fields.Float("Total",function="_get_all",function_multi=True), - 'total_fee': fields.Float("FEE",function="_get_all",function_multi=True), - 'total_epo': fields.Float("EPO",function="_get_all",function_multi=True), - 'total_srv': fields.Float("Service",function="_get_all",function_multi=True), - 'state': fields.Selection([['draft','Draft'],['waiting_approve','Waiting Approval'],['approved','Approved'],['done','Done']],'State'), - 'date': fields.Date("Date"), - 'user_id': fields.Many2One("base.user","Approver"), - 'partner_id': fields.Many2One("partner","Contact"), - 'payment_id': fields.Many2One("account.payment","Payment"), - } - - _defaults={ - 'state': 'draft', - 'date': lambda *a: time.strftime("%Y-%m-%d"), - } - - def send_to_payment(self,ids,context={}): - count=0 - for obj in self.browse(ids): - res=obj.make_payment() - count+=1 - obj.write({ - 'state': 'done', - }) - # support list view - if count<=1: - return res - - def approve(self,ids,context={}): - for obj in self.browse(ids): - obj.write({ - 'state': 'approved', - 'user_id': get_active_user(), - }) - - def make_payment(self,ids,context={}): + def add_payment(self,ids,context={}): obj=self.browse(ids)[0] - invoice_lines=[] - for line in obj.lines: - for mline in line.matching_id.lines: - invoice=mline.invoice_id - state=mline.state - if invoice and state=='match': - vals={ - 'invoice_id': invoice.id, - 'amount': invoice.amount_due or 0, - } - invoice_lines.append(('create', vals)) - if not invoice_lines: - raise Exception("Nothing to approve") - 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.partner_id - company_id=get_active_company() - datenow=obj.date or time.strftime("%Y-%m-%d") - memo='Payment; %s'%(partner.name) + inv=obj.invoice_id + if inv.inv_type not in ("invoice","debit"): + raise Exception("Wrong invoice type") + if obj.amount>inv.amount_due: + raise Exception("Amount paid exceeds due amount") vals={ - "partner_id": partner.id, - "company_id": company_id, - "type": "in", + "type": inv.type=="out" and "in" or "out", "pay_type": "invoice", - 'date': datenow, - "account_id": st.import_account_id.id, - 'invoice_lines': invoice_lines, - 'rd_cust': True, #XXX - 'memo': memo, + "partner_id": inv.partner_id.id, + "date": obj.date, + "ref": obj.ref, + "account_id": obj.account_id.id, + "currency_id": inv.currency_id.id, + "lines": [("create",{ + "type": "invoice", + "invoice_id": inv.id, + "account_id": inv.account_id.id, + "amount": obj.amount, + })], } - payment_id=get_model("account.payment").create(vals,context={"type":"in"}) - obj.write({ - 'payment_id': payment_id, - }) - return { - 'next': { - 'name': 'payment', - 'mode': 'form', - 'active_id': payment_id, - }, - 'flash': 'Create Payment successfully', + pmt_id=get_model("account.payment").create(vals,context={"type":vals["type"]}) + # to check when before payment post + ctx={ + 'hdcase_reconcile':inv.hdcase_reconcile, } - - - def update_amount(self,context={}): - data=context['data'] - data['total']=0 - for line in data['lines']: - data['total']+=line['amount'] or 0 - return data - - def onchange_matching(self,context={}): - data=context['data'] - path=context['path'] - line=get_data_path(data,path,parent=True) - matching_id=line['matching_id'] - matching=get_model('clinic.matching.payment').browse(matching_id) - line['srv']=matching['total_srv'] or 0 - line['epo']=matching['total_epo'] or 0 - line['fee']=matching['total_fee'] or 0 - line['amount']=line['fee']+line['epo']+line['srv'] - data=self.update_amount(context=context) - return data - - def to_draft(self,ids,context={}): - for obj in self.browse(ids): - obj.write({ - 'state': 'draft', - }) - - def submit(self,ids,context={}): - obj=self.browse(ids)[0] - obj.write({ - 'state': 'waiting_approve', - }) - - def post(self,ids,context={}): - obj=self.browse(ids)[0] - obj.write({ - 'state': 'done', - }) - print("Post") + get_model("account.payment").post([pmt_id],context=ctx) return { - 'next': { - 'name': 'clinic_invoice_payment', - 'mode': 'form', - 'active_id': obj.id, - }, - 'flash': 'Posted.An message will send to you after finish', - } - - def post_invoice(self,ids,context={}): - print("post_invoice") - - def reject(self,ids,context={}): - # send msg to user - for obj in self.browse(ids): - obj.write({ - 'state': 'draft', - }) - - def view_payment(self,ids,context={}): - obj=self.browse(ids)[0] - payment_id=None - if obj.payment_id: - payment_id=obj.payment_id.id - return { - 'next': { - 'name': 'payment', - 'mode': 'form', - 'active_id': payment_id, - }, + "next": { + "name": "view_invoice", + "active_id": inv.id, + } } InvoicePayment.register()