class ProductBrand(Model): _name = "product.brand" _string = "Brand" _fields = { "name": fields.Char("Name", required=True, search=True), "description": fields.Text("Description", search=True), "image": fields.File("Image"), "code": fields.Char("Code"), "parent_id": fields.Many2One("product.brand","Parent Brand"), "sub_brands": fields.One2Many("product.brand","parent_id","Sub Brands"), "products": fields.One2Many("product","brand_id","Products", operator="child_of"), "num_products": fields.Integer("Number of products", function="get_num_products"), "groups": fields.Many2Many("product.brand.group","Group"), } _order = "name" def get_num_products(self, ids, context={}): vals = {} for obj in self.browse(ids): nums = 0 for product in obj.products: if not product.parent_id: nums += 1 vals[obj.id] = nums return vals
class Profile(Model): _name = "profile" _string = "Profile" _key = ["name"] _fields = { "name": fields.Char("Name", required=True, search=True), "code": fields.Char("Short Code"), "perms": fields.One2Many("profile.access", "profile_id", "Model Permissions"), "field_perms": fields.One2Many("field.access", "profile_id", "Field Permissions"), "menu_perms": fields.One2Many("menu.access", "profile_id", "Menu Permissions"), "other_perms": fields.Many2Many("permission", "Other Permissions"), "home_action": fields.Char("Login Action"), "login_company_id": fields.Many2One("company", "Login Company"), "prevent_login": fields.Boolean("Prevent Login"), "comments": fields.One2Many("message", "related_id", "Comments"), "default_model_perms": fields.Selection([["full", "Full Access"], ["readonly","Read-only Access"], ["no", "No Access"]], "Default Model Permissions"), "default_menu_access": fields.Selection([["visible", "Visible"], ["hidden", "Hidden"]], "Default Menu Access"), } _order = "name" _defaults = { "default_model_perms": "full", } def get_data(self, context={}): vals = {} perms = [] for m in get_model("model").search_browse([]): perms.append({ "model_id": [m.id, m.string], }) vals["perms"] = perms return vals def copy(self, ids, context={}): obj = self.browse(ids)[0] vals = { "name": obj.name + " (Copy)", "perms": [], "other_perms": [("set", [p.id for p in obj.other_perms])], "home_action": obj.home_action, } for perm in obj.perms: vals["perms"].append(("create", { "model_id": perm.model_id.id, "perm_read": perm.perm_read, "perm_create": perm.perm_create, "perm_write": perm.perm_write, "perm_delete": perm.perm_delete, "view_all": perm.view_all, "modif_all": perm.modif_all, })) profile_id = get_model("profile").create(vals) return { "next": { "name": "profile", "mode": "form", "active_id": profile_id, }, "flash": "New profile created", }
class Product(Model): _inherit = "product" _fields = { "review": fields.One2Many("ecom.product.review", "product_id", "Product Review"), "wishlist": fields.One2Many("ecom.wishlist", "product_id", "Wishlist"), "has_sample": fields.Boolean("Has Sample", function="check_sample"), "avg_rate": fields.Integer("Average Rating", function="get_rating"), } def check_sample(self, ids, context={}): vals = {} for obj in self.browse(ids): product = obj sample = False for img in product.images: if img.title: if "SAMPLE_OPTS_" in img.title: sample = True vals[obj.id] = sample return vals def get_rating(self, ids, context={}): vals = {} for obj in self.browse(ids): score = [] for review in get_model("ecom.product.review").search_browse( [["product_id", "=", obj.id], ["state", "=", "approved"]]): score.append(int(review.rating or 0)) vals[obj.id] = sum(score) / len(score) if score else 0 return vals
class Page(Model): _name = "cms.page" _string = "Page" _name_field = "title" _fields = { "title": fields.Char("Title", required=True, translate=True, search=True), "code": fields.Char("Code", required=True, search=True), "body": fields.Text("Body", translate=True), "blocks": fields.One2Many("cms.block", "related_id", "Blocks"), "comments": fields.One2Many("message", "related_id", "Comments"), "meta_description": fields.Char("Meta Description"), "meta_keywords": fields.Char("Meta Keywords"), "template": fields.Char("Template"), "state": fields.Selection([["active", "Active"], ["inactive", "Inactive"]], "Status", required=True), } _defaults = { "state": "active", }
class ProductionPeriod(Model): _name = "production.period" _string = "Production Period" _name_field = "number" _fields = { "number": fields.Char("Number", required=True, search=True), "date_from": fields.Date("Date From", required=True), "date_to": fields.Date("Date To", required=True), "production_orders": fields.One2Many("production.order", "period_id", "Production Orders"), "costs": fields.One2Many("production.period.cost", "period_id", "Period Costs"), "amount_total": fields.Decimal("Period Actual Total", function="get_total", function_multi=True), "alloc_total": fields.Decimal("Production Order Total", function="get_total", function_multi=True), } def update_period_costs(self, ids, context={}): obj = self.browse(ids)[0] cost_prod_ids = [] for cost in get_model("production.cost").search_browse( [["order_id.period_id", "=", obj.id]]): prod_id = cost.product_id.id cost_prod_ids.append(prod_id) cost_prod_ids = list(set(cost_prod_ids)) cur_prod_ids = [c.product_id.id for c in obj.costs] new_prod_ids = [ prod_id for prod_id in cost_prod_ids if prod_id not in cur_prod_ids ] for prod_id in new_prod_ids: vals = { "period_id": obj.id, "product_id": prod_id, "amount": 0, } get_model("production.period.cost").create(vals) def get_total(self, ids, context={}): vals = {} for obj in self.browse(ids): amt = 0 alloc = 0 for cost in obj.costs: amt += cost.amount or 0 alloc += cost.alloc_amount or 0 vals[obj.id] = { "amount_total": amt, "alloc_total": alloc, } return vals
class BankReconcile(Model): _name = "account.bank.reconcile" _string = "Bank Reconciliation" _name_field = "number" _fields = { "account_lines": fields.One2Many("account.move.line", "bank_reconcile_id", "Account Entries"), "statement_lines": fields.One2Many("account.statement.line", "bank_reconcile_id", "Statement Lines"), "total_account": fields.Decimal("Total Account", function="get_total", function_multi=True), "total_statement": fields.Decimal("Total Statement", function="get_total", function_multi=True), "number": fields.Char("Number", function="get_total", function_multi=True), } def get_total(self, ids, context={}): vals = {} for obj in self.browse(ids): total_account = 0 total_statement = 0 for line in obj.account_lines: total_account += line.debit - line.credit for line in obj.statement_lines: total_statement += line.received - line.spent number = "R%d" % obj.id if abs(total_account - total_statement) > 0: number += "*" vals[obj.id] = { "total_account": total_account, "total_statement": total_statement, "number": number, } return vals def delete(self, ids, **kw): st_line_ids = [] move_line_ids = [] for obj in self.browse(ids): for st_line in obj.statement_lines: st_line_ids.append(st_line.id) for move_line in obj.account_lines: move_line_ids.append(move_line.id) st_line_ids = list(set(st_line_ids)) move_line_ids = list(set(move_line_ids)) get_model("account.statement.line").write(st_line_ids, {"state": "not_reconciled"}) get_model("account.move.line").write(move_line_ids, {"state": "not_reconciled"}) super().delete(ids, **kw)
class Country(Model): _name = "country" _string = "Country" _key = ["name"] _fields = { "name": fields.Char("Name", required=True, search=True, translate=True), "code": fields.Char("Code", search=True), "provinces": fields.One2Many("province", "country_id", "Provinces"), "postal_codes": fields.One2Many("postal.code", "country_id", "Postal Codes"), } _order = "name"
class Competitor(Model): _name = "competitor" _string = "Competitor" _fields = { "name": fields.Char("Name", required=True, search=True), "contact_id": fields.Many2One("contact", "Contact"), "opports": fields.One2Many("opport.compet", "compet_id", "Opportunities"), "comments": fields.One2Many("message", "related_id", "Comments"), } _order = "name"
class QCTest(Model): _name = "qc.test" _string = "QC Test" _fields = { "name": fields.Char("Test Name", search=True, required=True), "description": fields.Text("Description"), "min_value": fields.Decimal("Minimum Value"), "max_value": fields.Decimal("Maximum Value"), "comments": fields.One2Many("message", "related_id", "Comments"), "documents": fields.One2Many("document", "related_id", "Documents"), } _order = "name"
class DocumentCateg(Model): _name = "document.categ" _string = "Document Category" _name_field = "full_name" _fields = { "name": fields.Char("Category Name", required=True, search=True), "code": fields.Char("Document Code", search=True), "full_name": fields.Char("Category Name", function="get_full_name", search=True, store=True, size=256), "parent_id": fields.Many2One("document.categ", "Parent Category"), "description": fields.Text("Description", search=True), "comments": fields.One2Many("message", "related_id", "Comments"), "expire_after": fields.Char("Expire After"), "file_name": fields.Char("Filename Format"), "reminder_templates": fields.One2Many("reminder.template", "doc_categ_id", "Reminder Templates"), } _order = "full_name" _constraints = ["_check_cycle"] def create(self, vals, **kw): new_id = super().create(vals, **kw) self.function_store([new_id]) return new_id def write(self, ids, vals, **kw): super().write(ids, vals, **kw) child_ids = self.search(["id", "child_of", ids]) self.function_store(child_ids) def get_full_name(self, ids, context={}): vals = {} for obj in self.browse(ids): names = [obj.name] p = obj.parent_id while p: names.append(p.name) p = p.parent_id full_name = " / ".join(reversed(names)) vals[obj.id] = full_name return vals
class Account(Model): _name = "email.account" _string = "Email Account" _name_field = "name" _fields = { "name": fields.Char("Account Name", required=True, search=True), "type": fields.Selection([["imap", "IMAP"], ["pop", "POP"], ["smtp", "SMTP"], ["mailgun", "Mailgun"]], "Type", required=True, search=True), "host": fields.Char("Host", required=True), "port": fields.Integer("Port"), "user": fields.Char("User"), "password": fields.Char("Password"), "security": fields.Selection([["starttls", "STARTTLS"], ["ssl", "SSL"]], "Security"), "comments": fields.One2Many("message", "related_id", "Comments"), "mailboxes": fields.One2Many("email.mailbox", "account_id", "Mailboxes"), } def list_imap_mailboxes(self, ids, context={}): print("fetch_emails_imap", ids) obj = self.browse(ids)[0] if obj.type != "imap": raise Exception("Invalid email account type") if obj.security == "ssl": serv = imaplib.IMAP4_SSL(host=obj.host, port=obj.port or 993) else: serv = imaplib.IMAP4(host=obj.host, port=obj.port or 143) serv.login(obj.user, obj.password) res = serv.list() if res[0] != "OK": raise Exception("Invalid IMAP response") return { "next": { "name": "email_account", "mode": "form", "active_id": obj.id, }, "flash": "Mailboxes found on IMAP server: " + ", ".join(m.decode() for m in res[1]), }
class DocumentTmpl(Model): _name = "document.tmpl" _string = "Document Template" _fields = { "file": fields.File("File"), "categ_id": fields.Many2One("document.categ", "Category", required=True, search=True), "description": fields.Text("Description", search=True), "date": fields.Date("Date", required=True, search=True), "attachments": fields.One2Many("attach", "related_id", "Attachments"), "comments": fields.One2Many("message", "related_id", "Comments"), } _defaults = { "date": lambda *a: time.strftime("%Y-%m-%d"), }
class Contact(Model): _inherit = "contact" _fields = { "wishlist": fields.One2Many("ecom.wishlist", "contact_id", "Wishlist"), "wishlist_count": fields.Integer("Wishlist Count", function="count_wishlist"), } def count_wishlist(self, ids, context={}): db = get_connection() try: vals = {} for obj in self.browse(ids): contact_id = obj.id res = db.query( "SELECT COUNT(*) FROM ecom_wishlist WHERE contact_id = %s" % contact_id) res = res[0]['count'] or 0 vals[obj.id] = res return vals except: import traceback traceback.print_exc() db.rollback()
class Rule(Model): _name = "wkf.rule" _string = "Workflow Rule" _name_field = "description" _fields = { "trigger_model_id": fields.Many2One("model", "Trigger Model", required=True, search=True), "trigger_event": fields.Char("Trigger Event", required=True, search=True), "condition_method": fields.Char("Condition Method"), "condition_args": fields.Text("Condition Arguments"), "action_model_id": fields.Many2One("model", "Action Model", required=True, search=True), "action_method": fields.Char("Action Method", required=True), "action_args": fields.Text("Action Arguments"), "description": fields.Text("Rule Description", search=True), "comments": fields.One2Many("message", "related_id", "Comments"), "state": fields.Selection([["active", "Active"], ["inactive", "Inactive"]], "Status", required=True, search=True), "error": fields.Text("Error Message"), } _order = "trigger_model_id.name,trigger_event,action_model_id.name,action_method" _defaults = { "state": "active", }
class CustomOption(Model): _name = "product.custom.option" _string = "Custom Option" _key = ["code"] _fields = { "name": fields.Char("Name", required=True, search=True, translate=True), "seq": fields.Char("Sequence", required=True), "code": fields.Char("Code", search=True), "type": fields.Selection([["text", "Text"], ["selection", "Selection"]], "Type", required=True), "required": fields.Boolean("Required"), "description": fields.Text("Description"), "price": fields.Decimal("Price"), "values": fields.One2Many("product.custom.option.value", "cust_opt_id", "Values"), } _defaults = { "type": "text", "seq": '0', }
class LinkListItem(Model): _name = "cms.linklist.item" _fields = { "list_id": fields.Many2One("cms.linklist", "Link List", required=True, on_delete="cascade"), "sequence": fields.Integer("Sequence"), "title": fields.Char("Title", required=True, translate=True), "type": fields.Selection([["menu", "Menu"], ["submenu", "Submenu"]], "Type", required=True), "url": fields.Char("URL", required=True, size=256), "sub_items": fields.One2Many("cms.linklist.item", None, "Sub Items", function="get_sub_items"), } _defaults = { "type": "menu", } _order = "list_id,sequence,id" def get_sub_items(self, ids, context={}): list_ids = [] for obj in self.browse(ids): list_ids.append(obj.list_id.id) list_ids = list(set(list_ids)) sub_items = {} for lst in get_model("cms.linklist").browse(list_ids): parent_id = None for item in lst.items: if item.type == "menu": sub_items[item.id] = [] parent_id = item.id elif item.type == "submenu": sub_items[parent_id].append(item.id) return {id: sub_items[id] for id in ids}
class Reconcile(Model): _name = "account.reconcile" _string = "Account Reconciliation" _name_field = "number" _audit_log = True _fields = { "lines": fields.One2Many("account.move.line", "reconcile_id", "Account Entries", condition=[["move_id.state", "=", "posted"]]), "debit": fields.Decimal("Total Debit", function="get_total", function_multi=True), "credit": fields.Decimal("Total Credit", function="get_total", function_multi=True), "balance": fields.Decimal("Balance", function="get_total", function_multi=True), "number": fields.Char("Number", function="get_total", function_multi=True), } def get_total(self, ids, context={}): vals = {} for obj in self.browse(ids): debit = 0 credit = 0 for line in obj.lines: debit += line.debit credit += line.credit balance = debit - credit number = "R%d" % obj.id if balance != 0: number += "*" vals[obj.id] = { "debit": debit, "credit": credit, "balance": balance, "number": number, } return vals
class PaySlipLine(Model): _name = "hr.payslip.line" _string = "Pay Slip Line" _fields = { "slip_id": fields.Many2One("hr.payslip", "Pay Slip", required=True, on_delete="cascade"), "sequence": fields.Integer("Sequence"), "payitem_id": fields.Many2One("hr.payitem", "Pay Item", required=True), "qty": fields.Decimal("Qty", required=True), "rate": fields.Decimal("Rate", required=True), "amount": fields.Decimal("Amount", function="get_amount"), "comments": fields.One2Many("message", "related_id", "Comments"), } _defaults = { "state": "draft", "date_from": lambda *a: date.today().strftime("%Y-%m-01"), "date_to": lambda *a: (date.today() + relativedelta(day=31)).strftime("%Y-%m-%d"), } _order = "sequence" def get_amount(self, ids, context={}): # TODO need some logic for compute pay item vals = {} for obj in self.browse(ids): vals[obj.id] = obj.qty * obj.rate return vals
class StockJournal(Model): _name = "stock.journal" _string = "Stock Journal" _key = ["name"] _fields = { "name": fields.Char("Name", required=True, search=True), "code": fields.Char("Code", search=True), "sequence_id": fields.Many2One("sequence", "Sequence", multi_company=True), "location_from_id": fields.Many2One("stock.location", "Location From", search=True, multi_company=True), "location_to_id": fields.Many2One("stock.location", "Location To", search=True, multi_company=True), "comments": fields.One2Many("message", "related_id", "Comments"), } _order = "name"
class ContactCateg(Model): _name = "contact.categ" _string = "Contact Category" _key = ["code"] _name_field = "name" _fields = { "name": fields.Char("Category Name", required=True, search=True), "code": fields.Char("Category Code", search=True), "parent_id": fields.Many2One("contact.categ", "Parent", search=True), "description": fields.Text("Description"), "comments": fields.One2Many("message", "related_id", "Comments"), "full_name": fields.Char("Full Name", function="get_full_name"), } _order = "code" def get_full_name(self, ids, context={}): vals = {} for obj in self.browse(ids): n = obj.name p = obj.parent_id while p: n = p.name + " / " + n p = p.parent_id vals[obj.id] = n return vals
class Website(Model): _name = "website" _string = "Website" _fields = { "name": fields.Char("Website Title"), "parent_categ_id": fields.Many2One("product.categ", "Product Category"), "parent_group_id": fields.Many2One("product.group", "Product Group"), "contact_categ_id": fields.Many2One("contact.categ", "Customer Contact Category"), "user_profile_id": fields.Many2One("profile", "Customer User Profile"), "sale_account_id": fields.Many2One("account.account", "Sales Account"), "sale_tax_id": fields.Many2One("account.tax.rate", "Sales Tax"), "account_receivable_id": fields.Many2One("account.account", "Receivable Account"), "news_categ_id": fields.Many2One("contact.categ", "Newsletter Contact Category"), "target_list_id": fields.Many2One("mkt.target.list", "Newsletter Target List"), "invoice_flag": fields.Boolean("Use same invoice number as sale order number"), "ship_product_id": fields.Many2One("product", "Shipping Product"), "preview_doc_categ_id": fields.Many2One("document.categ", "Preview picture document category"), "invoice_template_id": fields.Many2One("report.template", "Invoice Template"), "payment_slip_template_id": fields.Many2One("report.template", "Payment Slip Template"), "auto_create_account": fields.Boolean("Auto-create customer account after checkout"), "ga_script": fields.Text("Google Analytic script"), "state": fields.Selection([["active", "Active"], ["inactive", "Inactive"]], "Status", required=True), "theme_id": fields.Many2One("theme", "Theme"), "settings": fields.One2Many("website.setting","website_id","Website Settings"), "sale_channel_id": fields.Many2One("sale.channel","Sales Channel"), "bank_method_id": fields.Many2One("payment.method","Bank Transfer",condition=[["type","=","bank"]]), "paypal_method_id": fields.Many2One("payment.method","Paypal",condition=[["type","=","paypal"]]), "paysbuy_method_id": fields.Many2One("payment.method","Paysbuy",condition=[["type","=","paysbuy"]]), "scb_method_id": fields.Many2One("payment.method","SCB Gateway",condition=[["type","=","scb_gateway"]]), "url": fields.Char("Website URL"), } _order="name" _defaults = { "state": "active", }
class Room(Model): _name = "room" _string = "Room" _fields = { "name": fields.Char("Name", search=True), "description": fields.Text("Description"), "comments": fields.One2Many("message", "related_id", "Comments") }
class Subdistrict(Model): _name = "subdistrict" _string = "Subdistrict" _export_name_field = "code" _fields = { "district_id": fields.Many2One("district", "District"), "name": fields.Char("Name", required=True, search=True, translate=True), "code": fields.Char("Code", search=True), "comments": fields.One2Many("message", "related_id", "Comments"), "postal_codes": fields.One2Many("postal.code", "subdistrict_id", "Postal Codes"), } _order = "name"
class LinkList(Model): _name = "cms.linklist" _string = "Link List" _key = ["code"] _fields = { "name": fields.Char("Name", required=True), "code": fields.Char("Code", required=True), "items": fields.One2Many("cms.linklist.item", "list_id", "Items"), "top_items": fields.One2Many("cms.linklist.item", "list_id", "Top Items", condition=[["type", "=", "menu"]]), }
class PayPeriod(Model): _name = "hr.pay.period" _string = "Pay Period" _fields = { "name": fields.Char("Name", required=True, search=True), "year": fields.DateTime("Year"), 'lines': fields.One2Many("hr.pay.period.line", "period_id", "Lines"), }
class ContactRelationType(Model): _name = "contact.relation.type" _string = "Relation Type" _fields = { "name": fields.Char("Name", required=True, search=True), "description": fields.Text("Description"), "comments": fields.One2Many("message", "related_id", "Comments"), } _order = "name"
class Group(Model): _name = "user.group" _string = "Group" _fields = { "name": fields.Char("Group Name", required=True, search=True), "users": fields.Many2Many("base.user", "Users"), "comments": fields.One2Many("message", "related_id", "Comments"), } _order = "name"
class BlogPost(Model): _name = "cms.blog.post" _string = "Blog Post" _name_field = "title" _fields = { "blog_id": fields.Many2One("cms.blog", "Blog", required=True, on_delete="cascade"), "date": fields.Date("Date", required=True), "title": fields.Char("Title", required=True, translate=True), "body": fields.Text("Body", translate=True), "blocks": fields.One2Many("cms.block", "related_id", "Blocks"), "meta_description": fields.Char("Meta Description"), "meta_keywords": fields.Char("Meta Keywords"), "comments": fields.One2Many("message", "related_id", "Comments"), } _defaults = { "date": lambda *a: time.strftime("%Y-%m-%d"), } _order = "date desc"
class Bom(Model): _name = "bom" _string = "Bill of Material" _name_field = "number" _key = ["number"] _fields = { "number": fields.Char("Number", required=True, search=True), "product_id": fields.Many2One("product", "Product", required=True, search=True), "qty": fields.Decimal("Qty", required=True, scale=6), "uom_id": fields.Many2One("uom", "UoM", required=True), "location_id": fields.Many2One("stock.location", "FG Warehouse"), "routing_id": fields.Many2One("routing", "Routing"), "lines": fields.One2Many("bom.line", "bom_id", "Lines"), "comments": fields.One2Many("message", "related_id", "Comments"), "documents": fields.One2Many("document", "related_id", "Documents"), "max_qty_loss": fields.Decimal("Max Qty Loss", scale=6), "container": fields.Selection([["sale", "From Sales Order"]], "FG Container"), "lot": fields.Selection([["production", "From Production Order"]], "FG Lot"), "qc_tests": fields.Many2Many("qc.test", "QC Tests"), } def _get_number(self, context={}): while 1: num = get_model("sequence").get_number("bom") if not num: return None res = self.search([["number", "=", num]]) if not res: return num get_model("sequence").increment("bom") _defaults = { "number": _get_number, } def onchange_product(self,context={}): data=context['data'] path=context['path'] line=get_data_path(data,path,parent=True) product_id=line['product_id'] if product_id: product=get_model('product').browse(product_id) line['uom_id']=product.uom_id.id return data
class Settings(Model): _name = "hr.payroll.settings" _fields = { "tax_rates": fields.One2Many("hr.tax.rate", "settings_id", "Tax Rates"), "social_rate": fields.Decimal("Rate (%)"), "social_min_wage": fields.Decimal("Min Wage Per Month"), "social_max_wage": fields.Decimal("Max Wage Per Month"), "comments": fields.One2Many("message", "related_id", "Comments"), "social_number": fields.Char("SSO Identification No."), "prov_name": fields.Char("Fund Name"), "child_alw_limit": fields.Integer("Limit to Children"), "child_alw_limit": fields.Integer("Limit to Children"), 'journal_id': fields.Many2One("account.journal", "Journal"), 'bank_account_id': fields.Many2One("account.account", "Bank Account"), 'sso_account_id': fields.Many2One("account.account", "SSO Account"), 'sso_comp_support': fields.Boolean("SSO Company Support"), 'intg_acc': fields.Boolean("Integrate to Account"), }