import time from netforce.model import Model, fields, get_model class AccountInvoice(Model): _inherit="account.invoice" _fields={ 'clinic_expense_id': fields.Many2One("clinic.hd.case.expense","Expense"), 'department_id': fields.Many2One("clinic.department","Department",search=True), } #override netforce_account/account_invoice def post(self,ids,context={}): print("override post invoice") t0=time.time() settings=get_model("settings").browse(1) for obj in self.browse(ids): obj.check_related() if abs(obj.amount_total)<0.001: raise Exception("Invoice total is zero") partner=obj.partner_id if obj.type=="out": account_id=partner.account_receivable_id.id or settings.account_receivable_id.id if not account_id: raise Exception("Account receivable not found") elif obj.type=="in": account_id=partner.account_payable_id.id or settings.account_payable_id.id if not account_id: raise Exception("Account payable not found") sign=obj.type=="out" and 1 or -1 if obj.inv_type=="credit": sign*=-1 obj.write({"account_id": account_id}) if obj.type=="out": desc="Sale; "+partner.name elif obj.type=="in": desc="Purchase; "+partner.name if obj.type=="out": journal_id=obj.journal_id.id or settings.sale_journal_id.id if not journal_id: raise Exception("Sales journal not found") elif obj.type=="in": journal_id=obj.journal_id.id or settings.purchase_journal_id.id if not journal_id: raise Exception("Purchases journal not found") if obj.type=="out": rate_type="sell" elif obj.type=="in": rate_type="buy" move_vals={ "journal_id": journal_id, "number": obj.number, "date": obj.date, "ref": obj.ref, "narration": desc, "related_id": "account.invoice,%s"%obj.id, "company_id": obj.company_id.id, } lines=[] taxes={} tax_nos=[] t01=time.time() total_amt=0.0 total_base=0.0 total_tax=0.0 hdcase=obj.related_id for line in obj.lines: cur_amt=get_model("currency").convert(line.amount,obj.currency_id.id,settings.currency_id.id,date=obj.date,rate_type=rate_type) total_amt+=cur_amt tax_id=line.tax_id if tax_id and obj.tax_type!="no_tax": base_amt=get_model("account.tax.rate").compute_base(tax_id,cur_amt,tax_type=obj.tax_type) tax_comps=get_model("account.tax.rate").compute_taxes(tax_id,base_amt,when="invoice") for comp_id,tax_amt in tax_comps.items(): tax_vals=taxes.setdefault(comp_id,{"tax_amt":0,"base_amt":0}) tax_vals["tax_amt"]+=tax_amt tax_vals["base_amt"]+=base_amt total_tax+=tax_amt else: base_amt=cur_amt total_base+=base_amt acc_id=line.account_id.id if not acc_id: raise Exception("Missing line account for invoice line '%s'"%line.description) amt=base_amt*sign line_vals={ "description": line.description, "account_id": acc_id, "credit": amt>0 and amt or 0, "debit": amt<0 and -amt or 0, "track_id": line.track_id.id, "track2_id": line.track2_id.id, "partner_id": partner.id, } lines.append(line_vals) #XXX ar_debit=line.ar_debit_id if hdcase and ar_debit: amt=amt*-1 line_vals={ "description": line.description, "account_id": ar_debit.id, "credit": amt>0 and amt or 0, "debit": amt<0 and -amt or 0, "track_id": line.track_id.id, "track2_id": line.track2_id.id, "partner_id": partner.id, } lines.append(line_vals) for comp_id,tax_vals in taxes.items(): comp=get_model("account.tax.component").browse(comp_id) acc_id=comp.account_id.id if not acc_id: raise Exception("Missing account for tax component %s"%comp.name) amt=tax_vals["tax_amt"]*sign line_vals={ "description": desc, "account_id": acc_id, "credit": amt>0 and amt or 0, "debit": amt<0 and -amt or 0, "tax_comp_id": comp_id, "tax_base": tax_vals["base_amt"], "partner_id": partner.id, "invoice_id": obj.id, } if comp.type=="vat": if obj.type=="out": if obj.tax_no: tax_no=obj.tax_no else: tax_no=self.gen_tax_no(exclude=tax_nos,context={"date":obj.date}) tax_nos.append(tax_no) obj.write({"tax_no":tax_no}) line_vals["tax_no"]=tax_no elif obj.type=="in": line_vals["tax_no"]=obj.tax_no lines.append(line_vals) if obj.tax_type=="tax_in": rounding=total_amt-(total_base+total_tax) if abs(rounding)>0.00499: # XXX amt=rounding*sign if not settings.rounding_account_id.id: raise Exception("Missing rounding account in financial settings") line_vals={ "description": desc, "account_id": settings.rounding_account_id.id, "credit": amt>0 and amt or 0, "debit": amt<0 and -amt or 0, "partner_id": partner.id, "invoice_id": obj.id, } lines.append(line_vals) t02=time.time() dt01=(t02-t01)*1000 print("post dt01",dt01) groups={} keys=["description","account_id","track_id","tax_comp_id","partner_id","invoice_id","reconcile_id"] for line in lines: key_val=tuple(line.get(k) for k in keys) if key_val in groups: group=groups[key_val] group["debit"]+=line["debit"] group["credit"]+=line["credit"] if line.get("tax_base"): if "tax_base" not in group: group["tax_base"]=0 group["tax_base"]+=line["tax_base"] else: groups[key_val]=line.copy() group_lines=sorted(groups.values(),key=lambda l: (l["debit"],l["credit"])) for line in group_lines: amt=line["debit"]-line["credit"] amt=get_model("currency").round(settings.currency_id.id,amt) if amt>=0: line["debit"]=amt line["credit"]=0 else: line["debit"]=0 line["credit"]=-amt amt=0 for line in group_lines: amt-=line["debit"]-line["credit"] #XXX if amt >0: line_vals={ "description": desc, "account_id": account_id, "debit": amt>0 and amt or 0, "credit": amt<0 and -amt or 0, "due_date": obj.due_date, "partner_id": partner.id, } move_vals["lines"]=[("create",line_vals)] move_vals["lines"]+=[("create",vals) for vals in group_lines] else: move_vals["lines"]=[("create",vals) for vals in group_lines] t03=time.time() dt02=(t03-t02)*1000 print("post dt02",dt02) move_id=get_model("account.move").create(move_vals) t04=time.time() dt03=(t04-t03)*1000 print("post dt03",dt03) get_model("account.move").post([move_id]) t05=time.time() dt04=(t05-t04)*1000 print("post dt04",dt04) currency_rate=obj.currency_id.get_rate(date=obj.date,rate_type=rate_type) obj.write({"move_id":move_id,"currency_rate":currency_rate,"state":"waiting_payment"}) t06=time.time() dt05=(t06-t05)*1000 print("post dt05",dt05) t1=time.time() dt=(t1-t0)*1000 print("overrice invoice.post <<< %d ms"%dt) AccountInvoice.register()