def delete(self, ids, **kw): move_ids = [] for obj in self.browse(ids): for line in obj.lines: move_ids.append(line.id) get_model("stock.move").delete(move_ids) # to update stored functions super().delete(ids, **kw)
def post(self,ids,context={}): sale_ids=[] for obj in self.browse(ids): if obj.pay_type!="invoice": continue for line in obj.invoice_lines: inv=line.invoice_id rel=inv.related_id if rel and rel._model=="sale.order": sale_ids.append(rel.id) for inv_line in inv.lines: rel=inv_line.related_id if rel and rel._model=="sale.order": sale_ids.append(rel.id) sale_ids=list(set(sale_ids)) unpaid_sale_ids=[] for sale in get_model("sale.order").browse(sale_ids): if not sale.is_paid: unpaid_sale_ids.append(sale.id) res=super().post(ids,context=context) paid_sale_ids=[] for sale in get_model("sale.order").browse(unpaid_sale_ids): if sale.is_paid: paid_sale_ids.append(sale.id) if paid_sale_ids: get_model("sale.order").trigger(paid_sale_ids,"paid") return res
def validate(self, ids, context={}): obj = self.browse(ids)[0] if not obj.lines: raise Exception("Product list is empty") pick = obj.picking_id if obj.mode == "backorder": vals = { "picking_id": pick.id, "lines": [], } for line in obj.lines: if not line.qty_actual: raise Exception("Missing actual qty for product %s" % line.product_id.code) line_vals = { "product_id": line.product_id.id, "qty": line.qty_actual, "uom_id": line.uom_id.id, } vals["lines"].append(("create", line_vals)) val_id = get_model("pick.validate").create(vals) res = get_model("pick.validate").do_validate([val_id]) obj.clear() return { "flash": res["flash"], } elif obj.mode == "loss": if not obj.location_loss_id: raise Exception("Missing inventory loss location") pick.set_done(context=context) # XXX obj.clear() return { "flash": "Picking validated successfully", "focus_field": "picking_id", }
def get_delivery_slots(self,ids,context={}): print("get_delivery_slots",ids) obj=self.browse(ids[0]) settings=get_model("ecom2.settings").browse(1) max_days=settings.delivery_max_days if not max_days: return {obj.id:[]} min_hours=settings.delivery_min_hours or 0 d_from=date.today()+timedelta(days=obj.delivery_delay) d_to=d_from+timedelta(days=max_days) d=d_from slots=[] for slot in get_model("delivery.slot").search_browse([]): slots.append([slot.id,slot.name,slot.time_from]) slot_num_sales={} for sale in get_model("sale.order").search_browse([["date",">=",time.strftime("%Y-%m-%d")]]): k=(sale.due_date,sale.delivery_slot_id.id) slot_num_sales.setdefault(k,0) slot_num_sales[k]+=1 slot_caps={} for cap in get_model("delivery.slot.capacity").search_browse([]): k=(cap.slot_id.id,int(cap.weekday)) slot_caps[k]=cap.capacity delivery_weekdays=None for line in obj.lines: prod=line.product_id if prod.delivery_weekdays: days=[int(w) for w in prod.delivery_weekdays.split(",")] if delivery_weekdays==None: delivery_weekdays=days else: delivery_weekdays=[d for d in delivery_weekdays if d in days] days=[] now=datetime.now() while d<=d_to: ds=d.strftime("%Y-%m-%d") res=get_model("hr.holiday").search([["date","=",ds]]) if res: d+=timedelta(days=1) continue w=d.weekday() if w==6 or delivery_weekdays is not None and w not in delivery_weekdays: d+=timedelta(days=1) continue day_slots=[] for slot_id,slot_name,from_time in slots: t_from=datetime.strptime(ds+" "+from_time+":00","%Y-%m-%d %H:%M:%S") capacity=slot_caps.get((slot_id,w)) num_sales=slot_num_sales.get((ds,slot_id),0) state="avail" if t_from<now or (t_from-now).seconds<min_hours*3600: state="full" if capacity is not None and num_sales>=capacity: state="full" day_slots.append([slot_id,slot_name,state,num_sales,capacity]) days.append([ds,day_slots]) d+=timedelta(days=1) print("days:") pprint(days) return {obj.id: days}
def make_po(self, ids, context={}): suppliers = {} for obj in self.browse(ids): if obj.qty_virt >= obj.min_qty: continue prod = obj.product_id if prod.supply_method!="purchase": raise Exception("Supply method for product %s is not set to 'Purchase'"%prod.code) res = get_model("stock.orderpoint").search([["product_id", "=", prod.id]]) if res: op = get_model("stock.orderpoint").browse(res)[0] max_qty = op.max_qty else: max_qty = 0 diff_qty = max_qty - obj.qty_virt if prod.purchase_uom_id: purch_uom=prod.purchase_uom_id if not prod.purchase_to_stock_uom_factor: raise Exception("Missing purchase order -> stock uom factor for product %s"%prod.code) purch_qty=diff_qty/prod.purchase_to_stock_uom_factor else: purch_uom=prod.uom_id purch_qty=diff_qty if prod.purchase_qty_multiple: n=math.ceil(purch_qty/prod.purchase_qty_multiple) purch_qty=n*prod.purchase_qty_multiple if prod.purchase_uom_id: qty_stock=purch_qty*prod.purchase_to_stock_uom_factor else: qty_stock=None line_vals = { "product_id": prod.id, "description": prod.name_get()[0][1], "qty": purch_qty, "uom_id": purch_uom.id, "unit_price": prod.purchase_price or 0, "tax_id": prod.purchase_tax_id.id, "qty_stock": qty_stock, } if not prod.suppliers: raise Exception("Missing default supplier for product %s" % prod.name) contact_id = prod.suppliers[0].supplier_id.id suppliers.setdefault(contact_id, []).append(line_vals) if not suppliers: raise Exception("Nothing to order") count = 0 for contact_id, lines in suppliers.items(): vals = { "contact_id": contact_id, "lines": [("create", x) for x in lines], } purch_id = get_model("purchase.order").create(vals) count += 1 return { "next": { "name": "purchase", "tab": "Draft", }, "flash": "%d purchase orders created" % count, }
def to_draft(self,ids,context={}): for obj in self.browse(ids): move_ids=[] for move in obj.lines: move_ids.append(move.id) get_model("stock.move").to_draft(move_ids) obj.write({"state":"draft"})
def compute_thai_tax(self, context={}): emp_id = context.get("employee_id") if emp_id != 'null': emp_id = int(emp_id) emp = get_model("hr.employee").browse(emp_id) period = context.get("period", 12) date = context.get("date") vals = {} vals["B1"] = max(0, self.get_yearly_provident_fund(context=context) - 10000) #vals["B2"]=emp.gov_pension_fund or 0 vals["B2"] = 0 vals["B3"] = emp.teacher_fund or 0 vals["B4"] = emp.old_disabled or 0 vals["B5"] = emp.old_disabled_spouse or 0 vals["B6"] = emp.severance_pay or 0 vals["B7"] = vals["B1"] + vals["B2"] + vals["B3"] + vals["B4"] + vals["B5"] + vals["B6"] vals["C1"] = 30000 vals["C2"] = 30000 if emp.spouse_filing_status in ("joint", "no_income") else 0 vals["C3a"] = 15000 * (emp.num_child1 or 0) vals["C3b"] = 17000 * (emp.num_child2 or 0) vals["C4a"] = 30000 if emp.father_id_no else 0 vals["C4b"] = 30000 if emp.mother_id_no else 0 vals["C4c"] = 30000 if emp.spouse_father_id_no else 0 vals["C4d"] = 30000 if emp.spouse_mother_id_no else 0 vals["C5"] = emp.disabled_support or 0 vals["C6"] = emp.parent_health_insurance or 0 vals["C7"] = emp.life_insurance or 0 vals["C8"] = min(10000, self.get_yearly_provident_fund(context=context)) vals["C9"] = emp.retirement_mutual_fund or 0 vals["C10"] = emp.long_term_equity_fund or 0 vals["C11"] = emp.interest_residence or 0 vals["C12"] = emp.other_deduct or 0 vals["C13"] = self.get_yearly_social_security(context=context) vals["C14"] = vals["C1"] + vals["C2"] + vals["C3a"] + vals["C3b"] + vals["C4a"] + vals["C4b"] + vals["C4c"] + vals["C4d"] + \ vals["C5"] + vals["C6"] + vals["C7"] + vals["C8"] + vals["C9"] + \ vals["C10"] + vals["C11"] + vals["C12"] + vals["C13"] vals["A1"] = self.get_yearly_income(context=context) + vals["B6"] vals["A2"] = vals["B7"] vals["A3"] = vals["A1"] - vals["A2"] vals["A4"] = min(0.4 * vals["A3"], 60000) # XXX: use settings vals["A5"] = vals["A3"] - vals["A4"] vals["A6"] = vals["C14"] vals["A7"] = vals["A5"] - vals["A6"] vals["A8"] = min(2 * (emp.education_donation or 0), 0.1 * vals["A7"]) vals["A9"] = vals["A7"] - vals["A8"] vals["A10"] = min(emp.other_donation or 0, 0.1 * vals["A9"]) vals["A11"] = vals["A9"] - vals["A10"] vals["A12"] = get_model("hr.tax.rate").compute_tax(vals["A11"]) vals["A13"] = emp.house_deduct or 0 vals["A14"] = max(0, vals["A12"] - vals["A13"]) vals["A15"] = emp.wht_amount or 0 vals["A16"] = vals["A14"] - vals["A15"] vals["A17"] = 0 # XXX vals["A18"] = 0 vals["A19"] = 0 vals["A20"] = vals["A16"] vals["A21"] = 0 vals["A22"] = vals["A20"] vals["tax_month"] = vals["A12"] / period return vals
def check_sent_emails(self, context={}): print("send_sent_emails") res = get_model("email.account").search([["type", "=", "mailgun"]]) # XXX if not res: return acc_id = res[0] get_model("email.account").check_sent_emails([acc_id])
def add_products(self, ids, context={}): obj = self.browse(ids)[0] pricelist = obj.pricelist_id categ_ids = [c.id for c in obj.product_categs] for prod in get_model("product").search_browse([["categs.id", "in", categ_ids]]): factor = pricelist.factor or 1.0 if pricelist.base_price == "product": base_price = prod.sale_price or 0 elif pricelist.base_price == "other_pricelist": if not pricelist.other_pricelist_id: raise Exception("Missing base price list") base_price = get_model("price.list").get_price( pricelist.other_pricelist_id.id, prod.id, 1) or 0 # XXX: qty elif pricelist.base_price == "volume": base_price = prod.volume or 0 else: raise Exception("Invalid base price type") price = utils.round_amount(base_price * factor, pricelist.rounding, pricelist.rounding_method) vals = { "list_id": pricelist.id, "product_id": prod.id, "price": price, } get_model("price.list.item").create(vals) return { "next": { "name": "pricelist_item", }, "flash": "Products added to price list", }
def onchange_product(self, context): data = context["data"] type = data["type"] path = context["path"] contact_id = data["contact_id"] contact = get_model("contact").browse(contact_id) line = get_data_path(data, path, parent=True) prod_id = line.get("product_id") if not prod_id: return {} prod = get_model("product").browse(prod_id) line["description"] = prod.description line["qty"] = 1 if prod.uom_id is not None: line["uom_id"] = prod.uom_id.id if type == "out": if prod.sale_price is not None: line["unit_price"] = prod.sale_price if prod.sale_account_id is not None: line["account_id"] = prod.sale_account_id.id if prod.sale_tax_id is not None: line["tax_id"] = contact.tax_receivable_id.id or prod.sale_tax_id.id elif type == "in": if prod.purchase_price is not None: line["unit_price"] = prod.purchase_price if prod.purchase_account_id is not None: line["account_id"] = prod.purchase_account_id.id if prod.purchase_tax_id is not None: line["tax_id"] = contact.tax_payable_id.id or prod.purchase_tax_id.id data = self.update_amounts(context) return data
def get(self): db = get_connection() try: ctx = self.context categ_id=self.get_argument("categ_id",None) if categ_id: categ_id = int(categ_id) else: categ_code=self.get_argument("categ_code",None) res=get_model("product.categ").search([["code","=",categ_code]]) if not res: raise Exception("Product categ not found: '%s'"%categ_code) categ_id=res[0] res = get_model("product.categ").browse([categ_id]) if not res: raise Exception("Can't find product category id: ",categ_id) categ = res[0] ctx["product_categ"] = categ ctx["parent_categ_list"] = list_categ_parent(categ, categ_list=[]) content = render("ecom_product_categ", ctx) ctx["content"] = content html = render("cms_layout", ctx) self.write(html) db.commit() except: self.redirect("/cms_page_not_found") import traceback traceback.print_exc() db.rollback()
def create(self, vals, **kw): new_id = super().create(vals, **kw) inv_id = vals["invoice_id"] cred_id = vals["credit_id"] get_model("account.invoice").function_store([inv_id, cred_id]) self.post([new_id]) return new_id
def get_brands(condition): print("get_brands") res=get_model("product").read_group(["brand_id"],condition=condition) brand_nums={} for r in res: brand_id=r["brand_id"][0] if r["brand_id"] else None brand_nums.setdefault(brand_id,0) brand_nums[brand_id]+=r["_count"] res=get_model("product.brand").search_read([],["code","name","parent_id"]) brand_ids={} for r in res: brand_ids[r["id"]]=r top_brands=[] for r in res: parent_id=r["parent_id"][0] if r["parent_id"] else None if parent_id: parent=brand_ids[parent_id] parent.setdefault("sub_brands",[]).append(r) else: top_brands.append(r) for brand_id,num in brand_nums.items(): if not brand_id: continue brand=brand_ids[brand_id] brand["num_products"]=num def _set_total_num(c): for s in c.get("sub_brands",[]): _set_total_num(s) if c.get("num_products") is None: c["num_products"]=0 for s in c.get("sub_brands",[]): c["num_products"]+=s["num_products"] for c in top_brands: _set_total_num(c) return top_brands
def get_categs(condition): print("get_categs") res=get_model("product").read_group(["categ_id"],condition=condition) categ_nums={} for r in res: categ_id=r["categ_id"][0] if r["categ_id"] else None categ_nums.setdefault(categ_id,0) categ_nums[categ_id]+=r["_count"] res=get_model("product.categ").search_read([],["code","name","parent_id"]) categ_ids={} for r in res: categ_ids[r["id"]]=r top_categs=[] for r in res: parent_id=r["parent_id"][0] if r["parent_id"] else None if parent_id: parent=categ_ids[parent_id] parent.setdefault("sub_categories",[]).append(r) else: top_categs.append(r) for categ_id,num in categ_nums.items(): if not categ_id: continue categ=categ_ids[categ_id] categ["num_products"]=num def _set_total_num(c): for s in c.get("sub_categories",[]): _set_total_num(s) if c.get("num_products") is None: c["num_products"]=0 for s in c.get("sub_categories",[]): c["num_products"]+=s["num_products"] for c in top_categs: _set_total_num(c) return top_categs
def get_last_level(categ): while(get_model("product.categ").search_browse([["parent_id","=",categ.id]])): categ = get_model("product.categ").search_browse([["parent_id","=",categ.id]],order="code")[0] if categ.parent_id: return get_model("product.categ").search_browse([["parent_id","=",categ.parent_id.id]]) else: return None
def copy_to_quotation(self, ids, context): id = ids[0] obj = self.browse(id) vals = { "opport_id": obj.id, "contact_id": obj.contact_id.id, "lines": [], "user_id": obj.user_id.id, } prod = obj.product_id if prod: line_vals = { "product_id": prod.id, "description": prod.name_get()[0][1], "qty": obj.qty or 1, "uom_id": prod.uom_id.id, "unit_price": obj.amount or prod.sale_price, } vals["lines"].append(("create", line_vals)) quot_id = get_model("sale.quot").create(vals, context=context) quot = get_model("sale.quot").browse(quot_id) return { "next": { "name": "quot", "mode": "form", "active_id": quot_id, }, "flash": "Quotation %s created from opportunity" % quot.number }
def make_ui_params_db(): print("building ui_params_db...") user_id = get_active_user() set_active_user(1) try: data = {} data["active_languages"] = get_model("language").get_active_langs() trans = {} db = database.get_connection() res = db.query("SELECT l.code,t.original,t.translation FROM translation t JOIN language l ON l.id=t.lang_id") for r in res: trans.setdefault(r.code, {})[r.original] = r.translation data["translations"] = trans settings = get_model("settings").browse(1) data["date_format"] = settings.date_format or "YYYY-MM-DD" data["use_buddhist_date"] = settings.use_buddhist_date and True or False res = db.query("SELECT action FROM inline_help") data["inline_help"] = {r.action: True for r in res} data["layouts"] = get_model("view.layout").layouts_to_json() data["actions"] = get_model("action").actions_to_json() data["menu_icon"] = settings.menu_icon dbname = database.get_active_db() if not os.path.exists("static/db/%s" % dbname): os.makedirs("static/db/%s" % dbname) s = json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) print(" => static/db/%s/ui_params_db.json" % dbname) open("static/db/%s/ui_params_db.json" % dbname, "w").write(s) finally: set_active_user(user_id)
def get_can_alloc(self, ids, context={}): print("get_can_alloc", ids, context) job_id = context.get("job_id") if not job_id: return {id: None for id in ids} job = get_model("job").browse(job_id) prod_ids = [] for item in job.items: sitem = item.service_item_id if sitem.product_id: prod_ids.append(sitem.product_id.id) print("prod_ids", prod_ids) vals = {} for obj in self.browse(ids): if job.skill_level_id: if obj.skill_level_id and obj.skill_level_id.level < job.skill_level_id.level: vals[obj.id] = False continue if obj.product_categs and prod_ids: categ_ids = [c.id for c in obj.product_categs] res = get_model("product").search([["id", "in", prod_ids], ["categs.id", "child_of", categ_ids]]) if not res: vals[obj.id] = False continue region = job.contact_id.region_id if obj.regions and region: region_ids = [r.id for r in obj.regions] if region.id not in region_ids: vals[obj.id] = False continue vals[obj.id] = True return vals
def reconcile(self, ids, context={}): print("MoveLine.reconcile", ids) rec_id = get_model("account.reconcile").create({}) all_ids = ids[:] for line in self.browse(ids): rec = line.reconcile_id if not rec: continue for rline in rec.lines: all_ids.append(rline.id) all_ids = list(set(all_ids)) acc_id = None for obj in self.browse(all_ids): if not acc_id: acc_id = obj.account_id.id else: if obj.account_id.id != acc_id: acc=get_model("account.account").browse(acc_id) raise Exception("Can only reconcile transactions of same account (%s / %s)"%(obj.account_id.code,acc.code)) self.write(all_ids, {"reconcile_id": rec_id}) inv_ids=[] for obj in self.browse(all_ids): move=obj.move_id rel=move.related_id if rel._model=="account.invoice": inv_ids.append(rel.id) if inv_ids: get_model("account.invoice").function_store(inv_ids)
def get_balance_90d(self, ids, context={}, nocache=False): if not nocache: min_ctime = time.strftime("%Y-%m-%d 00:00:00") vals = get_model("field.cache").get_value("account.account", "balance_90d", ids, min_ctime=min_ctime) remain_ids = [id for id in ids if id not in vals] if remain_ids: res = self.get_balance_90d(remain_ids, context=context, nocache=True) for id, data in res.items(): vals[id] = data get_model("field.cache").set_value("account.account", "balance_90d", id, data) return vals print("#########################################################################") print("get_balance_90d CACHE MISS", ids) date_from = datetime.date.today() - datetime.timedelta(days=90) date_to = datetime.date.today() db = database.get_connection() vals = {} for id in ids: balance = self.get_balance([id], context={"date_to": date_from.strftime("%Y-%m-%d")})[id]["balance"] q = "SELECT move_date,debit,credit FROM account_move_line WHERE account_id=%s AND move_date>%s AND move_date<=%s AND move_state='posted' ORDER BY move_date" res = db.query(q, id, date_from, date_to) d = date_from data = [] for r in res: while d.strftime("%Y-%m-%d") < r["move_date"]: data.append([time.mktime(d.timetuple()) * 1000, balance]) d += datetime.timedelta(days=1) balance += (r["debit"] or 0) - (r["credit"] or 0) while d <= date_to: data.append([time.mktime(d.timetuple()) * 1000, balance]) d += datetime.timedelta(days=1) vals[id] = data return vals
def create_quot(self, ids, context={}): obj = self.browse(ids[0]) vals = { "contact_id": obj.contact_id.id, "job_template_id": obj.job_template_id.id, "lines": [], } tmpl = obj.job_template_id for line in tmpl.lines: prod = line.product_id line_vals = { "product_id": prod.id, "description": line.description, "qty": line.qty, "uom_id": line.uom_id.id, "unit_price": line.unit_price, "tax_id": prod.sale_tax_id.id if prod else None, } vals["lines"].append(("create", line_vals)) quot_id = get_model("sale.quot").create(vals) quot = get_model("sale.quot").browse(quot_id) return { "next": { "name": "quot", "mode": "form", "active_id": quot_id, }, "flash": "Quotation %s created from service order template %s" % (quot.number, tmpl.name), }
def validate(self): with Transaction(): if not self.data["location_id"]: raise Exception("Missing location") vals={ "location_id": self.data["location_id"][0], "lines": [], } for line in self.data["lines"]: prod_id=line["product_id"][0] prod=get_model("product").browse(prod_id) line_vals={ "product_id": prod.id, "prev_qty": line["prev_qty"], "new_qty": line["new_qty"], "uom_id": prod.uom_id.id, } vals["lines"].append(("create",line_vals)) if not vals["lines"]: raise Exception("Empty stock count") count_id=get_model("stock.count").create(vals) get_model("stock.count").validate([count_id]) count=get_model("stock.count").browse(count_id) msg="Stock count %s created successfully"%count.number make_view("message",{"message":msg}).focus() self.render()
def _get_loc_to(self, context={}): print("_get_loc_to", context) data = context.get("data") settings = get_model("settings").browse(1) if data: journal_id = data.get("journal_id") if journal_id: journal = get_model("stock.journal").browse(journal_id) if journal.location_to_id: return journal.location_to_id.id pick_type = context.get("pick_type") pick_type = context.get("pick_type") if pick_type == "in": journal = settings.pick_in_journal_id elif pick_type == "out": journal = settings.pick_out_journal_id elif pick_type == "internal": journal = settings.pick_internal_journal_id else: journal = None if journal and journal.location_from_id: return journal.location_to_id.id if pick_type != "out": return None res = get_model("stock.location").search([["type", "=", "customer"]]) if not res: return None return res[0]
def create(self,vals,*args,**kw): new_id=super().create(vals,*args,**kw) obj=self.browse(new_id) user_id=access.get_active_user() user=get_model("base.user").browse(user_id) if obj.related_id._model=="issue": issue=obj.related_id project=issue.project_id contact=issue.contact_id emails=issue.get_email_addresses() subject="New message by %s for issue %s"%(user.name,issue.number) if obj.subject: subject+=": %s"%obj.subject if emails: vals={ "from_addr": "*****@*****.**", # XXX "to_addrs": ",".join(emails), "subject": subject, "body": obj.body, "state": "to_send", "name_id": "contact,%s"%contact.id, "related_id": "issue,%s"%issue.id, } get_model("email.message").create(vals) return new_id
def update_cost_price(self, context): data = context["data"] path = context["path"] line = get_data_path(data, path, parent=True) cost_price_cur=line["cost_price_cur"] or 0 qty=line["qty"] or 0 currency_id=data["currency_id"] if not currency_id: raise Exception("Missing currency") currency=get_model("currency").browse(currency_id) currency_rate=data["currency_rate"] date=data["date"] settings=get_model("settings").browse(1) if not currency_rate: if currency_id == settings.currency_id.id: currency_rate = 1 else: rate_from = currency.get_rate(date=date) if not rate_from: raise Exception("Missing currency rate for %s" % currency.code) rate_to = settings.currency_id.get_rate(date=date) if not rate_to: raise Exception("Missing currency rate for %s" % settings.currency_id.code) currency_rate = rate_from / rate_to cost_price=get_model("currency").convert(cost_price_cur,currency_id,settings.currency_id.id,rate=currency_rate) cost_amount=cost_price*qty line["cost_price"]=cost_price line["cost_amount"]=cost_amount return data
def get_unit_price(self,ids,context={}): settings=get_model("settings").browse(1) vals={} for obj in self.browse(ids): pick=obj.picking_id if pick: if pick.currency_rate: currency_rate = pick.currency_rate else: if pick.currency_id.id == settings.currency_id.id: currency_rate = 1 else: rate_from = pick.currency_id.get_rate(date=pick.date) if not rate_from: raise Exception("Missing currency rate for %s" % pick.currency_id.code) rate_to = settings.currency_id.get_rate(date=pick.date) if not rate_to: raise Exception("Missing currency rate for %s" % settings.currency_id.code) currency_rate = rate_from / rate_to price=obj.unit_price_cur or 0 price_conv=get_model("currency").convert(price,pick.currency_id.id,settings.currency_id.id,rate=currency_rate) else: price_conv=None vals[obj.id]=price_conv return vals
def create_est_costs(self,ids,context={}): obj=self.browse(ids[0]) del_ids=[] for cost in obj.est_costs: if cost.product_id: del_ids.append(cost.id) get_model("quot.cost").delete(del_ids) #obj.write({"est_costs":[("delete_all",)]}) for line in obj.lines: prod=line.product_id if not prod: continue if not prod.purchase_price: continue if not line.sequence: continue if "bundle" == prod.type: continue vals={ "quot_id": obj.id, "sequence": line.sequence if not line.is_hidden else line.parent_sequence, "product_id": prod.id, "description": prod.name, "supplier_id": prod.suppliers[0].supplier_id.id if prod.suppliers else None, "list_price": prod.purchase_price, "purchase_price": prod.purchase_price, "landed_cost": prod.landed_cost, "purchase_duty_percent": prod.purchase_duty_percent, "purchase_ship_percent": prod.purchase_ship_percent, "qty": line.qty, "currency_id": prod.purchase_currency_id.id, } get_model("quot.cost").create(vals)
def onchange_container(self, context={}): data = context["data"] cont_id = data.get("container_id") if not cont_id: return cont = get_model("stock.container").browse(cont_id) contents = cont.get_contents() lines = [] for (prod_id, lot_id, loc_id), (qty, amt, qty2) in contents.items(): prod = get_model("product").browse(prod_id) line_vals = { "product_id": prod_id, "qty": qty, "uom_id": prod.uom_id.id, "qty2": qty2, "location_from_id": loc_id, "location_to_id": None, "lot_id": lot_id, "container_from_id": cont_id, } if data["type"] == "internal": line_vals["container_to_id"] = cont_id lines.append(line_vals) data["lines"] = lines return data
def do_reconcile(self, ids, context={}): obj = self.browse(ids)[0] account_id = obj.account_id.id cond = [["account_id", "=", account_id]] if obj.contact_id: cond.append(["contact_id", "=", obj.contact_id.id]) if obj.to_date: cond.append(["move_date", "<=", obj.to_date]) num_rec = 0 unrec = {} for line in get_model("account.move.line").search_browse(cond, order="move_id.date,id"): if not line.contact_id: continue if line.reconcile_id and line.reconcile_id.balance < 0: # TODO: speed continue amt = line.debit - line.credit key2 = "%d,%.2f" % (line.contact_id.id, -amt) line2_ids = unrec.get(key2) if line2_ids: line2_id = line2_ids.pop(0) if not line2_ids: del unrec[key2] rec_id = get_model("account.reconcile").create({}) get_model("account.move.line").write([line.id, line2_id], {"reconcile_id": rec_id}) num_rec += 2 else: key = "%d,%.2f" % (line.contact_id.id, amt) unrec.setdefault(key, []).append(line.id) return { "next": { "name": "account_reconcile", }, "flash": "%d transactions reconciled" % num_rec, }
def get_all_balances(date_from=None, date_to=None, track1=None, track2=None): t = time.time() k = (date_from, date_to, track1, track2) if k in _acc_bal_cache: res, res_t = _acc_bal_cache[k] if t - res_t <= 10: print("cache hit", k) return res print("cache miss", k) if track1: res = get_model("account.track.categ").search([["code", "=", track1]]) if not res: raise Exception("Invalid tracking category: %s" % track1) track_id = res[0] else: track_id = None if track2: res = get_model("account.track.categ").search([["code", "=", track2]]) if not res: raise Exception("Invalid tracking category: %s" % track2) track2_id = res[0] else: track2_id = None ctx = { "date_from": date_from, "date_to": date_to, "track_id": track_id, "track2_id": track2_id, } res = get_model("account.account").search_read([["type", "!=", "view"]], ["code", "balance"], context=ctx) _acc_bal_cache[k] = (res, t) return res
def get_plan_out_qty(self, ids, context={}): settings = get_model("settings").browse(1) vals = {} for obj in self.browse(ids): cond = [["state", "in", ["pending", "approved", "done"]], ["date", ">=", obj.date_from + " 00:00:00"], ["date", "<=", obj.date_to + " 23:59:59"], ["product_id", "=", obj.product_id.id], ["location_from_id", "=", obj.location_id.id]] if obj.customer_id: cond.append(["contact_id", "=", obj.customer_id.id]) total = 0 for move in get_model("stock.move").search_browse(cond): total += get_model("uom").convert(move.qty, move.uom_id.id, obj.uom_id.id) vals[obj.id] = total return vals
def onchange_contact(self, context={}): settings = get_model("settings").browse(1) data = context["data"] contact_id = data["contact_id"] contact = get_model("contact").browse(contact_id) data["ship_address_id"] = contact.get_address(pref_type="shipping") if data["type"] == "in": data[ "journal_id"] = contact.pick_in_journal_id.id or settings.pick_in_journal_id.id elif data["type"] == "out": data[ "journal_id"] = contact.pick_out_journal_id.id or settings.pick_out_journal_id.id elif data["type"] == "internal": data[ "journal_id"] = contact.pick_internal_journal_id.id or settings.pick_internal_journal_id.id self.onchange_journal(context=context) return data
def _get_product_ids(self, context={}): order_id = int(context["refer_id"]) order = get_model("production.order").browse(order_id) prods = [] for comp in order.components: prods.append(comp.product_id.id) prods.append(order.product_id.id) return prods
def save_changes(self, ids, context={}): obj = self.browse(ids)[0] check_password(obj.password) vals = { "name": obj.name, "password": obj.password, "email": obj.email, "mobile": obj.mobile, } user_id = get_active_user() set_active_user(1) get_model("base.user").write([user_id], vals) obj.write({"password": ""}) set_active_user(user_id) return { "next": "_close", }
def migrate(self): res = get_model("partner.relation.type").search_browse([]) if res: print("Contact relations already created") return vals = { "name": "Sub-contact", } type_id = get_model("partner.relation.type").create(vals) for obj in get_model("partner").search_browse([]): if obj.partner_id: vals = { "from_partner_id": obj.id, "to_partner_id": obj.partner_id.id, "rel_type_id": type_id, } get_model("partner.relation").create(vals)
def delete(self, ids, context={}): sale_ids = [] purch_ids = [] for inv in self.browse(ids): if inv.inv_type not in ("prepay", "overpay"): if inv.state not in ("draft", "waiting_approval", "voided"): raise Exception("Can't delete invoice with this status") for line in inv.lines: if line.sale_id: sale_ids.append(line.sale_id.id) if line.purch_id: purch_ids.append(line.purch_id.id) super(Invoice, self).delete(ids, context=context) if sale_ids: get_model("sale.order").function_store(sale_ids) if purch_ids: get_model("purchase.order").function_store(purch_ids)
def gen_tax_no(self, context={}): seq_id = get_model("sequence").find_sequence(type="wht_no", context=context) if not seq_id: return None while 1: num = get_model("sequence").get_next_number(seq_id, context=context) if not num: return None user_id = get_active_user() set_active_user(1) res = self.search([["tax_invoice", "=", num]]) set_active_user(user_id) if not res: return num get_model("sequence").increment_number(seq_id, context=context)
def get_balance_90d(self, ids, context={}, nocache=False): if not nocache: min_ctime = time.strftime("%Y-%m-%d 00:00:00") vals = get_model("field.cache").get_value("stock.location", "balance_90d", ids, min_ctime=min_ctime) remain_ids = [id for id in ids if id not in vals] if remain_ids: res = self.get_balance_90d(remain_ids, context=context, nocache=True) for id, data in res.items(): vals[id] = data get_model("field.cache").set_value("stock.location", "balance_90d", id, data) return vals print( "#########################################################################" ) print("location.get_balance_90d CACHE MISS", ids) date_from = datetime.date.today() - datetime.timedelta(days=90) date_to = datetime.date.today() db = database.get_connection() vals = {} for id in ids: balance = self.get_balance( [id], context={"date_to": date_from.strftime("%Y-%m-%d")})[id] q = "SELECT date,location_from_id,location_to_id,cost_amount FROM stock_move WHERE (location_from_id=%s OR location_to_id=%s) AND date>%s AND date<=%s AND state='done' ORDER BY date" res = db.query(q, id, id, date_from.strftime("%Y-%m-%d 23:59:59"), date_to.strftime("%Y-%m-%d 23:59:59")) d = date_from data = [] for r in res: while d.strftime("%Y-%m-%d 23:59:59") < r.date: data.append([time.mktime(d.timetuple()) * 1000, balance]) d += datetime.timedelta(days=1) if r.location_to_id == id and r.location_from_id != id: balance += r.cost_amount or 0 elif r.location_from_id == id and r.location_to_id != id: balance -= r.cost_amount or 0 while d <= date_to: data.append([time.mktime(d.timetuple()) * 1000, balance]) d += datetime.timedelta(days=1) vals[id] = data return vals
def get_product_list(self, order_id): prods = [] order = get_model("production.order").browse(order_id) if order: for comp in order.components: prods.append(comp.product_id.id) prods.append(order.product_id.id) return prods
def to_pending(self, ids, context={}): settings = get_model("settings").browse(1) obj = self.browse(ids)[0] if settings.lock_date: assert obj.date_purchase >= settings.lock_date, "Accounting transaction is before lock date" if obj.state not in ("registered", "sold", "disposed"): raise Exception("Invalid state") obj.write({"state": "pending"})
def onchange_book(self, context={}): data = context["data"] path = context["path"] line = get_data_path(data, path, parent=True) book_id = line["book_id"] book = get_model("bookstore.book").browse(book_id) line["unit_price"] = book.cost return data
def get_split_container(self, prev_cont_num, order_num, context={}): part_no = order_num.rpartition("-")[2] if not part_no or not part_no.startswith("P") or not len(part_no) == 3: raise Exception( "Can not find split part number of production order %s" % order_num) new_cont_num = prev_cont_num + "-" + part_no res = get_model("stock.container").search( [["number", "=", new_cont_num]]) if res: new_cont_id = res[0] else: vals = { "number": new_cont_num, } new_cont_id = get_model("stock.container").create(vals) return new_cont_id
def get_number_receive(self, ids, context={}): print("Hello ===========================>") res = {} for obj in self.browse(ids): receive_ptc = get_model("petty.cash.fund").search( [['number_receive', '!=', None]]) res[obj.id] = receive_ptc return res
def get_invoice(s): s = s.strip() if not s: return None res = get_model("account.invoice").search([["number", "=", s]]) if not res: raise Exception("Invoice not found: %s" % s) return res[0]
def dispose_depreciation(self,ids,context): obj=self.browse(ids)[0] if obj.asset_id.last_dep: d_from=datetime.strptime(obj.asset_id.last_dep,"%Y-%m-%d")+timedelta(days=1) else: d_from=datetime.strptime(obj.asset_id.date_purchase,"%Y-%m-%d") d_to=datetime.strptime(obj.date,"%Y-%m-%d") days = (d_to - d_from).days+1 if days > 30: raise Exception(" (Last depreciation : %s ) - (Date : %s ) Over 30 Days, Please Check Date"%(obj.asset_id.last_dep,obj.date)) elif days <= 0: raise Exception(" (Last depreciation : %s ) - (Date : %s ) less 0 Days, Please Check Date"%(obj.asset_id.last_dep,obj.date)) narration = "Fixed asset depreciation [%s] %s"%((obj.asset_id.number or ""),(obj.asset_id.name or "")) get_model("account.fixed.asset").depreciate([obj.asset_id.id],obj.date,context={"narration":narration}) return { "flash":"registered assets (%s) are depreciated to %s"%(obj.asset_id.number,obj.date), }
def is_avail_search(self, clause, context={}): print("is_avail_search", clause, context) time_start = context.get("time_start") time_stop = context.get("time_stop") job_id = context.get("job_id") if job_id: job = get_model("job").browse(job_id) if job.state == "planned": job.write({"state": "allocated"}) if not time_start or not time_stop: return [] ids = [] for alloc in get_model("service.resource.alloc").search_browse( [["time_stop", ">", time_start], ["time_start", "<", time_stop]]): ids.append(alloc.resource_id.id) ids = list(set(ids)) return [["id", "not in", ids]]
def get_account(s): s = s.strip() if not s: return None res = get_model("account.account").search([["code", "=", s]]) if not res: raise Exception("Account not found: %s" % s) return res[0]
def get(self): db = get_connection() try: set_active_user(1) action = self.get_argument("action") res = get_model("inline.help").search([["action", "=", action]]) if not res: raise Exception("Inline help not found for action '%s'" % action) page_id = res[0] page = get_model("inline.help").browse(page_id) self.write(page.content) db.commit() except: import traceback traceback.print_exc() db.rollback()
def fill_qc_tests(self, ids, context={}): obj = self.browse(ids)[0] prod_order = obj.production_id if not prod_order: raise Exception("Please select production order") for qc_test in prod_order.qc_tests: vals = { "barcode_id": obj.id, "test_id": qc_test.test_id.id, "sample_qty": qc_test.sample_qty, "value": qc_test.value, "min_value": qc_test.min_value, "max_value": qc_test.max_value, "result": qc_test.result, "prod_qc_id": qc_test.id } get_model("barcode.qc.line").create(vals)
def get_tax_rate(s): s = s.strip() if not s: return None res = get_model("account.tax.rate").search([["code", "=", s]]) if not res: raise Exception("Tax rate not found: %s" % s) return res[0]
def migrate(self): res = get_model("account.journal").search([]) if res: print("Journals already created") return vals = { "name": "General", "type": "general", } gen_id = get_model("account.journal").create(vals) vals = { "name": "Sales", "type": "sale", } sale_id = get_model("account.journal").create(vals) vals = { "name": "Purchases", "type": "purchase", } purch_id = get_model("account.journal").create(vals) vals = { "name": "Receipts", "type": "pay_in", } pay_in_id = get_model("account.journal").create(vals) vals = { "name": "Disbursements", "type": "pay_out", } pay_out_id = get_model("account.journal").create(vals) vals = { "general_journal_id": gen_id, "sale_journal_id": sale_id, "purchase_journal_id": purch_id, "pay_in_journal_id": pay_in_id, "pay_out_journal_id": pay_out_id, } get_model("company").write([1], vals) for move in get_model("account.move").search_browse([]): journal_id = gen_id if move.invoice_id: if move.invoice_id.type == "out": journal_id = sale_id elif move.invoice_id.type == "in": journal_id = purch_id elif move.payment_id: if move.payment_id.type == "in": journal_id = pay_in_id elif move.payment_id.type == "out": journal_id = pay_out_id move.write({"journal_id": journal_id})
def copy_to_invoice(self,ids,context={}): inv_vals = { "type": "out", "inv_type": "invoice", "lines": [], } for obj in self.browse(ids): if obj.invoice_id: raise Exception("Invoice already created for work time %s"%obj.id) project=obj.project_id contact=project.contact_id if inv_vals.get("contact_id"): if contact.id!=inv_vals["contact_id"]: raise Exception("Different contacts") else: inv_vals["contact_id"]=contact.id resource=obj.resource_id prod=resource.product_id if not prod: raise Exception("Missing product for work time %d"%obj.id) if not prod.sale_account_id: raise Exception("Missing sales account in product %s"%prod.code) line_vals = { "product_id": prod.id, "description": obj.description or "/", "qty": line.bill_hours or 0, "uom_id": prod.uom_id.id, "unit_price": prod.sale_price or 0, "account_id": prod.sale_account_id.id, "tax_id": prod.sale_tax_id.id if prod else None, "amount": (line.bill_hours or 0)*(prod.sale_price or 0), "related_id": "work.time,%s"%obj.id, } inv_vals["lines"].append(("create", line_vals)) if not inv_vals["lines"]: raise Exception("Nothing to invoice") inv_id = get_model("account.invoice").create(inv_vals, {"type": "out", "inv_type": "invoice"}) self.write(ids,{"invoice_id": inv_id}) inv = get_model("account.invoice").browse(inv_id) return { "next": { "name": "view_invoice", "active_id": inv_id, }, "flash": "Invoice %s created from work time" % inv.number, }
def onchange_uom(self, context): data = context["data"] path = context["path"] line = get_data_path(data, path, parent=True) prod_id = line.get("product_id") if not prod_id: return {} prod = get_model("product").browse(prod_id) uom_id = line.get("uom_id") if not uom_id: return {} uom = get_model("uom").browse(uom_id) if prod.sale_price is not None: line[ "unit_price"] = prod.sale_price * uom.ratio / prod.uom_id.ratio data = self.update_amounts(context) return data
def _get_number(self, context={}): seq_id = get_model("sequence").find_sequence(type="sale_forecast", context=context) if not seq_id: return None while 1: num = get_model("sequence").get_next_number(seq_id, context=context) if not num: return None user_id = access.get_active_user() access.set_active_user(1) res = self.search([["number", "=", num]]) access.set_active_user(user_id) if not res: return num get_model("sequence").increment_number(seq_id, context=context)
def payment_error(self,context={}): res=super().payment_error(context=context) if res: return res transaction_no=context.get("transaction_no") res=get_model("sale.order").search([["transaction_no","=",transaction_no]]) if not res: return sale_id=res[0] settings=get_model("ecom2.settings").browse(1) if settings.ecom_return_url: url=settings.ecom_return_url+str(sale_id) else: url="/ui#name=sale&mode=form&active_id=%d"%sale_id return { "next_url": url, }
def approve(self, ids, context={}): settings = get_model("settings").browse(1) for obj in self.browse(ids): for move in obj.lines: move.write({"state": "approved", "date": obj.date}) obj.write({"state": "approved"}) if obj.type == "out" and settings.auto_create_delivery_order and obj.ship_method_id and not obj.ship_tracking: obj.create_delivery_order()
def get_amount(self, ids, context={}): vals = {} settings = get_model("settings").browse(1) sale_ids=[] for line in self.browse(ids): sale_ids.append(line.order_id.id) sale_ids=list(set(sale_ids)) for sale in get_model("sale.order").browse(sale_ids): prod_qtys={} prom_amts={} prom_pcts={} for line in sale.lines: prod_qtys.setdefault(line.product_id.id,0) prod_qtys[line.product_id.id]+=line.qty for line in sale.used_promotions: if line.amount and line.product_id: prom_amts.setdefault(line.product_id.id,0) prom_amts[line.product_id.id]+=line.amount elif line.percent: prom_pcts.setdefault(line.product_id.id,0) prom_pcts[line.product_id.id]+=line.percent for line in sale.lines: amt = line.qty * line.unit_price if line.discount: disc = amt * line.discount / 100 else: disc = 0 if line.discount_amount: disc += line.discount_amount amt-=disc amt_before_prom=amt prom_amt=prom_amts.get(line.product_id.id,Decimal(0))/prod_qtys[line.product_id.id]*line.qty prom_pct=prom_pcts.get(line.product_id.id,Decimal(0))+prom_pcts.get(None,0) if prom_pct: prom_amt+=math.ceil(amt_before_prom/line.qty*prom_pct/100)*line.qty if prom_amt: amt-=prom_amt order = line.order_id vals[line.id] = { "amount": amt, "amount_cur": get_model("currency").convert(amt, order.currency_id.id, settings.currency_id.id), "amount_discount": disc, "promotion_amount": prom_amt, } return vals
def create_est_costs(self, ids, context={}): obj = self.browse(ids[0]) del_ids = [] for cost in obj.est_costs: if cost.product_id: del_ids.append(cost.id) get_model("quot.cost").delete(del_ids) #obj.write({"est_costs":[("delete_all",)]}) for line in obj.lines: prod = line.product_id if not prod: continue if not prod.purchase_price: continue if not line.sequence: continue if "bundle" == prod.type: continue vals = { "quot_id": obj.id, "sequence": line.sequence if not line.is_hidden else line.parent_sequence, "product_id": prod.id, "description": prod.name, "supplier_id": prod.suppliers[0].supplier_id.id if prod.suppliers else None, "list_price": prod.purchase_price, "purchase_price": prod.purchase_price, "landed_cost": prod.landed_cost, "purchase_duty_percent": prod.purchase_duty_percent, "purchase_ship_percent": prod.purchase_ship_percent, "qty": line.qty, "currency_id": prod.purchase_currency_id.id, } get_model("quot.cost").create(vals)
def copy_to_credit_note(self, ids, context={}): id = ids[0] obj = self.browse(id) contact = obj.contact_id inv_vals = { "type": "in", "inv_type": "credit", "ref": obj.number, "related_id": "purchase.return,%s" % obj.id, "contact_id": obj.contact_id.id, "currency_id": obj.currency_id.id, "lines": [], "tax_type": obj.tax_type, } if contact.purchase_journal_id: inv_vals["journal_id"] = contact.purchase_journal_id.id if contact.purchase_journal_id.sequence_id: inv_vals["sequence_id"] = contact.purchase_journal_id.sequence_id.id for line in obj.lines: prod = line.product_id remain_qty = line.qty - line.qty_invoiced if remain_qty <= 0: continue line_vals = { "product_id": prod.id, "description": line.description, "qty": remain_qty, "uom_id": line.uom_id.id, "unit_price": line.unit_price, "account_id": prod and prod.purchase_account_id.id or None, "tax_id": line.tax_id.id, "amount": line.amount, } inv_vals["lines"].append(("create", line_vals)) if not inv_vals["lines"]: raise Exception("Nothing left to invoice") inv_id = get_model("account.invoice").create(inv_vals, {"type": "in", "inv_type": "invoice"}) inv = get_model("account.invoice").browse(inv_id) return { "next": { "name": "view_invoice", "active_id": inv_id, }, "flash": "Credit note %s created from purchase return %s" % (inv.number, obj.number), }
def create_track_entries(self, ids, context={}): obj = self.browse(ids[0]) settings = get_model("settings").browse(1) for line in obj.lines: if line.track_id: amt = line.credit - line.debit if line.track_id.currency_id: amt = get_model("currency").convert( amt, settings.currency_id.id, line.track_id.currency_id.id) vals = { "date": obj.date, "track_id": line.track_id.id, "amount": amt, "description": line.description, "move_id": obj.id, } get_model("account.track.entry").create(vals) if line.track2_id: amt = line.credit - line.debit if line.track2_id.currency_id: amt = get_model("currency").convert( amt, settings.currency_id.id, line.track2_id.currency_id.id) vals = { "date": obj.date, "track_id": line.track2_id.id, "amount": amt, "description": line.description, "move_id": obj.id, } get_model("account.track.entry").create(vals)