def export_static_files(self, ids, context={}): obj = self.browse(ids)[0] theme = obj.name dbname = get_active_db() if obj.file: zip_path = utils.get_file_path(obj.file) zf = zipfile.ZipFile(zip_path) for n in zf.namelist(): if not n.startswith("static/"): continue if n[-1] == "/": continue n2 = n[7:] if n2.find("..") != -1: continue data = zf.read(n) f_path = "static/db/" + dbname + "/themes/" + theme + "/" + n2 dir_path = os.path.dirname(f_path) if not os.path.exists(dir_path): os.makedirs(dir_path) print("export file", f_path) open(f_path, "wb").write(data) else: export_module_file_all("themes/" + theme + "/static", "static/db/" + dbname + "/themes/" + theme)
def import_data(self, ids, context={}): obj = self.browse(ids)[0] if obj.import_type == 'auto': obj.import_auto() else: if not obj.file: raise Exception("File not found") if obj.file.split(".")[-1] != 'csv': raise Exception("Wrong File") fpath = get_file_path(obj.file) data = open(fpath, "r").read().split("\n") att_ids = [] records = {} for row in data: lines = row.split(",") if not lines: continue size = len(lines) if size < 2: continue if size > 2: raise Exception("Wrong File") att_id = lines[0] att_date = lines[1] if not records.get(att_id): records[att_id] = [] records[att_id].append(att_date) continue # TODO Check format date if att_id not in att_ids: att_ids.append(att_id) # self.set_att(ids,att_ids,context=context) emps = { emp['attendance_id']: emp['id'] for emp in get_model("hr.employee").search_read( [], ['attendance_id']) } att = get_model("hr.attendance") at_ids = att.search([]) # XXX testing att.delete(at_ids) for att_id, lines in records.items(): att_id = int(att_id) date_list = [] for line in lines: datetime = line date = datetime.split(" ")[0] action = 'sign_in' if date in date_list: action = 'sign_out' # FIXME find the last record and overwrite time date_list.append(date) att.create({ 'employee_id': emps[att_id], 'action': action, 'time': datetime, }) print("Done!")
def delete(self, ids, **kw): files = [] for obj in self.browse(ids): if obj.file: files.append(obj.file) super().delete(ids, **kw) for f in files: path = utils.get_file_path(f) os.remove(path)
def import_data(self, ids, context={}): obj = self.browse(ids)[0] if obj.import_type == 'auto': obj.import_auto() else: if not obj.file: raise Exception("File not found") if obj.file.split(".")[-1] != 'csv': raise Exception("Wrong File") fpath = get_file_path(obj.file) data = open(fpath, "r").read().split("\n") att_ids = [] records = {} for row in data: lines = row.split(",") if not lines: continue size = len(lines) if size < 2: continue if size > 2: raise Exception("Wrong File") att_id = lines[0] att_date = lines[1] if not records.get(att_id): records[att_id] = [] records[att_id].append(att_date) continue # TODO Check format date if att_id not in att_ids: att_ids.append(att_id) # self.set_att(ids,att_ids,context=context) emps = {emp['attendance_id']: emp['id'] for emp in get_model("hr.employee").search_read([], ['attendance_id'])} att = get_model("hr.attendance") at_ids = att.search([]) # XXX testing att.delete(at_ids) for att_id, lines in records.items(): att_id = int(att_id) date_list = [] for line in lines: datetime = line date = datetime.split(" ")[0] action = 'sign_in' if date in date_list: action = 'sign_out' # FIXME find the last record and overwrite time date_list.append(date) att.create({ 'employee_id': emps[att_id], 'action': action, 'time': datetime, }) print("Done!")
def send_email_smtp(self, ids, context={}): print("send_email_smtp", ids) obj = self.browse(ids)[0] if obj.state not in ("draft", "to_send"): return try: mailbox = obj.mailbox_id if not mailbox: raise Exception("Missing mailbox") account = mailbox.account_id if account.type != "smtp": raise Exception("Invalid email account type") if account.security == "SSL": server = smtplib.SMTP_SSL(account.host, account.port or 465, timeout=30) else: server = smtplib.SMTP(account.host, account.port or 587, timeout=30) server.ehlo() if account.security == "starttls": server.starttls() if account.user: server.login(account.user, account.password) msg = MIMEMultipart() msg.set_charset("utf-8") msg["From"] = obj.from_addr msg["To"] = obj.to_addrs if obj.cc_addrs: msg["Cc"] = obj.cc_addrs msg["Subject"] = Header(obj.subject, "utf-8") msg.attach(MIMEText(obj.body, "html", "utf-8")) for attach in obj.attachments: path = utils.get_file_path(attach.file) data = open(path, "rb").read() part = MIMEBase('application', "octet-stream") part.set_payload(data) encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % attach.file) msg.attach(part) to_addrs = obj.to_addrs.split(",") cc_addrs = obj.cc_addrs.split(",") if obj.cc_addrs else [] server.sendmail(obj.from_addr, to_addrs + cc_addrs, msg.as_string()) obj.write({"state": "sent"}) server.quit() except Exception as e: print("WARNING: failed to send email %s" % obj.id) import traceback traceback.print_exc() obj.write({"state": "error", "error_message": str(e)})
def onchange_file(self, context={}): print("onchange_file") data = context["data"] filename = data["file"] if not filename: return categ_id = data["categ_id"] if not categ_id: return categ = get_model("document.categ").browse(categ_id) fmt = categ.file_name if not fmt: return contact_id = data.get("contact_id") if contact_id: contact = get_model("contact").browse(contact_id) else: contact = None date = data["date"] vals = { "contact_code": contact and contact.code or "", "doc_code": categ.code or "", "Y": date[0:4], "y": date[2:4], "m": date[5:7], "d": date[8:10], } filename2 = fmt % vals res = os.path.splitext(filename) rand = base64.urlsafe_b64encode(os.urandom(8)).decode() filename2 += "," + rand + res[1] if filename2 != filename: path = utils.get_file_path(filename) path2 = utils.get_file_path(filename2) os.rename(path, path2) return { "vals": { "file": filename2, } }
def import_acc_file(self, ids, context): obj = self.browse(ids)[0] path = get_file_path(obj.file) data = open(path).read() rd = csv.reader(StringIO(data)) headers = next(rd) headers = [h.strip() for h in headers] del_ids = get_model("conv.account").search([["conv_id", "=", obj.id]]) get_model("conv.account").delete(del_ids) for row in rd: print("row", row) line = dict(zip(headers, row)) print("line", line) if not line.get("Account"): continue acc_code = line["Account"].strip() if not acc_code: continue res = get_model("account.account").search([["code", "=", acc_code]]) if not res: raise Exception("Account code not found: %s" % acc_code) acc_id = res[0] debit = float(line["Debit"].strip().replace(",", "") or 0) credit = float(line["Credit"].strip().replace(",", "") or 0) amount_cur = line["Currency Amt"].strip().replace(",", "") if amount_cur: amount_cur = float(amount_cur) else: amount_cur = None track_id=line.get('Track-1') if track_id: track_id = self.get_track_categ(track_id) track2_id=line.get('Track-2') if track2_id: track2_id = self.get_track_categ(track2_id) vals = { "conv_id": obj.id, "account_id": acc_id, "debit": debit, "credit": credit, "amount_cur": amount_cur, "track_id": track_id, "track2_id": track2_id, } get_model("conv.account").create(vals) return { "next": { "name": "conv_bal", "active_id": obj.id, "view_xml": "conv_bal1", } }
def get_data(self, ids, context={}): settings = get_model("settings").browse(1) pages = [] for obj in self.browse(ids): context['refer_id'] = obj.id data = self.get_payslip(context=context) pages.append(data) if pages: pages[-1]["is_last_page"] = True return { "pages": pages, "logo": get_file_path(settings.logo), }
def get_data(self, ids, context={}): company_id = get_active_company() comp = get_model("company").browse(company_id) settings = get_model('settings').browse(1) pages = [] for obj in self.browse(ids): lines = [] for line in obj.lines: lines.append({ 'description': line.description, 'account_code': line.account_id.code, 'account_name': line.account_id.name, 'debit': line.debit, 'credit': line.credit, 'tax_comp': line.tax_comp_id.name, 'tax_base': line.tax_base, 'track': line.track_id.name, 'contact': line.contact_id.name, }) data = { "comp_name": comp.name, "number": obj.number, "date": obj.date, "journal": obj.journal_id.name, "narration": obj.narration, "lines": lines, "total_debit": obj.total_debit, "total_credit": obj.total_credit, } if settings.logo: data['logo'] = get_file_path(settings.logo) pages.append(data) if pages: pages[-1]["is_last_page"] = True return { "pages": pages, "logo": get_file_path(settings.logo), # XXX: remove when render_odt fixed }
def _get_report_path(name): fname = name + ".jrxml" report_dir = tempfile.mkdtemp() print("report_dir", report_dir) try: _extract_report_file(fname, report_dir) except: res = get_model("report.template").search([["name", "=", name]]) if not res: raise Exception("Report template not found: %s" % name) tmpl_id = res[0] tmpl = get_model("report.template").browse(tmpl_id) in_path = utils.get_file_path(tmpl.file) data = open(in_path, "rb").read() out_path = os.path.join(report_dir, fname) f = open(out_path, "wb") f.write(data) f.close() report_path = os.path.join(report_dir, fname) tree = etree.parse(report_path) for el in tree.iterfind( ".//ns:imageExpression", {"ns": "http://jasperreports.sourceforge.net/jasperreports"}): expr = el.text m = re.match("^\"(.*)\"$", expr) if m: img_fname = m.group(1) img_path = utils.get_file_path(img_fname) if os.path.exists(img_path): img_path2 = os.path.join(report_dir, img_fname) shutil.copyfile(img_path, img_path2) else: _extract_report_file(img_fname, report_dir) el.text = '"' + os.path.join(report_dir, img_fname) + '"' report_xml = etree.tostring(tree, pretty_print=True).decode() f = open(report_path, "w") f.write(report_xml) f.close() return report_path
def send_email_mailgun(self, ids, context={}): print("send_emails_mailgun", ids) obj = self.browse(ids)[0] if obj.state not in ("draft", "to_send"): return try: mailbox = obj.mailbox_id if not mailbox: raise Exception("Missing mailbox") account = mailbox.account_id if account.type != "mailgun": raise Exception("Invalid email account type") url = "https://api.mailgun.net/v2/%s/messages" % account.user to_addrs = [] for a in obj.to_addrs.split(","): a = a.strip() if not utils.check_email_syntax(a): raise Exception("Invalid email syntax: %s" % a) to_addrs.append(a) if not to_addrs: raise Exception("Missing recipient address") data = { "from": obj.from_addr, "to": to_addrs, "subject": obj.subject, } if obj.cc_addrs: data["cc"] = [a.strip() for a in obj.cc_addrs.split(",")] data["html"] = obj.body or "<html><body></body></html>" files = [] for attach in obj.attachments: path = utils.get_file_path(attach.file) f = open(path, "rb") files.append(("attachment", f)) r = requests.post(url, auth=("api", account.password), data=data, files=files, timeout=15) try: res = json.loads(r.text) msg_id = res["id"] except: raise Exception("Invalid mailgun response: %s" % r.text) obj.write({"state": "sent", "message_id": msg_id}) except Exception as e: print("WARNING: failed to send email %s" % obj.id) import traceback traceback.print_exc() obj.write({"state": "error", "error_message": str(e)})
def _get_report_path(name): fname = name + ".jrxml" report_dir = tempfile.mkdtemp() print("report_dir", report_dir) try: _extract_report_file(fname, report_dir) except: res = get_model("report.template").search([["name", "=", name]]) if not res: raise Exception("Report template not found: %s" % name) tmpl_id = res[0] tmpl = get_model("report.template").browse(tmpl_id) in_path = utils.get_file_path(tmpl.file) data = open(in_path, "rb").read() out_path = os.path.join(report_dir, fname) f = open(out_path, "wb") f.write(data) f.close() report_path = os.path.join(report_dir, fname) tree = etree.parse(report_path) for el in tree.iterfind(".//ns:imageExpression", {"ns": "http://jasperreports.sourceforge.net/jasperreports"}): expr = el.text m = re.match("^\"(.*)\"$", expr) if m: img_fname = m.group(1) img_path = utils.get_file_path(img_fname) if os.path.exists(img_path): img_path2 = os.path.join(report_dir, img_fname) shutil.copyfile(img_path, img_path2) else: _extract_report_file(img_fname, report_dir) el.text = '"' + os.path.join(report_dir, img_fname) + '"' report_xml = etree.tostring(tree, pretty_print=True).decode() f = open(report_path, "w") f.write(report_xml) f.close() return report_path
def get_report_template(name, report_type): db = database.get_connection() res = db.get("SELECT file FROM report_template WHERE name=%s AND format=%s", name, report_type) if res: path = utils.get_file_path(res.file) data = open(path, "rb").read() return data loaded_modules = module.get_loaded_modules() for m in reversed(loaded_modules): f = "reports/" + name + "." + report_type if not pkg_resources.resource_exists(m, f): continue data = pkg_resources.resource_string(m, f) return data raise Exception("Report not found: %s" % name)
def get_data_pick_internal_form(self, context={}): company_id = get_active_company() comp = get_model("company").browse(company_id) obj_id = int(context["refer_id"]) obj = get_model("stock.picking").browse(obj_id) settings = get_model("settings").browse(1) comp_addr = settings.get_address_str() comp_name = comp.name comp_phone = settings.phone comp_fax = settings.fax comp_tax_no = settings.tax_no contact = obj.contact_id cust_addr = contact.get_address_str() cust_name = contact.name cust_fax = contact.fax cust_phone = contact.phone cust_tax_no = contact.tax_no data = { "comp_name": comp_name, "comp_addr": comp_addr, "comp_phone": comp_phone or "-", "comp_fax": comp_fax or "-", "comp_tax_no": comp_tax_no or "-", "cust_name": cust_name, "cust_addr": cust_addr, "cust_phone": cust_phone or "-", "cust_fax": cust_fax or "-", "cust_tax_no": cust_tax_no or "-", "date": obj.date, "number": obj.number, "ref": obj.ref, "lines": [], } if settings.logo: data["logo"] = get_file_path(settings.logo) for line in obj.lines: data["lines"].append({ "product": line.product_id.name, "description": line.product_id.description, "qty": line.qty, "uom": line.uom_id.name, "location_from": line.location_from_id.name, "location_to": line.location_to_id.name, "cost_price": line.cost_price, }) return data
def get_report_template(name, report_type): db = database.get_connection() res = db.get( "SELECT file FROM report_template WHERE name=%s AND format=%s", name, report_type) if res: path = utils.get_file_path(res.file) data = open(path, "rb").read() return data loaded_modules = module.get_loaded_modules() for m in reversed(loaded_modules): f = "reports/" + name + "." + report_type if not pkg_resources.resource_exists(m, f): continue data = pkg_resources.resource_string(m, f) return data raise Exception("Report not found: %s" % name)
def send_email_mailgun(self, ids, context={}): print("send_emails_mailgun", ids) obj = self.browse(ids)[0] if obj.state not in ("draft","to_send"): return try: mailbox = obj.mailbox_id if not mailbox: raise Exception("Missing mailbox") account = mailbox.account_id if account.type != "mailgun": raise Exception("Invalid email account type") url = "https://api.mailgun.net/v2/%s/messages" % account.user to_addrs = [] for a in obj.to_addrs.split(","): a = a.strip() if not utils.check_email_syntax(a): raise Exception("Invalid email syntax: %s" % a) to_addrs.append(a) if not to_addrs: raise Exception("Missing recipient address") data = { "from": obj.from_addr, "to": to_addrs, "subject": obj.subject, } if obj.cc_addrs: data["cc"] = [a.strip() for a in obj.cc_addrs.split(",")] data["html"] = obj.body or "<html><body></body></html>" files = [] for attach in obj.attachments: path = utils.get_file_path(attach.file) f = open(path, "rb") files.append(("attachment", f)) r = requests.post(url, auth=("api", account.password), data=data, files=files,timeout=15) try: res = json.loads(r.text) msg_id = res["id"] except: raise Exception("Invalid mailgun response: %s" % r.text) obj.write({"state": "sent", "message_id": msg_id}) except Exception as e: print("WARNING: failed to send email %s" % obj.id) import traceback traceback.print_exc() obj.write({"state": "error", "error_message": str(e)})
def send_email_smtp(self, ids, context={}): print("send_email_smtp", ids) obj = self.browse(ids)[0] if obj.state not in ("draft", "to_send"): return try: mailbox = obj.mailbox_id if not mailbox: raise Exception("Missing mailbox") account = mailbox.account_id if account.type != "smtp": raise Exception("Invalid email account type") if account.security == "SSL": server = smtplib.SMTP_SSL(account.host, account.port or 465, timeout=30) else: server = smtplib.SMTP(account.host, account.port or 587, timeout=30) server.ehlo() if account.security == "starttls": server.starttls() if account.user: server.login(account.user, account.password) msg = MIMEMultipart() msg.set_charset("utf-8") msg["From"] = obj.from_addr msg["To"] = obj.to_addrs msg["Subject"] = Header(obj.subject, "utf-8") msg.attach(MIMEText(obj.body, "html", "utf-8")) for attach in obj.attachments: path = utils.get_file_path(attach.file) data = open(path, "rb").read() part = MIMEBase("application", "octet-stream") part.set_payload(data) encode_base64(part) part.add_header("Content-Disposition", 'attachment; filename="%s"' % attach.file) msg.attach(part) to_addrs = obj.to_addrs.split(",") server.sendmail(obj.from_addr, to_addrs, msg.as_string()) obj.write({"state": "sent"}) server.quit() except Exception as e: print("WARNING: failed to send email %s" % obj.id) import traceback traceback.print_exc() obj.write({"state": "error", "error_message": str(e)})
def import_acc_file(self, ids, context): obj = self.browse(ids)[0] path = get_file_path(obj.file) data = open(path).read() rd = csv.reader(StringIO(data)) headers = next(rd) headers = [h.strip() for h in headers] del_ids = get_model("conv.account").search([["conv_id", "=", obj.id]]) get_model("conv.account").delete(del_ids) for row in rd: print("row", row) line = dict(zip(headers, row)) print("line", line) if not line.get("Account"): continue acc_code = line["Account"].strip() if not acc_code: continue res = get_model("account.account").search([["code", "=", acc_code]]) if not res: raise Exception("Account code not found: %s" % acc_code) acc_id = res[0] debit = float(line["Debit"].strip().replace(",", "") or 0) credit = float(line["Credit"].strip().replace(",", "") or 0) amount_cur = line["Currency Amt"].strip().replace(",", "") if amount_cur: amount_cur = float(amount_cur) else: amount_cur = None vals = { "conv_id": obj.id, "account_id": acc_id, "debit": debit, "credit": credit, "amount_cur": amount_cur, } get_model("conv.account").create(vals) return { "next": { "name": "conv_bal", "active_id": obj.id, "view_xml": "conv_bal1", } }
def load_templates(self, ids, context={}): obj = self.browse(ids[0]) if obj.file: zip_path = utils.get_file_path(obj.file) zf = zipfile.ZipFile(zip_path) for n in zf.namelist(): if not n.startswith("templates/"): continue if not n.endswith(".hbs"): continue n2 = n[10:-4] if n2.find("..") != -1: continue print("load template", n2) data = zf.read(n) vals = { "name": n2, "template": data.decode(), "theme_id": obj.id, } get_model("template").merge(vals) else: theme = obj.name loaded_modules = module.get_loaded_modules() for m in reversed(loaded_modules): if not pkg_resources.resource_isdir( m, "themes/" + theme + "/templates"): continue for f in pkg_resources.resource_listdir( m, "themes/" + theme + "/templates"): if not f.endswith(".hbs"): continue f2 = f[:-4] print("load template", f2) data = pkg_resources.resource_string( m, "themes/" + theme + "/templates/" + f) vals = { "name": f2, "template": data.decode(), "theme_id": obj.id, } get_model("template").merge(vals)
def import_bank_file(self, ids, context={}): obj = self.browse(ids)[0] path = get_file_path(obj.bank_file) data = open(path).read() rd = csv.reader(StringIO(data)) headers = next(rd) headers = [h.strip() for h in headers] for row in rd: print("row", row) line = dict(zip(headers, row)) print("line", line) vals = { "import_id": obj.id, "type": "bank", "date": parse_date(line["Date"], obj.date_fmt), "description": line["Description"], "received": parse_float(line["Received"]), "spent": parse_float(line["Spent"]), "invoice_no": line["Invoice No."], "other_account_id": get_account(line["Other Account"]), } get_model("batch.import.payment").create(vals)
def load_templates(self, ids, context={}): obj = self.browse(ids[0]) if obj.file: zip_path = utils.get_file_path(obj.file) zf = zipfile.ZipFile(zip_path) for n in zf.namelist(): if not n.startswith("templates/"): continue if not n.endswith(".hbs"): continue n2 = n[10:-4] if n2.find("..") != -1: continue print("load template", n2) data = zf.read(n) vals = { "name": n2, "template": data.decode(), "theme_id": obj.id, } get_model("template").merge(vals) else: theme = obj.name loaded_modules = module.get_loaded_modules() for m in reversed(loaded_modules): if not pkg_resources.resource_isdir(m, "themes/" + theme + "/templates"): continue for f in pkg_resources.resource_listdir(m, "themes/" + theme + "/templates"): if not f.endswith(".hbs"): continue f2 = f[:-4] print("load template", f2) data = pkg_resources.resource_string(m, "themes/" + theme + "/templates/" + f) vals = { "name": f2, "template": data.decode(), "theme_id": obj.id, } get_model("template").merge(vals)
def import_purchase_file(self, ids, context={}): obj = self.browse(ids)[0] path = get_file_path(obj.purchase_file) data = open(path).read() rd = csv.reader(StringIO(data)) headers = next(rd) headers = [h.strip() for h in headers] for row in rd: print("row", row) line = dict(zip(headers, row)) print("line", line) vals = { "import_id": obj.id, "date": parse_date(line["Date"], obj.date_fmt), "number": line["Invoice No."], "contact": line["Supplier Name"], "description": line["Description"], "amount": parse_float(line["Amount"]), "account_id": get_account(line["Expense Account"]), "tax_id": get_tax_rate(line["Tax Rate"]), } get_model("batch.import.purchase.invoice").create(vals)
def get_theme_static_data(theme_name, path): print("get_theme_static_data", theme_name, path) db = database.get_connection() if not db: return None res = db.get("SELECT file FROM cms_theme WHERE name=%s", theme_name) if not res: return None if res.file: zip_path = utils.get_file_path(res.file) zip_data = open(zip_path, "rb").read() f = BytesIO(zip_data) zf = zipfile.ZipFile(f) try: data = zf.read("static/" + path) return data except: return None else: data = module.read_module_file("themes/" + theme_name + "/static/" + path) if data: return data return None
def import_purch_file(self, ids, context): obj = self.browse(ids)[0] path = get_file_path(obj.file) data = open(path).read() rd = csv.reader(StringIO(data)) headers = next(rd) headers = [h.strip() for h in headers] del_ids = get_model("conv.purch.invoice").search([["conv_id", "=", obj.id]]) get_model("conv.purch.invoice").delete(del_ids) i = 1 for row in rd: i += 1 try: print("row", row) line = dict(zip(headers, row)) print("line", line) if not line.get("Number"): continue number = line["Number"].strip() if not number: continue ref = line["Reference"].strip() contact_name = line["Contact"].strip() res = get_model("contact").search([["name", "=", contact_name]]) if not res: raise Exception("Contact not found: '%s'" % contact_name) contact_id = res[0] date = datetime.datetime.strptime(line["Date"].strip(), obj.date_fmt).strftime("%Y-%m-%d") due_date = datetime.datetime.strptime(line["Due Date"].strip(), obj.date_fmt).strftime("%Y-%m-%d") amount_due = float(line["Amount Due"].strip().replace(",", "") or 0) acc_code = line["Account"].strip() if not acc_code: raise Exception("Account is missing") res = get_model("account.account").search([["code", "=", acc_code]]) if not res: raise Exception("Account code not found: %s" % acc_code) acc_id = res[0] amount_cur=None if line.get("Currency Amt"): amount_cur = line["Currency Amt"].strip().replace(",", "") amount_cur = float(amount_cur) track_id=line.get('Track-1') if track_id: track_id = self.get_track_categ(track_id) track2_id=line.get('Track-2') if track2_id: track2_id = self.get_track_categ(track2_id) vals = { "conv_id": obj.id, "number": number, "ref": ref, "contact_id": contact_id, "date": date, "due_date": due_date, "amount_due": amount_due, "account_id": acc_id, "amount_cur": amount_cur, "track_id": track_id, "track2_id": track2_id, } get_model("conv.purch.invoice").create(vals) except Exception as e: raise Exception("Error line %d: %s" % (i, e)) return { "next": { "name": "conv_bal", "active_id": obj.id, "view_xml": "conv_bal3", } }
def get_data_form(self, context={}): inv_id = context.get("invoice_id") # XXX: old, move this if not inv_id: inv_id = context["refer_id"] inv_id = int(inv_id) inv = get_model("account.invoice").browse(inv_id) dbname = database.get_active_db() company = inv.company_id settings = get_model("settings").browse(1) comp_addr = settings.get_address_str() comp_name = company.name comp_phone = settings.phone comp_fax = settings.fax comp_tax_no = settings.tax_no contact = inv.contact_id cust_addr = contact.get_address_str() cust_name = contact.name cust_fax = contact.fax cust_phone = contact.phone cust_tax_no = contact.tax_no data = { "comp_name": comp_name, "comp_addr": comp_addr, "comp_phone": comp_phone or "-", "comp_fax": comp_fax or "-", "comp_tax_no": comp_tax_no or "-", "cust_name": cust_name, "cust_addr": cust_addr, "cust_phone": cust_phone or "-", "cust_fax": cust_fax or "-", "cust_tax_no": cust_tax_no or "-", "date": inv.date or "-", "due_date": inv.due_date or "-", "number": inv.number or "-", "ref": inv.ref or "-", "memo": inv.memo or "", "lines": [], } if settings.logo: data["logo"] = get_file_path(settings.logo) for line in inv.lines: data["lines"].append({ "description": line.description, "code": line.product_id.code, "qty": line.qty, "uom": line.uom_id.name, "unit_price": line.unit_price, "discount": line.discount, "tax_rate": line.tax_id.rate, "amount": line.amount, }) is_cash = 'No' is_cheque = 'No' for obj in inv.payments: account_type = obj.payment_id.account_id.type if account_type in ("bank", "cash"): is_cash = 'Yes' if account_type in ("cheque"): is_cheque = 'Yes' data.update({ "amount_subtotal": inv.amount_subtotal, "amount_discount": inv.amount_discount, "amount_tax": inv.amount_tax, "amount_total": inv.amount_total, "amount_paid": inv.amount_paid, "payment_terms": inv.related_id.payment_terms or "-", "is_cash": is_cash, "is_cheque": is_cheque, "currency_code": inv.currency_id.code, "tax_rate": round(inv.amount_tax * 100.0 / inv.amount_subtotal or 0, 2), "qty_total": inv.qty_total, "memo": inv.memo, }) if inv.credit_alloc: data.update({ "original_inv_subtotal": inv.credit_alloc[0].invoice_id.amount_subtotal, }) return data
def import_purch_file(self, ids, context): obj = self.browse(ids)[0] path = get_file_path(obj.file) data = open(path).read() rd = csv.reader(StringIO(data)) headers = next(rd) headers = [h.strip() for h in headers] del_ids = get_model("conv.purch.invoice").search([["conv_id", "=", obj.id]]) get_model("conv.purch.invoice").delete(del_ids) i = 1 for row in rd: i += 1 try: print("row", row) line = dict(zip(headers, row)) print("line", line) if not line.get("Number"): continue number = line["Number"].strip() if not number: continue ref = line["Reference"].strip() contact_name = line["Contact"].strip() res = get_model("contact").search([["name", "=", contact_name]]) if not res: raise Exception("Contact not found: '%s'" % contact_name) contact_id = res[0] date = datetime.datetime.strptime(line["Date"].strip(), obj.date_fmt).strftime("%Y-%m-%d") due_date = datetime.datetime.strptime(line["Due Date"].strip(), obj.date_fmt).strftime("%Y-%m-%d") amount_due = float(line["Amount Due"].strip().replace(",", "") or 0) acc_code = line["Account"].strip() if not acc_code: raise Exception("Account is missing") res = get_model("account.account").search([["code", "=", acc_code]]) if not res: raise Exception("Account code not found: %s" % acc_code) acc_id = res[0] amount_cur = line["Amount Cur"].strip().replace(",", "") if amount_cur: amount_cur = float(amount_cur) else: amount_cur = None vals = { "conv_id": obj.id, "number": number, "ref": ref, "contact_id": contact_id, "date": date, "due_date": due_date, "amount_due": amount_due, "account_id": acc_id, "amount_cur": amount_cur, } get_model("conv.purch.invoice").create(vals) except Exception as e: raise Exception("Error line %d: %s" % (i, e)) return { "next": { "name": "conv_bal", "active_id": obj.id, "view_xml": "conv_bal3", } }
def get_payslip(self, context={}): if not context.get('refer_id'): return {} payslip_id = int(context['refer_id']) payslip = self.browse(payslip_id) employee = payslip.employee_id title = employee.title or "" employee_name = "%s. %s %s" % (title.title(), employee.first_name or '', employee.last_name or '') employee_address = get_model('hr.employee').get_address([employee.id]) lines = [] income = [] deduct = [] for line in payslip.lines: type = line.payitem_id.type if type in ('wage', 'allow'): income.append({ 'income': 1, 'item': line.payitem_id.name, 'amount': line.amount, }) else: deduct.append({ 'income': 0, 'item': line.payitem_id.name, 'amount': line.amount, }) range_amt = len(income) if len(income) > len(deduct) else len(deduct) total_deduct = 0.0 total_income = 0.0 for i in range(range_amt): line = {} if i < len(income): item = income[i] total_income += item['amount'] line.update({ 'income_description': item['item'], 'income_amt': item['amount'], 'income_no': i + 1, }) if i < len(deduct): item = deduct[i] total_deduct += item['amount'] line.update({ 'deduct_description': item['item'], 'deduct_amt': item['amount'], 'deduct_no': i + 1, }) lines.append(line) data = { 'ref': payslip.run_id.number, 'date': payslip.date, 'employee_name': employee_name, 'employee_address': employee_address or "Empty Address", 'amount_net': payslip.amount_net, 'total_deduct': total_deduct, 'total_income': total_income, 'lines': lines } comp = get_model('settings').browse(1) if comp.logo: data['logo'] = get_file_path(comp.logo) return data
def get_data_purchase_form(self, context={}): obj_id = int(context["refer_id"]) obj = get_model("purchase.order").browse(obj_id) dbname = database.get_active_db() settings = get_model("settings").browse(1) comp_name = settings.name comp_phone = settings.phone comp_fax = settings.fax comp_addr = settings.get_address_str() comp_tax_no = settings.tax_no contact = obj.contact_id cust_name = contact.name cust_fax = contact.fax cust_phone = contact.phone cust_tax_no = contact.tax_no cust_addr = contact.get_address_str() data = { "comp_name": comp_name, "comp_addr": comp_addr, "comp_phone": comp_phone or "-", "comp_fax": comp_fax or "-", "comp_tax_no": comp_tax_no or "-", "cust_name": cust_name, "cust_addr": cust_addr, "cust_phone": cust_phone or "-", "cust_fax": cust_fax or "-", "cust_tax_no": cust_tax_no or "-", "date": obj.date or "-", "number": obj.number or "-", "ref": obj.ref or "-", "delivery_date": obj.delivery_date or "-", "ship_method": obj.ship_method_id.name or "-", "payment_terms": obj.payment_terms or "-", "lines": [], } index = 0 for line in obj.lines: if line.tax_id: break index += 1 if not index: tax_rate = obj.lines[index].tax_id.rate tax_rate = tax_rate and tax_rate or "0" else: tax_rate = "0" if settings.logo: data["logo"] = get_file_path(settings.logo) for line in obj.lines: data["lines"].append({ "code": line.product_id.code, "description": line.description, "qty": line.qty, "uom": line.uom_id.name, "unit_price": line.unit_price, "tax_rate": line.tax_id.rate, "amount": line.amount, }) data.update({ "amount_subtotal": obj.amount_subtotal, "amount_tax": obj.amount_tax, "amount_total": obj.amount_total, "amount_total_words": utils.num2word(obj.amount_total), "currency_code": obj.currency_id.code, "tax_rate": int(tax_rate), "qty_total": obj.qty_total }) return data
def get_report_data(self, ids=None, context={}): # XXX: deprecated print("invoice.get_report_data") if ids is not None: # for new templates return super().get_report_data(ids, context=context) ids = context["ids"] print("ids", ids, type(ids)) inv_id = ids[0] inv = get_model("account.invoice").browse(inv_id) dbname = database.get_active_db() company = inv.company_id settings = get_model("settings").browse(1) comp_addr = settings.get_address_str() comp_name = company.name comp_phone = settings.phone comp_fax = settings.fax comp_tax_no = settings.tax_no contact = inv.contact_id cust_addr = contact.get_address_str() cust_name = contact.name cust_fax = contact.fax cust_phone = contact.phone cust_tax_no = contact.tax_no data = { "comp_name": comp_name, "comp_addr": comp_addr, "comp_phone": comp_phone or "-", "comp_fax": comp_fax or "-", "comp_tax_no": comp_tax_no or "-", "cust_name": cust_name, "cust_addr": cust_addr, "cust_phone": cust_phone or "-", "cust_fax": cust_fax or "-", "cust_tax_no": cust_tax_no or "-", "date": inv.date or "-", "due_date": inv.due_date or "-", "number": inv.number or "-", "ref": inv.ref or "-", "memo": inv.memo or "", "lines": [], } if settings.logo: data["logo"] = get_file_path(settings.logo) for line in inv.lines: data["lines"].append({ "description": line.description, "code": line.product_id.code, "qty": line.qty, "uom": line.uom_id.name, "unit_price": line.unit_price, "discount": line.discount, "tax_rate": line.tax_id.rate, "amount": line.amount, }) is_cash = 'No' is_cheque = 'No' for obj in inv.payments: account_type = obj.payment_id.account_id.type if account_type in ("bank", "cash"): is_cash = 'Yes' if account_type in ("cheque"): is_cheque = 'Yes' data.update({ "amount_subtotal": inv.amount_subtotal, "amount_discount": inv.amount_discount, "amount_tax": inv.amount_tax, "amount_total": inv.amount_total, "amount_paid": inv.amount_paid, "payment_terms": inv.related_id.payment_terms or "-", "is_cash": is_cash, "is_cheque": is_cheque, "currency_code": inv.currency_id.code, "tax_rate": get_model("currency").round(inv.currency_id.id,inv.amount_tax * 100 / inv.amount_subtotal) if inv.amount_subtotal else 0, "qty_total": inv.qty_total, "memo": inv.memo, }) if inv.credit_alloc: data.update({ "original_inv_subtotal": inv.credit_alloc[0].invoice_id.amount_subtotal, }) return data
def report_render_odt(tmpl_name, data): print("REPORT_RENDER_ODT", tmpl_name, data) try: tmpl_data = get_report_template(tmpl_name, "odt") except: tmpl_data = get_report_template(tmpl_name, "odt2") # XXX tmpl_f = BytesIO(tmpl_data) zf = zipfile.ZipFile(tmpl_f) f_out = BytesIO() zf_out = zipfile.ZipFile(f_out, "w") img_no = 1 add_files = [] for tmpl_fname in ("content.xml", "styles.xml"): getns = { "text": "urn:oasis:names:tc:opendocument:xmlns:text:1.0", "draw": "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", "svg-com": "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", "table": "urn:oasis:names:tc:opendocument:xmlns:table:1.0" } ns_manifest = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" ns_svg = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" f = zf.open(tmpl_fname) tree = etree.parse(f) open("/tmp/odt_template_orig.xml", "w").write(etree.tostring(tree, pretty_print=True).decode()) chunks = get_text_chunks(tree) print("#" * 80) print("CHUNKS", [c[1] for c in chunks]) found_expr = False expr = None expr_pos = [] for i, (p, t) in enumerate(chunks): if i + 1 < len(chunks): next_t = chunks[i + 1][1] else: next_t = None if not found_expr: if t.find("{{") != -1 or next_t and t[-1] == "{" and next_t[0] == "{": found_expr = True expr = "" expr_pos = [] if found_expr: expr += t expr_pos.append(p) if expr.find("}}") != -1: for p in expr_pos: set_pos_text(p, "") set_pos_text(expr_pos[0], expr) print("EXPR", expr) if not check_hbs_expression(expr): raise Exception("Invalid expression: '%s'" % expr) found_expr = False open("/tmp/odt_template_join.xml", "w").write(etree.tostring(tree, pretty_print=True).decode()) chunks = get_text_chunks(tree) blocks = [] level = 0 for p, t in chunks: for expr in re.findall("{{[#/].*?}}", t): if expr[2] == "#": blocks.append((p, expr, level)) level += 1 elif expr[2] == "/": level -= 1 blocks.append((p, expr, level)) print("#" * 80) print("BLOCKS", [(b[1], b[2]) for b in blocks]) pairs = [] for i, (p, t, level) in enumerate(blocks): if t[2] == "#": found = False for p2, t2, level2 in blocks[i + 1:]: if level2 == level: pairs.append((p, t, p2, t2)) found = True break if not found: raise Exception("No closing expression found for %s" % t) print("PAIRS", [(t, t2) for p, t, p2, t2 in pairs]) for p, t, p2, t2 in pairs: if p[0] == p2[0]: continue parent = get_common_parent(p[0], p2[0]) start = stop = None for i, c in enumerate(parent): if check_el_contains(c, p[0]): start = i if check_el_contains(c, p2[0]): stop = i print("relocate pair: '%s' '%s'" % (t, t2)) print(" parent=%s start=%s stop=%s" % (parent, start, stop)) if stop > start + 1: remove_keep_tail(parent, start) remove_keep_tail(parent, stop - 1) if start > 0: parent[start - 1].tail = (parent[start - 1].tail or "") + t else: parent.text = (parent.text or "") + t parent[stop - 2].tail = t2 + (parent[stop - 2].tail or "") open("/tmp/odt_template_block.xml", "w").write(etree.tostring(tree, pretty_print=True).decode()) def _repl(m): var = m.group(1) return "{{{odt_linebreak %s}}}" % var textp = tree.findall(".//*") for textel in textp: if not textel.text: continue if textel.text.find("{{") == -1: continue t = re.sub("{{\s*(\w+)\s*}}", _repl, textel.text) if t != textel.text: textel.text = t doc_tmpl = etree.tostring(tree, pretty_print=True, encoding="unicode") # XXX sometimes they're found as "”" instead of ” doc_tmpl = doc_tmpl.replace("“", "\"") doc_tmpl = doc_tmpl.replace("”", "\"") doc_tmpl = doc_tmpl.replace("“", "\"") doc_tmpl = doc_tmpl.replace("”", "\"") open("/tmp/odt_template_use.xml", "w").write(doc_tmpl) odt_xml = template.render_template(doc_tmpl, data) # XXX open("/tmp/odt_render_out.xml", "w").write(odt_xml) tree = etree.fromstring(odt_xml) for frame_el in tree.findall(".//draw:frame", namespaces={"draw": getns["draw"]}): title_el = frame_el.find("svg:title", namespaces={"svg": ns_svg}) if title_el is not None: fname = title_el.text else: fname = None if not fname: continue img_path = utils.get_file_path(fname) if not os.path.exists(img_path): # XXX continue new_zip_path = "Pictures/_img%d.png" % img_no img_no += 1 image_el = frame_el[0] image_el.attrib['{http://www.w3.org/1999/xlink}href'] = new_zip_path add_files.append((new_zip_path, img_path, "image/png")) cx = frame_el.attrib["{%s}width" % getns["svg-com"]] cy = frame_el.attrib["{%s}height" % getns["svg-com"]] cx_unit = cx[-2] + cx[-1] cx = cx[:-2] cy_unit = cy[-2] + cy[-1] cy = cy[:-2] img = Image.open(img_path) w, h = img.size scale = min(float(cx) / w, float(cy) / h) cx2 = w * scale cy2 = h * scale frame_el.attrib["{%s}width" % getns["svg-com"]] = str(cx2) + cx_unit frame_el.attrib["{%s}height" % getns["svg-com"]] = str(cy2) + cy_unit odt_xml = etree.tostring(tree, pretty_print=True, encoding="unicode") zf_out.writestr(tmpl_fname, odt_xml) print("add_files", add_files) f = zf.open("META-INF/manifest.xml") tree = etree.parse(f) root = tree.getroot() for zip_path, img_path, media_type in add_files: el = etree.Element("{%s}file-entry" % ns_manifest) el.attrib["{%s}full-path" % ns_manifest] = zip_path el.attrib["{%s}media-type" % ns_manifest] = media_type root.append(el) manif_xml = etree.tostring(tree, pretty_print=True, encoding="unicode") zf_out.writestr("META-INF/manifest.xml", manif_xml) out_names = set(zf_out.namelist()) for name in zf.namelist(): if name in out_names: continue data = zf.read(name) zf_out.writestr(name, data) for zip_path, img_path, media_type in add_files: img_data = open(img_path, "rb").read() zf_out.writestr(zip_path, img_data) zf.close() zf_out.close() data = f_out.getvalue() f_out.close() return data
def report_render_odt(tmpl_name, data): print("REPORT_RENDER_ODT", tmpl_name, data) try: tmpl_data = get_report_template(tmpl_name, "odt") except: tmpl_data = get_report_template(tmpl_name, "odt2") # XXX tmpl_f = BytesIO(tmpl_data) zf = zipfile.ZipFile(tmpl_f) f_out = BytesIO() zf_out = zipfile.ZipFile(f_out, "w") img_no = 1 add_files = [] for tmpl_fname in ("content.xml", "styles.xml"): getns = { "text": "urn:oasis:names:tc:opendocument:xmlns:text:1.0", "draw": "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", "svg-com": "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", "table": "urn:oasis:names:tc:opendocument:xmlns:table:1.0" } ns_manifest = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" ns_svg = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" f = zf.open(tmpl_fname) tree = etree.parse(f) open("/tmp/odt_template_orig.xml", "w").write(etree.tostring(tree, pretty_print=True).decode()) chunks = get_text_chunks(tree) print("#" * 80) print("CHUNKS", [c[1] for c in chunks]) found_expr = False expr = None expr_pos = [] for i, (p, t) in enumerate(chunks): if i + 1 < len(chunks): next_t = chunks[i + 1][1] else: next_t = None if not found_expr: if t.find("{{") != -1 or next_t and t[-1] == "{" and next_t[ 0] == "{": found_expr = True expr = "" expr_pos = [] if found_expr: expr += t expr_pos.append(p) if expr.find("}}") != -1: for p in expr_pos: set_pos_text(p, "") set_pos_text(expr_pos[0], expr) print("EXPR", expr) if not check_hbs_expression(expr): raise Exception("Invalid expression: '%s'" % expr) found_expr = False open("/tmp/odt_template_join.xml", "w").write(etree.tostring(tree, pretty_print=True).decode()) chunks = get_text_chunks(tree) blocks = [] level = 0 for p, t in chunks: for expr in re.findall("{{[#/].*?}}", t): if expr[2] == "#": blocks.append((p, expr, level)) level += 1 elif expr[2] == "/": level -= 1 blocks.append((p, expr, level)) print("#" * 80) print("BLOCKS", [(b[1], b[2]) for b in blocks]) pairs = [] for i, (p, t, level) in enumerate(blocks): if t[2] == "#": found = False for p2, t2, level2 in blocks[i + 1:]: if level2 == level: pairs.append((p, t, p2, t2)) found = True break if not found: raise Exception("No closing expression found for %s" % t) print("PAIRS", [(t, t2) for p, t, p2, t2 in pairs]) for p, t, p2, t2 in pairs: if p[0] == p2[0]: continue parent = get_common_parent(p[0], p2[0]) start = stop = None for i, c in enumerate(parent): if check_el_contains(c, p[0]): start = i if check_el_contains(c, p2[0]): stop = i print("relocate pair: '%s' '%s'" % (t, t2)) print(" parent=%s start=%s stop=%s" % (parent, start, stop)) if stop > start + 1: remove_keep_tail(parent, start) remove_keep_tail(parent, stop - 1) if start > 0: parent[start - 1].tail = (parent[start - 1].tail or "") + t else: parent.text = (parent.text or "") + t parent[stop - 2].tail = t2 + (parent[stop - 2].tail or "") open("/tmp/odt_template_block.xml", "w").write(etree.tostring(tree, pretty_print=True).decode()) def _repl(m): var = m.group(1) return "{{{odt_linebreak %s}}}" % var textp = tree.findall(".//*") for textel in textp: if not textel.text: continue if textel.text.find("{{") == -1: continue t = re.sub("{{\s*(\w+)\s*}}", _repl, textel.text) if t != textel.text: textel.text = t doc_tmpl = etree.tostring(tree, pretty_print=True, encoding="unicode") # XXX sometimes they're found as "”" instead of ” doc_tmpl = doc_tmpl.replace("“", "\"") doc_tmpl = doc_tmpl.replace("”", "\"") doc_tmpl = doc_tmpl.replace("“", "\"") doc_tmpl = doc_tmpl.replace("”", "\"") open("/tmp/odt_template_use.xml", "w").write(doc_tmpl) odt_xml = template.render_template(doc_tmpl, data) # XXX open("/tmp/odt_render_out.xml", "w").write(odt_xml) tree = etree.fromstring(odt_xml) for frame_el in tree.findall(".//draw:frame", namespaces={"draw": getns["draw"]}): title_el = frame_el.find("svg:title", namespaces={"svg": ns_svg}) if title_el is not None: fname = title_el.text else: fname = None if not fname: continue img_path = utils.get_file_path(fname) if not os.path.exists(img_path): # XXX continue new_zip_path = "Pictures/_img%d.png" % img_no img_no += 1 image_el = frame_el[0] image_el.attrib[ '{http://www.w3.org/1999/xlink}href'] = new_zip_path add_files.append((new_zip_path, img_path, "image/png")) cx = frame_el.attrib["{%s}width" % getns["svg-com"]] cy = frame_el.attrib["{%s}height" % getns["svg-com"]] cx_unit = cx[-2] + cx[-1] cx = cx[:-2] cy_unit = cy[-2] + cy[-1] cy = cy[:-2] img = Image.open(img_path) w, h = img.size scale = min(float(cx) / w, float(cy) / h) cx2 = w * scale cy2 = h * scale frame_el.attrib["{%s}width" % getns["svg-com"]] = str(cx2) + cx_unit frame_el.attrib["{%s}height" % getns["svg-com"]] = str(cy2) + cy_unit odt_xml = etree.tostring(tree, pretty_print=True, encoding="unicode") zf_out.writestr(tmpl_fname, odt_xml) print("add_files", add_files) f = zf.open("META-INF/manifest.xml") tree = etree.parse(f) root = tree.getroot() for zip_path, img_path, media_type in add_files: el = etree.Element("{%s}file-entry" % ns_manifest) el.attrib["{%s}full-path" % ns_manifest] = zip_path el.attrib["{%s}media-type" % ns_manifest] = media_type root.append(el) manif_xml = etree.tostring(tree, pretty_print=True, encoding="unicode") zf_out.writestr("META-INF/manifest.xml", manif_xml) out_names = set(zf_out.namelist()) for name in zf.namelist(): if name in out_names: continue data = zf.read(name) zf_out.writestr(name, data) for zip_path, img_path, media_type in add_files: img_data = open(img_path, "rb").read() zf_out.writestr(zip_path, img_data) zf.close() zf_out.close() data = f_out.getvalue() f_out.close() return data
def do_import(self, ids, context={}): print("import modules") obj = self.browse(ids)[0] path = utils.get_file_path(obj.file) zf = zipfile.ZipFile(path, "r") modules = {} for n in zf.namelist(): if not n.endswith("/module.json"): continue path = n[:-len("/module.json")] data = zf.read(n).decode() vals = json.loads(data) name = vals["name"] module = { "name": name, "path": path, "info": vals, "model_files": [], "layout_files": [], "action_files": [], "template_files": [], "script_files": [], } modules[name] = module if not modules: raise Exception("No modules found") print("modules", modules.keys()) ids = get_model("module").search([["name", "in", modules.keys()]]) get_model("module").delete_modules(ids) for name, module in modules.items(): info = module["info"] vals = { "name": name, "description": info.get("description"), "version": info.get("version"), "author": info.get("author"), } get_model("module").create(vals) for path in zf.namelist(): found = False for name, module in modules.items(): if path.startswith(module["path"] + "/"): path2 = path[len(module["path"]) + 1:] module = modules[name] found = True break if not found: continue if path2.startswith("models/") and path2.endswith(".xml"): module["model_files"].append(path) elif path2.startswith("layouts/") and path2.endswith(".xml"): module["layout_files"].append(path) elif path2.startswith("actions/") and path2.endswith(".json"): module["action_files"].append(path) elif path2.startswith("templates/") and path2.endswith(".hbs"): module["template_files"].append(path) elif path2.startswith("scripts/") and path2.endswith(".js"): module["script_files"].append(path) for mod_name, module in modules.items(): for path in module["model_files"]: print("import model", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() root = etree.fromstring(data) vals = { "name": root.attrib["name"], "module_id": get_model("module").get(mod_name, require=True), } if root.attrib.get("string"): vals["string"] = root.attrib["string"] if root.attrib.get("description"): # XXX vals["description"] = root.attrib["description"] res = get_model("model").search([["name", "=", vals["name"]]]) if res: model_id = res[0] get_model("model").write([model_id], vals) else: model_id = get_model("model").create(vals) def _import_field(el, model, mod_name): vals = { "model_id": get_model("model").get(model, require=True), "module_id": get_model("module").get(mod_name, require=True), "name": el.attrib["name"], "string": el.attrib["string"], "type": el.attrib["type"], } if el.attrib.get("relation"): vals["relation_id"] = get_model("model").get(el.attrib["relation"], require=True) if el.attrib.get("relfield"): vals["relfield_id"] = get_model("field").find_field(el.attrib["relation"], el.attrib["relfield"]) if el.attrib.get("selection"): vals["selection"] = el.attrib["selection"] if el.attrib.get("required"): vals["required"] = True if el.attrib.get("readonly"): vals["readonly"] = True if el.attrib.get("function"): vals["function"] = el.attrib["function"] if el.attrib.get("default"): vals["default"] = el.attrib["default"] if el.attrib.get("search"): vals["search"] = True if el.attrib.get("condition"): vals["condition"] = el.attrib["condition"] if el.attrib.get("description"): vals["description"] = el.attrib["description"] get_model("field").create(vals) for mod_name, module in modules.items(): for path in module["model_files"]: print("import fields #1", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() root = etree.fromstring(data) for el in root: if el.tag != "field": continue if el.attrib.get("relfield"): continue _import_field(el, root.attrib["name"], mod_name) for mod_name, module in modules.items(): for path in module["model_files"]: print("import fields #2", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() root = etree.fromstring(data) for el in root: if el.tag != "field": continue if not el.attrib.get("relfield"): continue _import_field(el, root.attrib["name"], mod_name) for mod_name, module in modules.items(): for path in module["layout_files"]: print("import layout", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() root = etree.fromstring(data) vals = { "name": n, "module_id": get_model("module").get(mod_name, require=True), "type": root.tag.lower(), } if root.attrib.get("model"): vals["model_id"] = get_model("model").get(root.attrib["model"], require=True) del root.attrib["model"] if root.attrib.get("inherit"): vals["inherit"] = root.attrib["inherit"] del root.attrib["inherit"] vals["layout"] = etree.tostring(root, pretty_print=True).decode() get_model("view.layout").create(vals) for mod_name, module in modules.items(): for path in module["action_files"]: print("import action", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() vals = json.loads(data) vals2 = { "name": n, "module_id": get_model("module").get(mod_name, require=True), } if vals.get("string"): vals2["string"] = vals["string"] if vals.get("view"): vals2["view"] = vals["view"] if vals.get("model"): vals2["model_id"] = get_model("model").get(vals["model"], require=True) if vals.get("view_layout"): vals2["view_layout_id"] = get_model("view.layout").get(vals["view_layout"], require=True) if vals.get("menu"): vals2["menu_id"] = get_model("view.layout").get(vals["menu"], require=True) if vals.get("options"): vals2["options"] = json.dumps(vals["options"]) get_model("action").create(vals2) for mod_name, module in modules.items(): for path in module["template_files"]: print("import template", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() vals = { "name": n, "module_id": get_model("module").get(mod_name, require=True), "template": data, } get_model("template").create(vals) for mod_name, module in modules.items(): for path in module["script_files"]: print("import script", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() vals = { "name": n, "module_id": get_model("module").get(mod_name, require=True), "code": data, } get_model("script").create(vals) return { "next": { "name": "module", }, "flash": "Modules imported successfully", }
def report_render_doc(tmpl_name, data): # Do they delete the newline thing print("report_render_doc", tmpl_name, data) tmpl_data = get_report_template(tmpl_name, "docx") tmpl_f = BytesIO(tmpl_data) zf = zipfile.ZipFile(tmpl_f) ns = "http://schemas.openxmlformats.org/package/2006/relationships" f = zf.open("word/_rels/document.xml.rels") tree = etree.parse(f) rels = {} for el in tree.findall(".//ns:Relationship", namespaces={"ns": ns}): rels[el.attrib.get("Id")] = el.attrib.get("Target") print("rels", rels) ns = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" f = zf.open("word/document.xml") tree = etree.parse(f) print("*** DOC_SRC *********************") print(etree.tostring(tree, pretty_print=True).decode()) for el in tree.iterfind(".//w:p", namespaces={"w": ns}): vals = [] start = False parent = el children = el.findall(".//w:r", namespaces={"w": ns}) vals = [] for child in children: grandchild = child.findall(".//w:t", namespaces={"w": ns}) if grandchild and grandchild[0].text: text = grandchild[0].text if text and (text.find("{{") != -1 or text.find("}}") != -1 or start): vals.append((text, child, grandchild[0])) start = False if text.find("}}") != -1 and not ( text.find("{{") != -1) else True text = "".join([text for text, c, g in vals]) for i, val in enumerate(vals): if i == 0: val[2].text = text else: parent.remove(val[1]) images = {} change_list = [] change_list.append("word/document.xml") for el in tree.iterfind(".//w:tc", namespaces={"w": ns}): expr = el.xpath("string()") if expr and expr.find("{{image") != -1: expr = expr.replace("\u201c", "\"") # XXX expr = expr.replace("\u201d", "\"") m = re.search("{{image \"(.*?)\"", expr) if not m: raise Exception("Failed to parse image expression: %s" % expr) n = m.group(1) v = data.get(n) if v: res = el.findall(".//w:drawing", namespaces={"w": ns}) if not res: raise Exception("Failed to replace image") el_drawing = res[0] el_blip = el_drawing.find( ".//a:blip", namespaces={ "a": "http://schemas.openxmlformats.org/drawingml/2006/main" }) embed = el_blip.attrib[ "{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed"] zip_path = rels[embed] change_list.append("word/" + zip_path) images[zip_path] = v el_extent = el_drawing.find( ".//wp:extent", namespaces={ "wp": "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" }) cx = int(el_extent.attrib["cx"]) cy = int(el_extent.attrib["cy"]) img_path = utils.get_file_path(v) img = Image.open(img_path) w, h = img.size scale = min(float(cx) / w, float(cy) / h) cx2 = int(round(w * scale)) cy2 = int(round(h * scale)) el_extent.attrib["cx"] = str(cx2) el_extent.attrib["cy"] = str(cy2) el_ext = el_drawing.find( ".//a:ext", namespaces={ "a": "http://schemas.openxmlformats.org/drawingml/2006/main" }) el_ext.attrib["cx"] = str(cx2) el_ext.attrib["cy"] = str(cy2) wts = el.findall(".//w:t", namespaces={"w": ns}) for wt in wts: if wt.text and wt.text.find("{{image") != -1: parent = wt.getparent() grandparent = parent.getparent() grandparent.remove(parent) for el in tree.iterfind(".//w:t", namespaces={"w": ns}): expr = el.text if expr.find("{{#") != -1 or expr.find("{{/") != -1: el_tr = el.getparent() while not el_tr.tag.endswith("}tr"): el_tr = el_tr.getparent() p = el_tr.getparent() # XXX if p: i = p.index(el_tr) p.remove(el_tr) p[i - 1].tail = expr doc_tmpl = etree.tostring(tree, pretty_print=True, encoding="unicode") doc_tmpl = doc_tmpl.replace("“", "\"") doc_tmpl = doc_tmpl.replace("”", "\"") doc_tmpl = doc_tmpl.replace("\u201c", "\"") doc_tmpl = doc_tmpl.replace("\u201d", "\"") print("*** DOC_TMPL *********************") for i, l in enumerate(doc_tmpl.split("\n")): print(i + 1, l) doc_xml = template.render_template(doc_tmpl, data) f_out = BytesIO() zf_out = zipfile.ZipFile(f_out, "w") for name in zf.namelist(): print("XXX", name) if name in change_list: pass else: data = zf.read(name) zf_out.writestr(name, data) for zip_path, v in images.items(): img_path = utils.get_file_path(v) img_data = open(img_path, "rb").read() zf_out.writestr("word/" + zip_path, img_data) zf_out.writestr("word/document.xml", doc_xml) zf.close() zf_out.close() data = f_out.getvalue() f_out.close() return data
def get_data_sale_form(self, context={}): obj_id = int(context["refer_id"]) obj = get_model("sale.order").browse(obj_id) dbname = database.get_active_db() settings = get_model("settings").browse(1) comp_name = settings.name comp_phone = settings.phone comp_fax = settings.fax comp_addr = settings.get_address_str() comp_tax_no = settings.tax_no contact = obj.contact_id cust_name = contact.name cust_fax = contact.fax cust_phone = contact.phone cust_tax_no = contact.tax_no cust_addr = contact.get_address_str() data = { "comp_name": comp_name, "comp_addr": comp_addr, "comp_phone": comp_phone or "-", "comp_fax": comp_fax or "-", "comp_tax_no": comp_tax_no or "-", "cust_name": cust_name, "cust_addr": cust_addr, "cust_phone": cust_phone or "-", "cust_fax": cust_fax or "-", "cust_tax_no": cust_tax_no or "-", "date": obj.date or "-", "number": obj.number or "-", "ref": obj.ref or "-", "delivery_date": obj.delivery_date or "-", "ship_method": obj.ship_method_id.name or "-", "payment_terms": obj.payment_terms or "-", "lines": [], } index = 0 item = 0 for line in obj.lines: if line.tax_id: break index += 1 if not index: tax_rate = obj.lines[index].tax_id.rate tax_rate = tax_rate and tax_rate or "0" else: tax_rate = "0" if settings.logo: data["logo"] = get_file_path(settings.logo) for line in obj.lines: item += 1 data["lines"].append({ "item": item, "code": line.product_id.code, "name": line.product_id.name or "-", "description": line.description, "qty": line.qty, "uom": line.uom_id.name, "unit_price": line.unit_price, "tax_rate": line.tax_id.rate, "amount": line.amount, }) data.update({ "amount_subtotal": obj.amount_subtotal, "amount_tax": obj.amount_tax, "amount_total": obj.amount_total, "amount_total_words": utils.num2word(obj.amount_total), "other_info": obj.other_info or "-", "currency_code": obj.currency_id.code, "tax_rate": int(tax_rate), "qty_total": obj.qty_total }) return data
def do_import(self, ids, context={}): print("import modules") obj = self.browse(ids)[0] path = utils.get_file_path(obj.file) zf = zipfile.ZipFile(path, "r") modules = {} for n in zf.namelist(): if not n.endswith("/module.json"): continue path = n[:-len("/module.json")] data = zf.read(n).decode() vals = json.loads(data) name = vals["name"] module = { "name": name, "path": path, "info": vals, "model_files": [], "layout_files": [], "action_files": [], "template_files": [], "script_files": [], } modules[name] = module if not modules: raise Exception("No modules found") print("modules", modules.keys()) ids = get_model("module").search([["name", "in", modules.keys()]]) get_model("module").delete_modules(ids) for name, module in modules.items(): info = module["info"] vals = { "name": name, "description": info.get("description"), "version": info.get("version"), "author": info.get("author"), } get_model("module").create(vals) for path in zf.namelist(): found = False for name, module in modules.items(): if path.startswith(module["path"] + "/"): path2 = path[len(module["path"]) + 1:] module = modules[name] found = True break if not found: continue if path2.startswith("models/") and path2.endswith(".xml"): module["model_files"].append(path) elif path2.startswith("layouts/") and path2.endswith(".xml"): module["layout_files"].append(path) elif path2.startswith("actions/") and path2.endswith(".json"): module["action_files"].append(path) elif path2.startswith("templates/") and path2.endswith(".hbs"): module["template_files"].append(path) elif path2.startswith("scripts/") and path2.endswith(".js"): module["script_files"].append(path) for mod_name, module in modules.items(): for path in module["model_files"]: print("import model", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() root = etree.fromstring(data) vals = { "name": root.attrib["name"], "module_id": get_model("module").get(mod_name, require=True), } if root.attrib.get("string"): vals["string"] = root.attrib["string"] if root.attrib.get("description"): # XXX vals["description"] = root.attrib["description"] res = get_model("model").search([["name", "=", vals["name"]]]) if res: model_id = res[0] get_model("model").write([model_id], vals) else: model_id = get_model("model").create(vals) def _import_field(el, model, mod_name): vals = { "model_id": get_model("model").get(model, require=True), "module_id": get_model("module").get(mod_name, require=True), "name": el.attrib["name"], "string": el.attrib["string"], "type": el.attrib["type"], } if el.attrib.get("relation"): vals["relation_id"] = get_model("model").get( el.attrib["relation"], require=True) if el.attrib.get("relfield"): vals["relfield_id"] = get_model("field").find_field( el.attrib["relation"], el.attrib["relfield"]) if el.attrib.get("selection"): vals["selection"] = el.attrib["selection"] if el.attrib.get("required"): vals["required"] = True if el.attrib.get("readonly"): vals["readonly"] = True if el.attrib.get("function"): vals["function"] = el.attrib["function"] if el.attrib.get("default"): vals["default"] = el.attrib["default"] if el.attrib.get("search"): vals["search"] = True if el.attrib.get("condition"): vals["condition"] = el.attrib["condition"] if el.attrib.get("description"): vals["description"] = el.attrib["description"] get_model("field").create(vals) for mod_name, module in modules.items(): for path in module["model_files"]: print("import fields #1", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() root = etree.fromstring(data) for el in root: if el.tag != "field": continue if el.attrib.get("relfield"): continue _import_field(el, root.attrib["name"], mod_name) for mod_name, module in modules.items(): for path in module["model_files"]: print("import fields #2", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() root = etree.fromstring(data) for el in root: if el.tag != "field": continue if not el.attrib.get("relfield"): continue _import_field(el, root.attrib["name"], mod_name) for mod_name, module in modules.items(): for path in module["layout_files"]: print("import layout", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() root = etree.fromstring(data) vals = { "name": n, "module_id": get_model("module").get(mod_name, require=True), "type": root.tag.lower(), } if root.attrib.get("model"): vals["model_id"] = get_model("model").get( root.attrib["model"], require=True) del root.attrib["model"] if root.attrib.get("inherit"): vals["inherit"] = root.attrib["inherit"] del root.attrib["inherit"] vals["layout"] = etree.tostring(root, pretty_print=True).decode() get_model("view.layout").create(vals) for mod_name, module in modules.items(): for path in module["action_files"]: print("import action", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() vals = json.loads(data) vals2 = { "name": n, "module_id": get_model("module").get(mod_name, require=True), } if vals.get("string"): vals2["string"] = vals["string"] if vals.get("view"): vals2["view"] = vals["view"] if vals.get("model"): vals2["model_id"] = get_model("model").get(vals["model"], require=True) if vals.get("view_layout"): vals2["view_layout_id"] = get_model("view.layout").get( vals["view_layout"], require=True) if vals.get("menu"): vals2["menu_id"] = get_model("view.layout").get( vals["menu"], require=True) if vals.get("options"): vals2["options"] = json.dumps(vals["options"]) get_model("action").create(vals2) for mod_name, module in modules.items(): for path in module["template_files"]: print("import template", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() vals = { "name": n, "module_id": get_model("module").get(mod_name, require=True), "template": data, } get_model("template").create(vals) for mod_name, module in modules.items(): for path in module["script_files"]: print("import script", path) n = os.path.splitext(os.path.basename(path))[0] data = zf.read(path).decode() vals = { "name": n, "module_id": get_model("module").get(mod_name, require=True), "code": data, } get_model("script").create(vals) return { "next": { "name": "module", }, "flash": "Modules imported successfully", }
def report_render_doc(tmpl_name, data): # Do they delete the newline thing print("report_render_doc", tmpl_name, data) tmpl_data = get_report_template(tmpl_name, "docx") tmpl_f = BytesIO(tmpl_data) zf = zipfile.ZipFile(tmpl_f) ns = "http://schemas.openxmlformats.org/package/2006/relationships" f = zf.open("word/_rels/document.xml.rels") tree = etree.parse(f) rels = {} for el in tree.findall(".//ns:Relationship", namespaces={"ns": ns}): rels[el.attrib.get("Id")] = el.attrib.get("Target") print("rels", rels) ns = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" f = zf.open("word/document.xml") tree = etree.parse(f) print("*** DOC_SRC *********************") print(etree.tostring(tree, pretty_print=True).decode()) for el in tree.iterfind(".//w:p", namespaces={"w": ns}): vals = [] start = False parent = el children = el.findall(".//w:r", namespaces={"w": ns}) vals = [] for child in children: grandchild = child.findall(".//w:t", namespaces={"w": ns}) if grandchild and grandchild[0].text: text = grandchild[0].text if text and (text.find("{{") != -1 or text.find("}}") != -1 or start): vals.append((text, child, grandchild[0])) start = False if text.find("}}") != -1 and not (text.find("{{") != -1) else True text = "".join([text for text, c, g in vals]) for i, val in enumerate(vals): if i == 0: val[2].text = text else: parent.remove(val[1]) images = {} change_list = [] change_list.append("word/document.xml") for el in tree.iterfind(".//w:tc", namespaces={"w": ns}): expr = el.xpath("string()") if expr and expr.find("{{image") != -1: expr = expr.replace("\u201c", "\"") # XXX expr = expr.replace("\u201d", "\"") m = re.search("{{image \"(.*?)\"", expr) if not m: raise Exception("Failed to parse image expression: %s" % expr) n = m.group(1) v = data.get(n) if v: res = el.findall(".//w:drawing", namespaces={"w": ns}) if not res: raise Exception("Failed to replace image") el_drawing = res[0] el_blip = el_drawing.find( ".//a:blip", namespaces={"a": "http://schemas.openxmlformats.org/drawingml/2006/main"}) embed = el_blip.attrib["{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed"] zip_path = rels[embed] change_list.append("word/" + zip_path) images[zip_path] = v el_extent = el_drawing.find( ".//wp:extent", namespaces={"wp": "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"}) cx = int(el_extent.attrib["cx"]) cy = int(el_extent.attrib["cy"]) img_path = utils.get_file_path(v) img = Image.open(img_path) w, h = img.size scale = min(float(cx) / w, float(cy) / h) cx2 = int(round(w * scale)) cy2 = int(round(h * scale)) el_extent.attrib["cx"] = str(cx2) el_extent.attrib["cy"] = str(cy2) el_ext = el_drawing.find( ".//a:ext", namespaces={"a": "http://schemas.openxmlformats.org/drawingml/2006/main"}) el_ext.attrib["cx"] = str(cx2) el_ext.attrib["cy"] = str(cy2) wts = el.findall(".//w:t", namespaces={"w": ns}) for wt in wts: if wt.text and wt.text.find("{{image") != -1: parent = wt.getparent() grandparent = parent.getparent() grandparent.remove(parent) for el in tree.iterfind(".//w:t", namespaces={"w": ns}): expr = el.text if expr.find("{{#") != -1 or expr.find("{{/") != -1: el_tr = el.getparent() while not el_tr.tag.endswith("}tr"): el_tr = el_tr.getparent() p = el_tr.getparent() # XXX if p: i = p.index(el_tr) p.remove(el_tr) p[i - 1].tail = expr doc_tmpl = etree.tostring(tree, pretty_print=True, encoding="unicode") doc_tmpl = doc_tmpl.replace("“", "\"") doc_tmpl = doc_tmpl.replace("”", "\"") doc_tmpl = doc_tmpl.replace("\u201c", "\"") doc_tmpl = doc_tmpl.replace("\u201d", "\"") print("*** DOC_TMPL *********************") for i, l in enumerate(doc_tmpl.split("\n")): print(i + 1, l) doc_xml = template.render_template(doc_tmpl, data) f_out = BytesIO() zf_out = zipfile.ZipFile(f_out, "w") for name in zf.namelist(): print("XXX", name) if name in change_list: pass else: data = zf.read(name) zf_out.writestr(name, data) for zip_path, v in images.items(): img_path = utils.get_file_path(v) img_data = open(img_path, "rb").read() zf_out.writestr("word/" + zip_path, img_data) zf_out.writestr("word/document.xml", doc_xml) zf.close() zf_out.close() data = f_out.getvalue() f_out.close() return data