class CreditAlloc(Model): _name = "account.credit.alloc" _fields = { "invoice_id": fields.Many2One("account.invoice", "Invoice", required=True, on_delete="cascade"), "credit_id": fields.Many2One("account.invoice", "Credit Note", on_delete="cascade"), "credit_move_id": fields.Many2One("account.move", "Credit Journal Entry", on_delete="cascade"), "credit_type": fields.Char("Credit Type", function="_get_related", function_context={"path": "credit_id.inv_type"}), "amount": fields.Decimal("Amount"), "move_id": fields.Many2One("account.move", "Journal Entry"), "date": fields.Date("Date", required=True), } _defaults = { "date": lambda *a: time.strftime("%Y-%m-%d"), } def create(self, vals, **kw): new_id = super().create(vals, **kw) inv_ids = [] inv_id = vals.get("invoice_id") if inv_id: inv_ids.append(inv_id) cred_id = vals.get("credit_id") if cred_id: inv_ids.append(cred_id) if inv_ids: get_model("account.invoice").function_store(inv_ids) return new_id def delete(self, ids, **kw): inv_ids = [] for obj in self.browse(ids): if obj.invoice_id: inv_ids.append(obj.invoice_id.id) if obj.credit_ids: inv_ids.append(obj.credit_id.id) if obj.move_id: obj.move_id.void() obj.move_id.delete() super().delete(ids, **kw) if inv_ids: get_model("account.invoice").function_store(inv_ids)
class SaleTarget(Model): _name = "sale.target" _string = "Sales Target" _key = ["user_id"] _fields = { "user_id": fields.Many2One("base.user", "Salesman", search=True), "prod_categ_id": fields.Many2One("product.categ", "Product Category", search=True), "date_from": fields.Date("From Date", required=True), "date_to": fields.Date("To Date", required=True, search=True), "amount_target": fields.Decimal("Target Amount"), "amount_actual": fields.Decimal("Actual Amount", function="get_amount", function_multi=True), "amount_expected": fields.Decimal("Expected Amount", function="get_amount", function_multi=True), "qty_target": fields.Decimal("Target Qty"), "qty_actual": fields.Decimal("Actual Qty", function="get_amount", function_multi=True), "qty_expected": fields.Decimal("Expected Qty", function="get_amount", function_multi=True), "comments": fields.One2Many("message", "related_id", "Comments"), } _order = "date_from,user_id,prod_categ_id" _defaults = { "date_from": lambda *a: date.today().strftime("%Y-%m-01"), "date_to": lambda *a: (date.today() + relativedelta(day=31)).strftime("%Y-%m-%d"), } def get_amount(self, ids, context={}): all_vals = {} db = database.get_connection() for obj in self.browse(ids): q = "SELECT SUM(opp.amount) AS amount,SUM(opp.qty) AS qty FROM sale_opportunity opp LEFT JOIN product prod ON prod.id=opp.product_id WHERE opp.state='won' AND opp.date_close>=%s AND opp.date_close<=%s" a = [obj.date_from, obj.date_to] if obj.user_id: q += " AND opp.user_id=%s" a.append(obj.user_id.id) if obj.prod_categ_id: q += " AND prod.categ_id=%s" a.append(obj.prod_categ_id.id) res_won = db.get(q, *a) q = "SELECT SUM(opp.amount*opp.probability/100) AS amount,SUM(opp.qty*opp.probability/100) AS qty FROM sale_opportunity opp LEFT JOIN product prod ON prod.id=opp.product_id WHERE opp.state='open' AND opp.date_close>=%s AND opp.date_close<=%s" a = [obj.date_from, obj.date_to] if obj.user_id: q += " AND opp.user_id=%s" a.append(obj.user_id.id) if obj.prod_categ_id: q += " AND prod.categ_id=%s" a.append(obj.prod_categ_id.id) res_open = db.get(q, *a) vals = { "amount_actual": res_won.amount or 0, "amount_expected": res_open.amount or 0, "qty_actual": res_won.qty or 0, "qty_expected": res_open.qty or 0, } all_vals[obj.id] = vals return all_vals
class ReminderTemplate(Model): _name = "reminder.template" _string = "Reminder Template" _fields = { "doc_categ_id": fields.Many2One("document.categ", "Document Category", required=True), "scheduled_date": fields.Char("Scheduled Date", required=True), "user_id": fields.Many2One("base.user", "To User", required=True), "subject": fields.Char("Subject", required=True), "body": fields.Text("Body"), } _order = "id"
class kaopopupline(Model): _name = "kao.popup.line" _transient = True _fields = { "product_id": fields.Many2One("product", "Product", search=True), "amount": fields.Integer("Amount"), "price": fields.Decimal("Price"), "total": fields.Decimal("Total"), "pop_id": fields.Many2One("kao.popup", "Lines", on_delete="cascade"), }
class FixedAssetType(Model): _name = "account.fixed.asset.type" _string = "Asset Type" _fields = { "name": fields.Char("Name", required=True, search=True), "dep_rate": fields.Decimal("Depreciation Rate (%)", search=True, required=True), "dep_method": fields.Selection( [["line", "Straight Line"], ["decline", "Declining Balance"]], "Depreciation Method", search=True, required=True), "fixed_asset_account_id": fields.Many2One("account.account", "Fixed Asset Account", required=True, multi_company=True), "accum_dep_account_id": fields.Many2One("account.account", "Accum. Depr. Account", required=True, multi_company=True), "dep_exp_account_id": fields.Many2One("account.account", "Depr. Exp. Account", required=True, multi_company=True), "description": fields.Text("Description"), } def copy(self, ids, context={}): obj = self.browse(ids)[0] vals = { 'name': '%s (Copy)' % (obj.name), 'dep_rate': obj.dep_rate, 'dep_method': obj.dep_method, 'fixed_asset_account_id': obj.fixed_asset_account_id.id, 'accum_dep_account_id': obj.accum_dep_account_id.id, 'dep_exp_account_id': obj.dep_exp_account_id.id, 'description': obj.description, } new_id = self.create(vals) #new=self.browse(new_id) return { 'next': { 'name': "fixed_asset_type", "mode": "form", "active_id": new_id, }, 'flash': "Copy fixed asset type successfully!" }
class CreditWizardLine(Model): _name = "account.credit.wizard.line" _transient = True _fields = { "wiz_id": fields.Many2One("account.credit.wizard", "Wizard", required=True, on_delete="cascade"), "move_line_id": fields.Many2One("account.move.line", "Account Entry", required=True, readonly=True, on_delete="cascade"), "move_id": fields.Many2One("account.move", "Journal Entry", required=True, readonly=True, on_delete="cascade"), "date": fields.Date("Date", readonly=True), "account_id": fields.Many2One("account.account", "Account", required=True, readonly=True, on_delete="cascade"), "amount_credit_remain": fields.Decimal("Outstanding Credit", readonly=True), "amount": fields.Decimal("Amount"), }
class BankAccount(Model): _name = "bank.account" _fields = { "bank_id": fields.Many2One("bank", "Bank", required=True), "branch": fields.Char("Branch"), "number": fields.Char("Account Number", required=True), "signatory": fields.Char("Signatory"), "online": fields.Boolean("Online"), "contact_id": fields.Many2One("contact", "Partner", on_delete="cascade"), }
class TransformSource(Model): _name = "stock.transform.source" _string = "Transform Source" _fields = { "transform_id": fields.Many2One("stock.transform", "Transform", on_delete="cascade"), "product_id": fields.Many2One("product", "Product", required=True), "qty": fields.Decimal("Qty", required=True, scale=6), "qty2": fields.Decimal("Qty2"), "uom_id": fields.Many2One("uom", "UoM", required=True), "lot_id": fields.Many2One("stock.lot", "Lot / Serial Number"), "container_id": fields.Many2One("stock.container", "Container"), }
class PayItemProfileLine(Model): _name = "hr.payitem.profile.line" _string = "Pay Item Profile" _fields = { "profile_id": fields.Many2One("hr.payitem.profile", "Profile", required=True, on_delete="cascade"), "payitem_id": fields.Many2One("hr.payitem", "Pay Item"), } _defaults = {}
class ProfileAccess(Model): _name = "profile.access" _key = ["profile_id", "model_id"] _fields = { "profile_id": fields.Many2One("profile", "Profile", required=True, on_delete="cascade"), "model_id": fields.Many2One("model", "Model", required=True), "perm_read": fields.Boolean("Read"), "perm_create": fields.Boolean("Create"), "perm_write": fields.Boolean("Write"), "perm_delete": fields.Boolean("Delete"), "view_all": fields.Boolean("View All"), "modif_all": fields.Boolean("Modify All"), }
class ProductBrandGroup(Model): _name = "product.brand.group" _string = "Product Brand Group" _key = ["code"] _fields = { "name": fields.Char("Group Name", required=True, search=True), "code": fields.Char("Group Code", search=True), "parent_id": fields.Many2One("product.brand.group", "Parent"), "brands": fields.Many2Many("product.brand", "Product Brands"), "image": fields.File("Image"), "company_id": fields.Many2One("company","Company"), } _order = "name"
class ConvertLead(Model): _name = "convert.lead" _transient = True _fields = { "lead_id": fields.Many2One("sale.lead", "Lead", required=True, on_delete="cascade"), "user_id": fields.Many2One("base.user", "Assigned To", required=True, on_delete="cascade"), "contact_id": fields.Many2One("contact", "Contact", required=True, on_delete="cascade"), "name": fields.Char("Opportunity Name", required=True), "uuid": fields.Char("UUID"), } def default_get(self, field_names=None, context={}, **kw): defaults = context.get("defaults") if defaults: lead_id = int(defaults["lead_id"]) lead = get_model("sale.lead").browse(lead_id) res = get_model("contact").search([["name", "=", lead.company]]) if res: defaults["contact_id"] = res[0] defaults["user_id"] = lead.user_id.id return super().default_get(field_names, context, **kw) def do_copy(self, ids, context={}): obj = self.browse(ids)[0] vals = { "user_id": obj.user_id.id, "name": obj.name, "contact_id": obj.contact_id.id, } opp_id = get_model("sale.opportunity").create(vals) return { "next": { "name": "opport", "mode": "form", "active_id": opp_id, } }
class Company(Model): _name = "company" _string = "Company" _key = ["name"] _audit_log = True _fields = { "name": fields.Char("Company Name", required=True, search=True, translate=True), "code": fields.Char("Company Code", search=True), "parent_id": fields.Many2One("company", "Parent"), "description": fields.Text("Description"), "comments": fields.One2Many("message", "related_id", "Comments"), "contact_id": fields.Many2One("contact","Contact"), } _order = "name"
class ProductionCost(Model): _name = "production.cost" _string = "Production Cost" _fields = { "order_id": fields.Many2One("production.order", "Production Order", required=True, on_delete="cascade"), "product_id": fields.Many2One("product", "Cost Product"), "amount": fields.Decimal("Amount", required=True), }
class BomLine(Model): _name = "bom.line" _fields = { "bom_id": fields.Many2One("bom", "BoM", required=True, on_delete="cascade"), "product_id": fields.Many2One("product", "Product", required=True), "qty": fields.Decimal("Qty", required=True, scale=6), "uom_id": fields.Many2One("uom", "UoM", required=True), "location_id": fields.Many2One("stock.location", "RM Warehouse"), "container": fields.Selection([["sale", "From Sales Order"]], "RM Container"), "lot": fields.Selection([["production", "From Production Order"]], "RM Lot"), "issue_method": fields.Selection([["manual", "Manual"], ["backflush", "Backflush"]], "Issue Method"), "qty2": fields.Decimal("Qty2", scale=6), "notes": fields.Text("Notes"), }
class TaskList(Model): _name = "task.list" _string = "Task List" _fields = { "name": fields.Char("Name", required=True), "date_created": fields.Date("Date Created", required=True), "project_id": fields.Many2One("project", "Project"), "milestone_id": fields.Many2One("project.milestone", "Milestone"), "tasks": fields.One2Many("task", "task_list_id", "Tasks"), } _order = "date_created desc,id desc" _defaults = { "date_created": lambda *a: time.strftime("%Y-%m-%d"), }
class BarcodeIssueLine(Model): _name = "barcode.issue.line" _transient = True _fields = { "wizard_id": fields.Many2One("barcode.issue", "Wizard", required=True, on_delete="cascade"), "product_id": fields.Many2One("product", "Product", required=True), "qty": fields.Decimal("Qty", required=True), "uom_id": fields.Many2One("uom", "UoM", required=True), "qty2": fields.Decimal("Secondary Qty"), "lot_id": fields.Many2One("stock.lot", "Lot / Serial Number"), "container_from_id": fields.Many2One("stock.container", "From Container"), "container_to_id": fields.Many2One("stock.container", "To Container"), "location_from_id": fields.Many2One("stock.location", "From Location"), "location_to_id": fields.Many2One("stock.location", "To Location"), "related_id": fields.Reference([["sale.order", "Sales Order"], ["purchase.order", "Purchase Order"]], "Related To"), "qty2": fields.Decimal("Qty2"), "notes": fields.Text("Notes"), }
class StockCountLine(Model): _name = "stock.count.line" _fields = { "count_id": fields.Many2One("stock.count", "Stock Count", required=True, on_delete="cascade"), "product_id": fields.Many2One("product", "Product", condition=[["type", "=", "stock"]], required=True), "lot_id": fields.Many2One("stock.lot", "Lot / Serial Number"), "bin_location": fields.Char("Bin Location", readonly=True), "prev_qty": fields.Decimal("Previous Qty", required=True, readonly=True), "new_qty": fields.Decimal("New Qty", required=True), "uom_id": fields.Many2One("uom", "UoM", required=True, readonly=True), "prev_cost_price": fields.Decimal("Previous Cost Price", scale=6, function="get_prev_cost_price"), "prev_cost_amount": fields.Decimal("Previous Cost Amount"), "unit_price": fields.Decimal("New Cost Price", scale=6), # TODO: rename to new_cost_price "new_cost_amount": fields.Decimal("New Cost Amount", function="get_new_cost_amount"), } _order = "product_id.code" def get_prev_cost_price(self, ids, context={}): vals = {} for obj in self.browse(ids): vals[obj.id] = (obj.prev_cost_amount or 0) / obj.prev_qty if obj.prev_qty else 0 return vals def get_new_cost_amount(self, ids, context={}): vals = {} for obj in self.browse(ids): vals[obj.id] = (obj.new_qty or 0) * (obj.unit_price or 0) return vals
class Reminder(Model): _name = "reminder" _string = "Reminder" _fields = { "scheduled_date": fields.Date("Scheduled Date", required=True), "doc_id": fields.Many2One("document", "Document", required=True, on_delete="cascade"), "user_id": fields.Many2One("base.user", "To User", required=True), "subject": fields.Char("Subject", required=True), "body": fields.Text("Body"), "state": fields.Selection([["pending", "Pending"], ["sent", "Sent"]], "Status", required=True), } _order = "scheduled_date,id" _defaults = { "scheduled_date": lambda *a: time.strftime("%Y-%m-%d"), "state": "pending", } def send_email(self, ids, context={}): for obj in self.browse(ids): to_addr = obj.user_id.email if not to_addr: continue vals = { "state": "to_send", "from_addr": "*****@*****.**", "to_addrs": to_addr, "subject": obj.subject, "body": obj.body, } get_model("email.message").create(vals) obj.write({"state": "sent"}) def send_reminders(self): t = time.strftime("%Y-%m-%d") ids = self.search([["scheduled_date", "<=", t], ["state", "=", "pending"]]) self.send_email(ids)
class ConvSaleInvoice(Model): _name = "conv.sale.invoice" _transient = True _fields = { "conv_id": fields.Many2One("conv.bal", "Conversion", required=True), "number": fields.Char("Number", required=True), "ref": fields.Char("Reference"), "contact_id": fields.Many2One("contact", "Contact", required=True, on_delete="cascade"), "date": fields.Date("Date", required=True), "due_date": fields.Date("Due Date", required=True), "amount_due": fields.Decimal("Amount Due", required=True), "move_line_id": fields.Many2One("account.move.line", "Move Line"), "account_id": fields.Many2One("account.account", "Account", required=True), "amount_cur": fields.Decimal("Currency Amt"), }
class AttributeValue(Model): _name = "product.attribute.value" _fields = { "product_id": fields.Many2One("product", "Product", required=True, on_delete="cascade"), "attribute_id": fields.Many2One("product.attribute", "Attribute", required=True), "value": fields.Char("Value"), # Deprecated "option_id": fields.Many2One("product.attribute.option", "Value"), }
class Operation(Model): _name = "mrp.operation" _fields = { "order_id": fields.Many2One("production.order", "Order", required=True, on_delete="cascade"), "date": fields.Date("Date", required=True), "workcenter_id": fields.Many2One("workcenter", "Workcenter", required=True), "hours": fields.Decimal("Hours", required=True), }
class TrackEntry(Model): _name = "account.track.entry" _string = "Tracking Entries" _fields = { "track_id": fields.Many2One("account.track.categ", "Tracking Category",required=True,on_delete="cascade",search=True), "date": fields.Date("Date",required=True,search=True), "amount": fields.Decimal("Amount",required=True), "product_id": fields.Many2One("product","Product",search=True), "description": fields.Text("Description"), "qty": fields.Decimal("Qty"), "uom_id": fields.Many2One("uom","UoM"), "unit_price": fields.Decimal("Unit Price"), "related_id": fields.Reference([["account.invoice","Invoice"],["stock.picking","Stock Picking"],["work.time","Work Time"],["hr.expense","Expense Claim"]],"Related To"), "move_id": fields.Many2One("account.move","Journal Entry",search=True), } _order = "date desc,id desc" _defaults={ "date": lambda *a: time.strftime("%Y-%m-%d"), } def onchange_product(self,context={}): data=context.get("data",{}) print("#"*80) print("ID",data.get("id")) prod_id=data["product_id"] if not prod_id: return prod=get_model("product").browse(prod_id) price=prod.cost_price if prod.cost_method == "standard" else prod.landed_cost if not price: raise Exception("Missing Cost Price or Landed Cost") track_id=data["track_id"] track=get_model("account.track.categ").browse(track_id) if track.currency_id: settings=get_model("settings").browse(1) price=get_model("currency").convert(price,settings.currency_id.id,track.currency_id.id) data["unit_price"]=-price data["qty"]=1 data["uom_id"]=prod.uom_id.id data["amount"]=data["unit_price"] return data def update_amount(self,context={}): data=context.get("data",{}) unit_price=data.get("unit_price",0) qty=data.get("qty",0) data["amount"]=unit_price*qty return data
class JobPart(Model): _name = "job.part" _audit_log = True _fields = { "job_id": fields.Many2One("job", "Job", required=True, on_delete="cascade"), "product_id": fields.Many2One("product", "Product", required=True), "qty_planned": fields.Decimal("Planned Qty", required=True), "uom_id": fields.Many2One("uom", "UoM", required=True), "location_id": fields.Many2One("stock.location", "From Warehouse", required=True), "qty_issued": fields.Decimal("Issued Qty", function="get_qty_issued"), "unit_price": fields.Decimal("Sale Unit Price"), "amount": fields.Decimal("Sale Amount", function="get_amount"), } def get_amount(self, ids, context={}): vals = {} for obj in self.browse(ids): if obj.qty_issued and obj.unit_price: vals[obj.id] = obj.qty_issued * obj.unit_price else: vals[obj.id] = None return vals def get_qty_issued(self, ids, context={}): vals = {} for obj in self.browse(ids): job = obj.job_id total_qty = 0 for pick in job.pickings: for move in pick.lines: if move.product_id.id != obj.product_id.id or move.state != "done": continue qty = get_model("uom").convert(move.qty, move.uom_id.id, obj.uom_id.id) if move.location_from_id.id == obj.location_id.id and move.location_to_id.id != obj.location_id.id: total_qty += qty elif move.location_from_id.id != obj.location_id.id and move.location_to_id.id == obj.location_id.id: total_qty -= qty vals[obj.id] = total_qty return vals
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 WSListener(Model): _name = "ws.listener" _log_access = False _fields = { "user_id": fields.Many2One("base.user", "User"), "last_check_time": fields.DateTime("Last Check Time", required=True), }
class PostalCode(Model): _name = "postal.code" _string = "Postal Code" _fields = { "code": fields.Char("Code", search=True, required=True), "country_id": fields.Many2One("country", "Country", search=True), "province_id": fields.Many2One("province", "Province", search=True), "district_id": fields.Many2One("district", "District", search=True), "subdistrict_id": fields.Many2One("subdistrict", "Subdistrict", search=True), } _order = "code"
class ScheduleLine(Model): _name = "hr.schedule.line" _string = "Schedule Line" def get_time_stop(self, ids, context={}): res = {} for obj in self.browse(ids): datenow = datetime.now().strftime("%Y-%m-%d") time_start = '%s %s' % (datenow, obj.time_start) time_total = obj.time_total or 0.0 if obj.skip_mid: time_total += 1 # 12.00-13.00 seconds = (time_total) * 60 * 60 time_stop = datetime.strptime(time_start, '%Y-%m-%d %H:%S') + timedelta(seconds=seconds) res[obj.id] = time_stop.strftime("%H:%S") return res _fields = { 'schedule_id': fields.Many2One("hr.schedule", "Schedule"), "dow": fields.Selection([["1", "Monday"], ["2", "Tuesday"], ["3", "Wednesday"], ["4", "Thursday"], ["5", "Friday"], ["6", "Saturday"], ["7", "Sunday"]], "Day Of Week"), 'time_start': fields.Char("Time Start"), 'time_stop': fields.Char("Time Stop"), } order = "dow, time_start"
class LeavePeriod(Model): _name = "hr.leave.period" _string = "Leave Period" _name_field = "date_from" # XXX _fields = { "leave_type_id": fields.Many2One("hr.leave.type", "Leave Type", required=True, search=True), "date_from": fields.Date("From Date", required=True, search=True), "date_to": fields.Date("To Date", required=True, search=True), "max_days": fields.Decimal("Max Days", search=True), } _order = "date_from" def name_search(self, name, condition=[], limit=None, context={}): ids = self.search(condition, limit=limit) return self.name_get(ids, context) def name_get(self, ids, context={}): vals = [] for obj in self.browse(ids): name = "%s - %s" % (obj.date_from, obj.date_to) vals.append((obj.id, name)) return vals def import_get(self, name, context={}): parent_vals = context["parent_vals"] leave_type_id = parent_vals["leave_type_id"] res = name.split(" - ") if len(res) != 2: raise Exception("Invalid leave period format: '%s'" % name) date_from, date_to = res cond = [["leave_type_id", "=", leave_type_id], ["date_from", "=", date_from], ["date_to", "=", date_to]] res = self.search(cond) if not res: raise Exception("Leave period not found") return res[0]
class WSEvent(Model): _name = "ws.event" _log_access = False _fields = { "listener_id": fields.Many2One("ws.listener", "Listener", on_delete="cascade"), "name": fields.Char("Name", required=True), "ctime": fields.DateTime("Create Time", required=True), } def new_event(self, event_name, user_id): print("WSEvent.new_event", event_name, user_id) t = time.strftime("%Y-%m-%d %H:%M:%S") db = get_connection() if user_id: res = db.query("SELECT id FROM ws_listener WHERE user_id=%s", user_id) else: res = db.query("SELECT id FROM ws_listener") for r in res: db.execute( "INSERT INTO ws_event (listener_id,name,ctime) VALUES (%s,%s,%s)", r.id, event_name, t)