def onchange_range(self, dtrange, date_from, date_till, resetRange=False): value = {} res = { "value" : value } if not date_from or resetRange: if dtrange == "month": date_from = util.getFirstOfLastMonth() elif dtrange == "week": day = util.strToDate(util.currentDate()) day = day - relativedelta(days=(7+day.weekday())) date_from = util.dateToStr(day) else: day = util.strToDate(util.currentDate()) day = day - relativedelta(days=1) date_from = util.dateToStr(day) if dtrange == "month": dt_date_from = util.strToDate(date_from) date_till = util.dateToStr(dt_date_from + relativedelta(months=1,days=-1)) elif dtrange == "week": dt_date_from = util.strToDate(date_from) weekday = dt_date_from.weekday() date_till = util.dateToStr(dt_date_from + relativedelta(days=weekday+(6-weekday))) else: date_till = date_from value["date_from"] = date_from value["date_till"] = date_till return res
def _active_version(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids) date = context and context.get( "date", util.currentDate()) or util.currentDate() cr.execute( "SELECT v.pricelist_id, v.id " " FROM product_pricelist_version AS v " " WHERE v.pricelist_id IN %s AND active=True " " AND (date_start is NULL OR date_start <= %s) " " AND (date_end is NULL OR date_end >= %s ) " " GROUP BY 1,2 ", (tuple(ids), date, date)) for row in cr.fetchall(): res[row[0]] = row[1] return res
def onchange_user(self, cr, uid, ids, date, hours, user_id): if uid == user_id: ts_obj = self.pool.get("hr_timesheet_sheet.sheet") ts_day = ts_obj.get_timesheet_day(cr, uid, util.currentDate()) if ts_day: return {"value": {"hours": ts_day.total_difference}} return {}
def _send_report(self, start_date=None, session=None): if not start_date: start_date = util.currentDate() for report_email in self.search([]): offset = -1 has_pos = False # check for main pos to send, or delay one day pos = report_email.pos_id if pos and session and session.config_id.id == pos.id: has_pos = True offset = 0 # send last... mail_range = report_email._cashreport_range(start_date, offset) has_report = report_email.range_start < mail_range[0] and mail_range[1] < start_date # ... or current if has_pos and mail_range[1] == start_date: has_report = True if has_report: report_email._send_mail(mail_range[0]) range_start = mail_range[0] # send other if report_email.range_start: while True: mail_range = report_email._cashreport_range(mail_range[0], -1) if report_email.range_start < mail_range[0]: report_email._send_mail(mail_range[0]) else: break report_email.range_start = range_start
def logbook_weeks(self): weeks = [] f = format.LangFormat(self._cr, self._uid, self._context) week_start = util.getFirstOfWeek(self.date_start) date_end = self.date_end or util.getPrevDayDate( util.getFirstOfNextWeek(util.currentDate())) while week_start <= date_end: week_str = datetime.strftime(util.strToDate(week_start), _("CW %W")) week_first = week_start week_start = util.getFirstOfNextWeek(week_start) week_end = util.getPrevDayDate(week_start) weeks.append({ "name": week_str, "date_start": week_first, "group": week_first[:7], "start": f.formatLang(week_first, date=True), "end": f.formatLang(week_end, date=True) }) weeks.sort(key=lambda v: v["date_start"], reverse=True) return weeks
class academy_advance_payment(osv.Model): def _default_semester_id(self, cr, uid, context=None): # get current semester user = self.pool["res.users"].browse(cr, uid, uid, context) semester = user.company_id.academy_semester_id if semester: return semester.id return None def unlink(self, cr, uid, ids, context=None): ids = util.idList(ids) for payment in self.browse(cr, uid, ids, context): if payment.invoice_id: raise osv.except_osv( _("Error"), _("Payment which is posted could not deleted")) super(academy_advance_payment, self).unlink(cr, uid, ids, context=context) _name = "academy.payment" _description = "Advance Payment" _rec_name = "reg_id" _columns = { "date": fields.date("Date", required=True), "reg_id": fields.many2one("academy.registration", "Registration", select=True, required=True), "semester_id": fields.many2one("academy.semester", "Semester", select=True, required=True), "amount": fields.float("Amount", digits_compute=dp.get_precision('Account'), required=True), "ref": fields.char("Reference", select=True), "invoice_id": fields.many2one("account.invoice", "Invoice", select=True, readonly=True), "voucher_id": fields.many2one("account.voucher", "Voucher", select=True, readonly=True) } _defaults = { "date": util.currentDate(), "semester_id": _default_semester_id }
class academy_journal(osv.Model): _name = "academy.journal" _description = "Academy Journal" def onchange_topic(self, cr, uid, ids, topic_id, context=None): res = {"value": {}} if topic_id: topic = self.pool.get("academy.topic").browse(cr, uid, topic_id) res["value"]["name"] = str(topic.name) + "\n" + str( topic.description) res["value"]["duration"] = topic.duration res["value"]["course_id"] = topic.course_id.id return res _columns = { "name": fields.text("Name"), "date": fields.date("Date", required=True), "begin": fields.float( "Begin", help= "The time must be between 00:00 and 24:00 o'clock and must not be bigger than the end" ), "end": fields.float("End", help="The time must be between 00:00 and 24:00 o'clock"), "topic_id": fields.many2one("academy.topic", "Topic", required=True), "student_ids": fields.many2many("res.partner", "res_partner_journal_rel", "partner_id", "journal_id", "Students"), "absence_ids": fields.one2many("academy.journal.absence", "journal_id", "Absences"), "trainer_id": fields.many2one("academy.trainer", "Trainer", required=True), "course_id": fields.related("topic_id", "course_id", type="many2one", readonly=True, relation="academy.course", string="Course"), "duration": fields.float("Unit(s)"), "expenses": fields.float("Transport Expenses"), "place": fields.char("Place", size=64) } _defaults = { "date": util.currentDate(), }
def __init__(self, cr, uid, name, context): super(Parser, self).__init__(cr, uid, name, context) self.localcontext.update({ "accounts_get": self._accounts_get, "date_from_get": self._date_from_get, "date_to_get": self._date_to_get, "code_str": self._code_str, "name_str": self._name_str, "debit_str": self._debit_str, "credit_str": self._credit_str, "balance_str": self._balance_str, }) self.localcontext["report_title"] = context.get( "report_title", _("Balance list")) self.localcontext["date_from"] = context.get( "date_from", util.getFirstOfMonth(util.currentDate())) self.localcontext["date_to"] = context.get( "date_to", util.getEndOfMonth(util.currentDate()))
def _default_logbook_id(self): logbooks = self.env["farm.chicken.logbook"].search([("state", "=", "active")]) default_day = util.currentDate() for logbook in logbooks: logs = self.search([("logbook_id", "=", logbook.id), ("day", "=", default_day)]) if not logs: return logbook.id return None
def _check_birthday(self, cr, uid): dt_current = util.strToDate(util.currentDate()) date_search = "%%-%02d-%02d" % (dt_current.month,dt_current.day) template_xmlid = "partner_birthday_mail.email_partner_birthday" partner_ids = self.search(cr, uid, [("birthday","ilike",date_search)]) template_obj = self.pool["email.template"] template_id = self.pool["ir.model.data"].xmlid_to_res_id(cr, uid, template_xmlid) if template_id: for partner in self.browse(cr, uid, partner_ids): template_obj.send_mail(cr, uid, template_id, partner.id, force_send=True)
def _get_contract(self, cr, uid, employee_id, date_from=None, date_to=None, context=None): if not date_from: date_from = util.currentDate() if not date_to: date_to = date_from contract_obj = self.pool["hr.contract"] # fetch contracts cr.execute( "SELECT c.id FROM hr_contract c" " WHERE c.employee_id = %s " " AND (c.date_start IS NULL OR (c.date_start <= %s AND (c.date_end IS NULL OR c.date_end >= %s) OR (c.date_start <= %s AND c.date_start >= %s)) )" " ORDER BY c.date_start DESC ", (employee_id, date_from, date_from, date_to, date_from)) contract_ids = [r[0] for r in cr.fetchall()] # return if not found if not contract_ids: return None # validate range for contract in contract_obj.browse(cr, uid, contract_ids, context=context): # check working_hours if not contract.working_hours: continue # validate range if date_from < contract.date_start: date_from = contract.date_start if contract.date_end and contract.date_end < date_to: date_to = contract.date_end # check date_to if date_to < date_from: continue return { "contract": contract, "working_hours": contract.working_hours, "date_from": date_from, "date_to": date_to } return None
def _cashreport_range(self, start_date=None, offset=0): if not start_date: start_date = util.currentDate() cashreport_name = _("Cashreport") date_from = start_date date_till = start_date f = format.LangFormat(self._cr, self._uid, self._context) # calc month if self.range == "month": dt_date_from = util.strToDate(util.getFirstOfMonth(start_date)) if offset: dt_date_from += relativedelta(months=offset) date_from = util.dateToStr(dt_date_from) date_till = util.getEndOfMonth(dt_date_from) month_name = helper.getMonthName(self._cr, self._uid, dt_date_from.month, context=self._context) cashreport_name = "%s - %s %s" % (cashreport_name, month_name, dt_date_from.year) # calc week elif self.range == "week": dt_date_from = util.strToDate(start_date) if offset: dt_date_from += relativedelta(weeks=offset) weekday = dt_date_from.weekday() dt_date_from = dt_date_from + relativedelta(days=-weekday) kw = dt_date_from.isocalendar()[1] date_from = util.dateToStr(dt_date_from) date_till = util.dateToStr(dt_date_from + relativedelta(days=weekday + (6 - weekday))) cashreport_name = _("%s - CW %s %s") % (cashreport_name, kw, dt_date_from.year) # calc date else: if offset: dt_date_from = util.strToDate(start_date) dt_date_from += relativedelta(days=offset) date_from = util.dateToStr(dt_date_from) date_till = date_from cashreport_name = _("%s - %s") % (cashreport_name, f.formatLang(date_from, date=True)) return (date_from, date_till, cashreport_name)
def _get_semester_id(self, cr, uid, context=None): # get current semester user = self.pool["res.users"].browse(cr, uid, uid, context) semester = user.company_id.academy_semester_id if semester: return semester.id # search semester based on date if current semester is not set semester_obj = self.pool["academy.semester"] #search next semester semester_ids = semester_obj.search( cr, uid, [("date_start", ">", util.currentDate())], order="date_start asc") if not semester_ids: # get current semester return semester_obj.search_id(cr, uid, [], order="date_end desc") return semester_ids and semester_ids[0] or None
def _prepare_cost_invoice(self, cr, uid, partner, company_id, currency_id, analytic_lines, context=None): res = super(account_analytic_line, self)._prepare_cost_invoice(cr, uid, partner, company_id, currency_id, analytic_lines, context=context) line_ids = [l.id for l in analytic_lines] account = analytic_lines[0].account_id f = format.LangFormat(cr, uid, context) cr.execute("SELECT MIN(line.date), MAX(line.date) " \ "FROM account_analytic_line as line " \ "WHERE account_id = %s " \ "AND id IN %s AND to_invoice IS NOT NULL", (account.id, tuple(line_ids))) invoice_name = None for date_from, date_to in cr.fetchall(): if date_from and date_to: invoice_name = "%s %s - %s" % ( account.name or "",f.formatLang(date_from,date=True), f.formatLang(date_to,date=True)) if not invoice_name: invoice_name = "%s %s" % (account.name or "",f.formatLang(util.currentDate(),date=True)) res["name"] = invoice_name return res
def _get_date_planned(self, cr, uid, order, line, start_date, context=None): start_date = util.strToTime(start_date) company = order.company_id date_planned = None real_delay = (line.delay or 0.0) - company.security_lead if real_delay: if company.calendar_id: date_planned = self.pool.get('resource.calendar').passed_range( cr, uid, company.calendar_id.id, start_date, real_delay)["to"] else: date_planned = start_date + relativedelta(days=real_delay) if date_planned: date_planned = util.timeToStr(date_planned) else: return util.currentDate() return date_planned
def _prepare_invoice_data(self, cr, uid, contract, context=None): invoice = super(account_analytic_account, self)._prepare_invoice_data(cr, uid, contract, context=context) # invoice name to contract name invoice["name"] = contract.name # determine user user_id = contract.manager_id or contract.user_id if user_id: invoice["user_id"] = user_id.id # determine shop if contract.shop_id: invoice["shop_id"] = contract.shop_id.id else: # shop from template template = contract.template_id if template and template.shop_id: invoice["shop_id"] = template.shop_id.id else: parent = contract.parent_id if parent: # get shop from parent if parent.shop_id: invoice["shop_id"] = parent.shop_id.id else: # shop from autocreate shop_obj = self.pool["sale.shop"] shop_ids = shop_obj.search(cr, uid, [("autocreate_order_parent_id","=",parent.id)], limit=2) if not shop_ids: shop_ids = shop_obj.search(cr, uid, [("project_id","=",parent.id)], limit=2) # check if only one shop is assinged if len(shop_ids) == 1: invoice["shop_id"] = shop_ids[0] # performance period if contract.recurring_invoices: # get next date function def getNextDate(cur_date,sign=1): interval = contract.recurring_interval*sign if contract.recurring_rule_type == 'daily': return cur_date+relativedelta(days=+interval) elif contract.recurring_rule_type == 'weekly': return cur_date+relativedelta(weeks=+interval) elif contract.recurring_rule_type == 'monthly': return cur_date+relativedelta(months=+interval) else: return cur_date+relativedelta(years=+interval) cur_date = util.strToDate(contract.recurring_next_date or util.currentDate()) if contract.recurring_prepaid: invoice["perf_enabled"] = True invoice["perf_start"] = cur_date invoice["perf_end"] = getNextDate(cur_date) else: invoice["perf_enabled"] = True invoice["perf_start"] = getNextDate(cur_date,-1) invoice["perf_end"] = cur_date # first of month and last of month if contract.recurring_rule_type == 'monthly': invoice["perf_end"] = util.strToDate(util.getEndOfMonth(invoice["perf_end"])) if contract.recurring_interval > 0: interval = -(contract.recurring_interval-1) invoice["perf_start"] = util.strToDate(util.getFirstOfMonth(invoice["perf_end"]))+relativedelta(months=interval) # convert dt to str invoice["perf_start"] = util.dateToStr(invoice["perf_start"]) invoice["perf_end"] = util.dateToStr(invoice["perf_end"]) return invoice
def _send_mail(self, start_date=None): if not start_date: start_date = start_date = util.currentDate() mail_obj = self.pool["mail.mail"] mail_tmpl_obj = self.pool["email.template"] att_obj = self.pool["ir.attachment"] rzl_obj = self.env["fpos.wizard.export.rzl"] bmd_obj = self.env["fpos.wizard.export.bmd"] config_obj = self.env["pos.config"] data_obj = self.pool["ir.model.data"] template_id = data_obj.xmlid_to_res_id(self._cr, self._uid, "fpos.email_report", raise_if_not_found=True) mail_context = self._context and dict(self._context) or {} mail_context["start_date"] = start_date mail_range = self._cashreport_range(start_date) mail_context["cashreport_name"] = mail_range[2] # check options if self.detail: mail_context["print_detail"] = True if self.separate: mail_context["no_group"] = True if self.product: mail_context["print_product"] = True # build config config_ids = [] if self.pos_ids: for pos in self.pos_ids: config_ids.append(pos.id) else: for config in config_obj.search([("liveop", "=", True)]): config_ids.append(config.id) # add report info mail_context["pos_report_info"] = { "from": mail_range[0], "till": mail_range[1], "name": mail_range[2], "config_ids": config_ids, } attachment_ids = [] if self.rzl_export or self.bmd_export: session_ids = self._session_ids(mail_range) # export rzl if self.rzl_export: rzl_data = rzl_obj.with_context(active_model="pos.session", active_ids=session_ids).default_get( ["data", "data_name"] ) attachment_ids.append( att_obj.create( self._cr, self._uid, { "name": rzl_data["data_name"], "datas_fname": rzl_data["data_name"], "datas": rzl_data["data"], }, context=self._context, ) ) # export bmd if self.bmd_export: bmd_data = bmd_obj.with_context(active_model="pos.session", active_ids=session_ids).default_get( ["data", "data_name"] ) attachment_ids.append( att_obj.create( self._cr, self._uid, {"name": "buerf", "datas_fname": "buerf", "datas": bmd_data["buerf"]}, context=self._context, ) ) # write msg_id = mail_tmpl_obj.send_mail( self._cr, self._uid, template_id, self.id, force_send=False, context=mail_context ) if attachment_ids: mail = mail_obj.browse(self._cr, self._uid, msg_id, context=self._context) # link with message att_obj.write( self._cr, self._uid, attachment_ids, {"res_model": "mail.message", "res_id": mail.mail_message_id.id}, context=self._context, ) # add attachment ids to message mail_obj.write( self._cr, self._uid, [msg_id], {"attachment_ids": [(4, oid) for oid in attachment_ids]}, context=self._context, ) # send mail_obj.send(self._cr, self._uid, [msg_id], context=mail_context)
class chicken_log(models.Model): @api.one def _parent_log(self): parent_house = self.logbook_id.house_id.parent_id if parent_house: parent_logs = self.search([("logbook_id.house_id", "=", parent_house.id), ("day", "=", self.day)]) return parent_logs and parent_logs[0] or None @api.multi def action_draft(self): return self.write({"state": "draft"}) @api.one def _validate_inv(self): # get childs parent = self.parent_id if not parent: parent = self logs = [parent] logs.extend(parent.child_ids) # get invoice logs inv_logs = [] non_inv_logs = [] inv_parent = False delivered = False for log in logs: if log.delivered: delivered = True if log.inv_exists: inv_logs.append(log) if log.id == parent.id: inv_parent = True else: non_inv_logs.append(log) # check if invoice exist if inv_logs: for inv_log in inv_logs: inv_log.inv_hierarchy = True # check if parent has no invoice if not inv_parent: # sumup invoice fields inv_fields = {} for inv_field in self._inv_fields: val = inv_logs[0][inv_field] for inv_log in inv_logs[1:]: val += inv_log[inv_field] inv_fields[inv_field] = val # set it to parent for inv_field, val in inv_fields.iteritems(): parent[inv_field] = val if delivered: parent.delivered = delivered else: for log in logs: log.inv_hierarchy = False return True @api.multi def action_validate(self): for log in self: log._validate_inv() logs_after = log.search([("logbook_id", "=", self.logbook_id.id), ("day", ">", self.day)], order="day desc") logs_after._validate_inv() return self.write({"state": "valid"}) @api.one @api.depends("loss", "loss_fix", "loss_fix_amount") def _compute_loss_total(self): # add loss without fix self._cr.execute( "SELECT SUM(COALESCE(loss,0)) FROM farm_chicken_log l " " WHERE l.logbook_id = %s AND l.day <= %s AND NOT COALESCE(l.loss_fix,False) ", (self.logbook_id.id, self.day)) res = self._cr.fetchone() loss_total = res and res[0] or 0 # add loss with fix self._cr.execute( "SELECT SUM(COALESCE(loss_fix_amount,0)) FROM farm_chicken_log l " " WHERE l.logbook_id = %s AND l.day <= %s AND l.loss_fix ", (self.logbook_id.id, self.day)) res = self._cr.fetchone() loss_total += res and res[0] or 0 self.loss_total = loss_total self.loss_amount = self.loss if self.loss_fix: self.loss_amount = self.loss_fix_amount @api.one @api.depends("loss") def _compute_loss_total_real(self): self._cr.execute( "SELECT SUM(COALESCE(loss,0)) FROM farm_chicken_log l " " WHERE l.logbook_id = %s AND l.day <= %s ", (self.logbook_id.id, self.day)) res = self._cr.fetchone() loss_total = res and res[0] or 0 self.loss_total_real = loss_total @api.one @api.depends("loss_total_real", "loss") def _compute_chicken_count(self): self.chicken_count = self.logbook_id.chicken_count - self.loss_total_real @api.one @api.depends("eggs_total", "eggs_removed") def _compute_eggs_count(self): self._cr.execute( "SELECT SUM(COALESCE(eggs_total,0))-SUM(COALESCE(eggs_removed,0))-(SUM(COALESCE(delivered_eggs_mixed,0))+SUM(COALESCE(delivered_eggs_industry,0))) FROM farm_chicken_log l " " WHERE l.logbook_id = %s AND l.day <= %s ", (self.logbook_id.id, self.day)) res = self._cr.fetchone() self.eggs_count = res and res[0] or None @api.one @api.depends("delivered_eggs_mixed", "delivered_eggs_industry", "inv_eggs_xl", "inv_eggs_m", "inv_eggs_l", "inv_eggs_s", "inv_eggs_s45g", "inv_eggs_industry", "inv_eggs_presorted") def _compute_delivery(self): self.delivered_eggs = self.delivered_eggs_mixed + self.delivered_eggs_industry self.inv_eggs = self.inv_eggs_xl + self.inv_eggs_l + self.inv_eggs_m + self.inv_eggs_s + self.inv_eggs_s45g + self.inv_eggs_industry + self.inv_eggs_presorted self.inv_diff_eggs = self.inv_eggs - self.delivered_eggs self.inv_diff_presorted = self.inv_eggs_presorted - self.delivered_eggs_industry @api.one @api.depends("logbook_id.date_start", "logbook_id.chicken_age") def _compute_chicken_age(self): logbook = self.logbook_id dt_start = util.strToDate(logbook.date_start) dt_cur = util.strToDate(self.day) diff = dt_cur - dt_start self.chicken_age = logbook.chicken_age + diff.days self.chicken_age_weeks = self.chicken_age / 7.0 @api.one @api.depends("eggs_total", "chicken_count") def _compute_eggs_performance(self): if self.chicken_count: self.eggs_performance = 100.0 / self.chicken_count * self.eggs_total else: self.eggs_performance = 0.0 @api.model def _default_logbook_id(self): logbooks = self.env["farm.chicken.logbook"].search([("state", "=", "active")]) default_day = util.currentDate() for logbook in logbooks: logs = self.search([("logbook_id", "=", logbook.id), ("day", "=", default_day)]) if not logs: return logbook.id return None @api.one @api.depends("day", "logbook_id", "logbook_id.house_id", "logbook_id.house_id.parent_id") def _compute_parent_id(self): if self.state != "done": parent_log = None parent_house = self.logbook_id.house_id.parent_id if parent_house: # assign parent log parent_log = self.search([("day", "=", self.day), ("logbook_id.state", "=", "active"), ("logbook_id.house_id", "=", parent_house.id)]) # create parent if not exist if parent_log: parent_log = parent_log[0] self.parent_id = parent_log @api.one def _validate(self, values=None): if self.state != "done": parent = self.parent_id # validate parent parent_house = self.logbook_id.house_id.parent_id if not parent and parent_house: logbook_obj = self.env["farm.chicken.logbook"] parent_logbook = logbook_obj._get_active(parent_house.id) if parent_logbook: self.parent_id = self.create({ "logbook_id": parent_logbook.id, "day": self.day }) parent = self.parent_id # check if parent exists # and validate if parent: # check for validate if values: validate_fields = [] for field in self._forward_fields: if field in values: validate_fields.append(field) else: validate_fields = self._forward_fields # validate fields if validate_fields: childs = parent.child_ids if childs: values = self.read(validate_fields)[0] for key in validate_fields: val = values[key] for child in childs: if child.id == self.id: continue val += child[key] values[key] = val parent.write(values) @api.multi def _calc_beyond(self): for field in ("chicken_count", "chicken_age", "chicken_age_weeks", "eggs_performance"): self._fields[field]._compute_value(self) def _create(self, cr, uid, vals, context=None): res = super(chicken_log, self)._create(cr, uid, vals, context=context) # validate log = self.browse(cr, uid, res, context=context) log._validate(vals) # validate beyond log._calc_beyond() return res def _write(self, cr, uid, ids, vals, context=None): # check invalid invalid_ids = [] if "loss" in vals: for stored_vals in self.search_read(cr, uid, [("id", "in", ids)], ["loss"], order="day asc", context=context): if vals.get("loss", 0) != stored_vals["loss"]: invalid_ids.append(stored_vals["id"]) # write res = super(chicken_log, self)._write(cr, uid, ids, vals, context=context) # validate self.browse(cr, uid, ids, context=context)._validate(vals) # validate beyond if invalid_ids: cr.execute( "SELECT l.logbook_id, MIN(l.day) FROM farm_chicken_log l WHERE l.id IN %s GROUP BY 1", (tuple(invalid_ids), )) for logbook_id, day in cr.fetchall(): log_ids = self.search(cr, uid, [("logbook_id", "=", logbook_id), ("day", ">", day)], order="day asc") self.browse(cr, uid, log_ids, context=context)._calc_beyond() return res _name = "farm.chicken.log" _description = "Log" _inherit = ["mail.thread"] _order = "day desc, logbook_id" _rec_name = "day" _forward_fields = ["feed", "water", "eggs_machine"] _inv_fields = [ "delivered_eggs_mixed", "delivered_eggs_industry", "inv_eggs_xl", "inv_eggs_m", "inv_eggs_l", "inv_eggs_s", "inv_eggs_s45g", "inv_eggs_industry", "inv_eggs_presorted" ] _calc_fields = ["loss", "eggs_total"] _sql_constraints = [("date_uniq", "unique(logbook_id, day)", "Only one log entry per day allowed!")] logbook_id = fields.Many2one("farm.chicken.logbook", "Logbook", required=True, index=True, readonly=True, states={'draft': [('readonly', False)]}, default=_default_logbook_id, ondelete="restrict") day = fields.Date("Day", required=True, readonly=True, index=True, states={'draft': [('readonly', False)]}, default=lambda self: util.currentDate()) loss = fields.Integer("Loss", readonly=True, states={'draft': [('readonly', False)]}) loss_fix = fields.Boolean("Loss Fix", readonly=True, states={'draft': [('readonly', False)]}) loss_fix_amount = fields.Integer("Loss Fix Amount", readonly=True, states={'draft': [('readonly', False)]}) loss_total = fields.Integer("Loss Total", readonly=True, compute="_compute_loss_total") loss_total_real = fields.Integer("Real Loss", readonly=True, compute="_compute_loss_total_real") loss_amount = fields.Integer("Loss Amount", readonly=True, compute="_compute_loss_total") weight = fields.Float("Weight [kg]", readonly=True, states={'draft': [('readonly', False)]}) feed_manual = fields.Boolean("Manual Feed Input", readonly=True, states={'draft': [('readonly', False)]}) feed = fields.Float("Feet [kg]", readonly=True, states={'draft': [('readonly', False)]}) water = fields.Float("Water [l]", readonly=True, states={'draft': [('readonly', False)]}) co2 = fields.Float("Co2", readonly=True, states={'draft': [('readonly', False)]}) temp = fields.Float("Temperature [°C]", readonly=True, states={'draft': [('readonly', False)]}) humidity = fields.Float("Humidity [%]", readonly=True, states={'draft': [('readonly', False)]}) eggs_total = fields.Integer("Eggs Total", readonly=True, states={'draft': [('readonly', False)]}) eggs_machine = fields.Integer("Eggs Machine", readonly=True, states={'draft': [('readonly', False)]}) eggs_nest = fields.Integer("Nest Eggs", readonly=True, states={'draft': [('readonly', False)]}) eggs_top = fields.Integer("Eggs moved above", readonly=True, states={'draft': [('readonly', False)]}) eggs_buttom = fields.Integer("Eggs laid down", readonly=True, states={'draft': [('readonly', False)]}) eggs_weight = fields.Float("Eggs Weight [g]", readonly=True, states={'draft': [('readonly', False)]}) eggs_dirty = fields.Integer("Dirty Eggs", readonly=True, states={'draft': [('readonly', False)]}) eggs_broken = fields.Integer("Broken Eggs", readonly=True, states={'draft': [('readonly', False)]}) eggs_color = fields.Selection( [ (1, "01"), (2, "02"), (3, "03"), (4, "04"), (5, "05"), (6, "06"), (7, "07"), (8, "08"), (9, "09"), (10, "10"), (11, "11"), (12, "12"), (13, "13"), (14, "14"), (15, "15"), ], string="Eggs Color", help="Color aligned to the DSM Yolk Color Fan", readonly=True, states={'draft': [('readonly', False)]}) eggs_color_dote = fields.Selection( [(1, "01"), (2, "02"), (3, "03"), (4, "04"), (5, "05")], string="Eggs Dote Color", help="Color aligned to the DSM Yolk Color Fan", readonly=True, states={'draft': [('readonly', False)]}) eggs_thickness = fields.Float("Eggs Thickness [kg]", readonly=True, states={'draft': [('readonly', False)]}) state = fields.Selection([("draft", "Draft"), ("valid", "Valid"), ("done", "Done")], string="State", default="draft") eggs_removed = fields.Integer("Eggs Removed", readonly=True, states={'draft': [('readonly', False)]}) chicken_age = fields.Integer("Chicken Age [Days]", readonly=True, compute="_compute_chicken_age", store=True) chicken_age_weeks = fields.Integer("Chicken Age [Weeks]", readonly=True, compute="_compute_chicken_age", store=True) chicken_count = fields.Integer("Chicken Count", readonly=True, compute="_compute_chicken_count", store=True) eggs_count = fields.Integer("Eggs Stock", readonly=True, compute="_compute_eggs_count") eggs_performance = fields.Float("Eggs Performance", readonly=True, compute="_compute_eggs_performance", store=True) delivered = fields.Boolean("Delivery", readonly=True, states={'draft': [('readonly', False)]}) delivered_eggs_mixed = fields.Integer( "Delivered Eggs", readonly=True, states={'draft': [('readonly', False)]}) delivered_eggs_industry = fields.Integer( "Delivered Eggs Industry", readonly=True, states={'draft': [('readonly', False)]}) delivered_eggs = fields.Integer("Delivered Eggs Total", readonly=True, compute="_compute_delivery", store=True) inv_exists = fields.Boolean( "Invoice Exists", help="Standalone invoice for the delivery exists", states={'draft': [('readonly', False)]}) inv_hierarchy = fields.Boolean("Invoice in Hierarchy Exists") inv_eggs_xl = fields.Integer("Invoiced Eggs XL", readonly=True, states={'draft': [('readonly', False)]}) inv_eggs_l = fields.Integer("Invoiced Eggs L", readonly=True, states={'draft': [('readonly', False)]}) inv_eggs_m = fields.Integer("Invoiced Eggs M", readonly=True, states={'draft': [('readonly', False)]}) inv_eggs_s = fields.Integer("Invoiced Eggs S", readonly=True, states={'draft': [('readonly', False)]}) inv_eggs_s45g = fields.Integer("Invoiced Eggs < 45g", readonly=True, states={'draft': [('readonly', False)]}) inv_eggs_industry = fields.Integer("Invoiced Eggs Industry", readonly=True, states={'draft': [('readonly', False)]}) inv_eggs_presorted = fields.Integer( "Invoiced Eggs Industry (presorted)", readonly=True, states={'draft': [('readonly', False)]}) inv_eggs = fields.Integer("Invoiced Eggs Total", readonly=True, compute="_compute_delivery", store=True) inv_diff_eggs = fields.Integer("Eggs Difference", readonly=True, compute="_compute_delivery", store=True) inv_diff_presorted = fields.Integer("Eggs Difference (presorted)", readonly=True, compute="_compute_delivery", store=True) child_ids = fields.One2many("farm.chicken.log", "parent_id", string="Child Logs", readonly=True) parent_id = fields.Many2one("farm.chicken.log", string="Parent Log", compute="_compute_parent_id", readonly=True, store=True) note = fields.Text("Note")
def logbook_week(self, date_start=None): if not date_start: date_start = util.currentDate() f = format.LangFormat(self._cr, self._uid, self._context) week_start = util.getFirstOfWeek(date_start) week_next = util.getFirstOfNextWeek(date_start) week_str = datetime.strftime(util.strToDate(week_start), _("CW %W")) week_day = week_start week_end = week_day days = [] log_obj = self.env["farm.chicken.log"] sum_loss = 0 first_weight = 0.0 valid_count = 0 fill_count = 0 day_count = 0 chicken_count = 0 avg_data = {} def getAvg(name, calc=True): data = avg_data.get(name, None) if data is None: data = {"val": [], "avg": 0.0} avg_data[name] = data if calc: val = data["val"][:7] val_len = len(val) if val_len: data["avg"] = sum(val) / val_len return data def addAvg(name, val): if val: data = getAvg(name, calc=False) data["val"].insert(0, val) return val # get 14 logs for average calc logByDay = {} logs = log_obj.search([("logbook_id", "=", self.id), ("day", "<", week_next)], limit=14, order="day desc") if logs: # set new start week_day_avg = logs[-1].day if week_day_avg < week_day: week_day = week_day_avg # assign log for log in logs: logByDay[log.day] = log chicken_age_weeks = 0 while week_day < week_next: week_end = week_day loss = 0 loss_fix = False loss_fix_amount = 0 loss_amount = 0 eggs_performance = 0.0 weight = 0 eggs_total = 0 eggs_broken = 0 eggs_dirty = 0 eggs_weight = 0 eggs_machine = 0 chicken_age = 0 feed = 0 water = 0 valid = False filled = False note = "" log = logByDay.get(week_day) if log: loss = log.loss loss_amount = log.loss_amount or 0 loss_fix = log.loss_fix loss_fix_amount = log.loss_fix_amount eggs_total = addAvg("eggs_total", log.eggs_total) eggs_broken = addAvg("eggs_broken", log.eggs_broken) eggs_dirty = addAvg("eggs_dirty", log.eggs_dirty) eggs_weight = addAvg("eggs_weight", log.eggs_weight) eggs_machine = addAvg("eggs_machine", log.eggs_machine) eggs_performance = addAvg("eggs_performance", log.eggs_performance) feed = addAvg("feed", log.feed) water = addAvg("water", log.water) weight = log.weight if weight and not first_weight: first_weight = weight chicken_count = log.chicken_count note = log.note or note chicken_age_weeks = log.chicken_age_weeks chicken_age = log.chicken_age valid = log.state != "draft" filled = True if filled: day_count += 1 sum_loss += loss_amount # add day only if within week if week_day >= week_start: if filled: fill_count += 1 if valid: valid_count += 1 days.append({ "name": format_date(util.strToDate(week_day), "E d.M.y", locale=self._context.get("lang") or tools.config.defaultLang), "day": week_day, "loss": loss, "loss_fix": loss_fix, "loss_fix_amount": loss_fix_amount, "eggs_total": eggs_total, "eggs_broken": eggs_broken, "eggs_dirty": eggs_dirty, "eggs_weight": eggs_weight, "eggs_machine": eggs_machine, "weight": weight, "note": note, "valid": valid, "filled": filled, "chicken_age_weeks": chicken_age_weeks, "overview": [{ "name": _("Eggs Total"), "value": "%s" % eggs_total }, { "name": _("Eggs Machine"), "value": "%s" % eggs_machine }, { "name": _("Broken Eggs"), "value": "%s" % eggs_broken }, { "name": _("Dirty Eggs"), "value": "%s" % eggs_dirty }, { "name": _("Eggs Weight"), "value": "%s g" % f.formatLang(eggs_weight) }, { "name": _("Egg Performance"), "value": "%s %%" % f.formatLang(eggs_performance) }, { "name": _("Loss"), "value": "%s" % loss_amount }, { "name": _("Chicken Count"), "value": "%s" % chicken_count }, { "name": _("Chicken Weight"), "value": "%s kg" % f.formatLang(weight) }, { "name": _("Day Age"), "value": "%s" % chicken_age }, { "name": _("Feed"), "value": "%s kg" % f.formatLang(feed, digits=0) }, { "name": _("Water"), "value": "%s l" % f.formatLang(water) }] }) week_day = util.getNextDayDate(week_day) days_len = len(days) return { "name": "%s %s" % (self.name, week_str), "week": week_str, "date": week_start, "start": f.formatLang(week_start, date=True), "end": f.formatLang(week_end, date=True), "filled": days_len == fill_count, "validated": days_len == valid_count, "days": days, "overview": [{ "name": _("Eggs"), "value": "%s" % f.formatLang(getAvg("eggs_total")["avg"]) }, { "name": _("Eggs Machine"), "value": "%s" % f.formatLang(getAvg("eggs_machine")["avg"]) }, { "name": _("Broken Eggs"), "value": "%s" % f.formatLang(getAvg("eggs_broken")["avg"]) }, { "name": _("Dirty Eggs"), "value": "%s" % f.formatLang(getAvg("eggs_dirty")["avg"]) }, { "name": _("Eggs Weight"), "value": "%s g" % f.formatLang(getAvg("eggs_weight")["avg"]) }, { "name": _("Egg Performance"), "value": "%s %%" % f.formatLang(getAvg("eggs_performance")["avg"]) }, { "name": _("Loss"), "value": "%s" % sum_loss, }, { "name": _("Chicken Count"), "value": "%s" % chicken_count }, { "name": _("Chicken Weight"), "value": "%s kg" % f.formatLang(first_weight) }, { "name": _("Week Age"), "value": "%s" % chicken_age_weeks }, { "name": _("Feed"), "value": "%s kg" % f.formatLang(getAvg("feed")["avg"], digits=0) }, { "name": _("Water"), "value": "%s l" % f.formatLang(getAvg("water")["avg"]) }] }
def action_create_contract(self, cr, uid, ids, context=None): account_obj = self.pool["account.analytic.account"] project_obj = self.pool["project.project"] for line in self.browse(cr, uid, ids, context=context): if line.is_contract: contract = None contract_id = False contract_ids = [] if line.contract_id: contract = line.contract_id contract_id = line.contract_id.id contract_ids = [contract_id] # check if not line.contract_name or not line.contract_start: raise Warning(_("No contract name or start date for %s") % line.name) if line.contract_start < util.currentDate(): raise Warning(_("Contract start date is before current date for %s") % line.name) if line.contract_end and line.contract_end < line.contract_start: raise Warning(_("Contract end date is before contract start date %s" % line.name)) # check task specific if line.is_task: if not line.contract_start_task: raise Warning(_("No task start date for %s") % line.name) if line.contract_start_task < util.currentDate(): raise Warning(_("Task start date is before current date for %s") % line.name) # get values values = self._prepare_contract(cr, uid, line, context=context) if not values: continue product = line.product_id recurring_tmpl = product.recurring_tmpl_id recurring_task = False # partner values helper.onChangeValuesPool(cr, uid, account_obj, values, account_obj.on_change_partner_id(cr, uid, contract_ids, values.get("partner_id"), name=values.get("name"), context=context), context=context) if recurring_tmpl: # recurring values values["template_id"] = recurring_tmpl.id helper.onChangeValuesPool(cr, uid, account_obj, values, account_obj.on_change_template(cr, uid, contract_ids, recurring_tmpl.id, date_start=values.get("date_start"), context=context), context=context) # check if tonract already exist if contract: # recurring task update if not values.get("recurring_task_ids") and contract.recurring_task_ids: recurring_task_update = [] for rec_task in contract.recurring_task_ids: recurring_task_update.append((1,rec_task.id, { "name": rec_task.name, "product_id": rec_task.product_id.id, "description": rec_task.description, "planned_hours": rec_task.planned_hours, "repeat": rec_task.repeat })) values["recurring_task_ids"] = recurring_task_update # recurring invoice update if not values.get("recurring_invoice_line_ids") and contract.recurring_invoice_line_ids: recurring_inv_update = [] for rec_inv in contract.recurring_invoice_line_ids: recurring_inv_update.append((1, rec_inv.id, { "product_id": rec_inv.product_id.id, "uom_id": rec_inv.uom_id.id, "name": rec_inv.name, "quantity": rec_inv.quantity, "price_unit": rec_inv.price_unit })) values["recurring_invoice_line_ids"] = recurring_inv_update else: # build on product # check if task should created automatically if product.auto_create_task: values["recurring_task"] = True values["recurring_interval"] = product.recurring_interval values["recurring_task_rule"] = product.recurring_rule_type values["recurring_task_next"] = line.contract_start_task # check for existing task line recurring_task_id = 0 recurring_found = 0 if contract: for recurring_task in contract.recurring_task_ids: recurring_task_id = recurring_task.id recurring_found = 1 # prepare recurrent task template values["recurring_task_ids"] = [(recurring_found, recurring_task_id, { "name": line.name.split("\n")[0], "product_id": line.product_id.id, "description": line.procurement_note, "planned_hours": product.planned_hours })] # billed at cost task if product.auto_create_task and product.billed_at_cost: values["invoice_on_timesheets"] = True # enable invoice on timesheets helper.onChangeValuesPool(cr, uid, account_obj, values, account_obj.onchange_invoice_on_timesheets(cr, uid, contract_ids, True, context=context), context=context) else: values["recurring_invoices"] = True values["recurring_interval"] = product.recurring_interval values["recurring_rule_type"] = product.recurring_rule_type # check for existing line recurring_invoice_line_id = 0 recurring_found = 0 if contract: for recurring_invoice_line in contract.recurring_invoice_line_ids: recurring_invoice_line_id = recurring_invoice_line.id recurring_found = 1 # only create invoice if it isn't a billed at cost task values["recurring_invoice_line_ids"] = [(recurring_found, recurring_invoice_line_id, { "product_id": product.id, "uom_id": line.product_uom.id, "name": line.name, "quantity": line.product_uom_qty, "price_unit": line.price_unit })] # calc contract self._calc_contract(cr, uid, line, values, context) if contract_id: # update account_obj.write(cr, uid, contract_id, values, context=context) else: # create shop = line.order_id.shop_id project_template = shop.project_template_id if project_template: project_id = project_obj.copy(cr, uid, project_template.id, values, context=context) account_id = project_obj.browse(cr, uid, project_id, context=context).analytic_account_id.id self.write(cr, uid, line.id, {"contract_id": account_id}, context=context) else: account_id = account_obj.create(cr, uid, values, context=context) self.write(cr, uid, line.id, {"contract_id": account_id}, context=context) return True
def model_copy(self, cr, uid, ids, context=None): for row in self.read(cr, uid, ids, context=context): if not row.get('cron_id', False): continue cron_ids = [row['cron_id'][0]] remaining = self.pool.get('ir.cron').read( cr, uid, cron_ids, ['numbercall'])[0]['numbercall'] model = None try: (model_name, oid) = row['doc_source'].split(',') oid = int(oid) model = self.pool.get(model_name) except: raise osv.except_osv( _('Wrong Source Document !'), _('Please provide another source document.\nThis one does not exist !' )) default = {'state': 'draft'} doc_obj = self.pool.get('subscription.document') document_ids = doc_obj.search(cr, uid, [('model.model', '=', model_name)]) doc = doc_obj.browse(cr, uid, document_ids)[0] for f in doc.field_ids: value = False if f.value == 'date': value = util.currentDate() elif f.value == 'text' and f.value_text: field_values = {} curDate = util.currentDate() it = re.finditer(PATTERN_TEXTSUBST, f.value_text) for m in it: field_name = m.group(1) if (field_name == "year"): field_values[field_name] = util.formatDate( curDate, "%Y") elif (field_name == "month"): field_values[field_name] = util.formatDate( curDate, "%m") elif (field_name == "month_name"): field_values[field_name] = helper.getMonth( cr, uid, curDate, context) else: field_values[field_name] = model.read( cr, uid, oid, [field_name], context)[field_name] value = f.value_text % field_values default[f.field.name] = value state = 'running' # if there was only one remaining document to generate # the subscription is over and we mark it as being done if remaining == 1: state = 'done' copy_id = model.copy(cr, uid, oid, default, context) self.pool.get('subscription.subscription.history').create( cr, uid, { 'subscription_id': row['id'], 'date': time.strftime('%Y-%m-%d %H:%M:%S'), 'document_id': model_name + ',' + str(copy_id) }) self.write(cr, uid, [row['id']], {'state': state}) return True
def do_assumption(self, cr, uid, ids, context=None): btakeover_line_obj = self.pool.get("account.btakeover.line") account_obj = self.pool.get("account.account") move_obj = self.pool.get("account.move") journal_obj = self.pool.get("account.journal") period_obj = self.pool.get("account.period") #currency_obj = self.pool.get("res.currency") #currency_id = currency_obj.search(cr, uid, [("symbol", "=", "€")]) user = self.pool.get("res.users").browse(cr, uid, uid) for btakeover in self.browse(cr, uid, ids): for line in btakeover.line_ids: account_ids = account_obj.search( cr, uid, [("code", "=", line.code), ("company_id", "=", user.company_id.id)]) account_id = account_ids and account_ids[0] or None if account_id: balance = account_obj._compute_account( cr, uid, [account_id], date_till=btakeover.date, context=context)[account_id] balance_is = float(balance["balance"]) balance_diff = balance_is - line.balance_nominal else: raise osv.except_osv( _('Error'), _('There is no account for the entered code!')) name = str( journal_obj.create_sequence( cr, uid, { "name": btakeover.journal_id.name, "code": btakeover.journal_id.code }, context)) date = btakeover.date if not date: date = util.currentDate() period = period_obj.search( cr, uid, [("date_start", "=", util.getFirstOfMonth(date))]) account = account_obj.browse(cr, uid, account_id) values = { "name": name, "ref": _("Balance Correction %s" % (btakeover.name)), "period_id": period[0], "journal_id": btakeover.journal_id.id, "date": date, "amount": line.balance_nominal, "line_id": [(0, 0, { "name": name, "account_id": btakeover.account_id.id, "currency_id": account.currency_id.id, "period_id": period[0], "journal_id": btakeover.journal_id.id, "debit": balance_diff > 0.0 and balance_diff or 0.0, "credit": balance_diff < 0.0 and (balance_diff * -1) or 0.0 }), (0, 0, { "name": name, "account_id": account_id, "currency_id": account.currency_id.id, "period_id": period[0], "journal_id": btakeover.journal_id.id, "debit": balance_diff < 0.0 and (balance_diff * -1) or 0.0, "credit": balance_diff > 0.0 and balance_diff or 0.0 })] } move_id = move_obj.create(cr, uid, values, context) btakeover_line_obj.write( cr, uid, line.id, { "state": "assumed", "move_id": move_id, "balance_is": balance_is }, context) self.write(cr, uid, btakeover.id, { "state": "assumed", "date": date }) return True
class account_btakeover(osv.osv): def copy_data(self, cr, uid, id, default=None, context=None): if not default: default = {} btakeover = self.browse(cr, uid, id) default.update({"state": "draft", "name": btakeover.name + _(" copy")}) res = super(account_btakeover, self).copy_data(cr, uid, id, default, context) return res def do_draft(self, cr, uid, ids, context): btakeover_line_obj = self.pool.get("account.btakeover.line") move_obj = self.pool.get("account.move") for record in self.browse(cr, uid, ids): for line in record.line_ids: btakeover_line_obj.write(cr, uid, line.id, {"state": "draft"}, context) move_obj.button_cancel(cr, uid, [line.move_id.id], context=context) move_obj.unlink(cr, uid, [line.move_id.id], context=context) self.write(cr, uid, record.id, {"state": "draft"}) return True def do_assumption(self, cr, uid, ids, context=None): btakeover_line_obj = self.pool.get("account.btakeover.line") account_obj = self.pool.get("account.account") move_obj = self.pool.get("account.move") journal_obj = self.pool.get("account.journal") period_obj = self.pool.get("account.period") #currency_obj = self.pool.get("res.currency") #currency_id = currency_obj.search(cr, uid, [("symbol", "=", "€")]) user = self.pool.get("res.users").browse(cr, uid, uid) for btakeover in self.browse(cr, uid, ids): for line in btakeover.line_ids: account_ids = account_obj.search( cr, uid, [("code", "=", line.code), ("company_id", "=", user.company_id.id)]) account_id = account_ids and account_ids[0] or None if account_id: balance = account_obj._compute_account( cr, uid, [account_id], date_till=btakeover.date, context=context)[account_id] balance_is = float(balance["balance"]) balance_diff = balance_is - line.balance_nominal else: raise osv.except_osv( _('Error'), _('There is no account for the entered code!')) name = str( journal_obj.create_sequence( cr, uid, { "name": btakeover.journal_id.name, "code": btakeover.journal_id.code }, context)) date = btakeover.date if not date: date = util.currentDate() period = period_obj.search( cr, uid, [("date_start", "=", util.getFirstOfMonth(date))]) account = account_obj.browse(cr, uid, account_id) values = { "name": name, "ref": _("Balance Correction %s" % (btakeover.name)), "period_id": period[0], "journal_id": btakeover.journal_id.id, "date": date, "amount": line.balance_nominal, "line_id": [(0, 0, { "name": name, "account_id": btakeover.account_id.id, "currency_id": account.currency_id.id, "period_id": period[0], "journal_id": btakeover.journal_id.id, "debit": balance_diff > 0.0 and balance_diff or 0.0, "credit": balance_diff < 0.0 and (balance_diff * -1) or 0.0 }), (0, 0, { "name": name, "account_id": account_id, "currency_id": account.currency_id.id, "period_id": period[0], "journal_id": btakeover.journal_id.id, "debit": balance_diff < 0.0 and (balance_diff * -1) or 0.0, "credit": balance_diff > 0.0 and balance_diff or 0.0 })] } move_id = move_obj.create(cr, uid, values, context) btakeover_line_obj.write( cr, uid, line.id, { "state": "assumed", "move_id": move_id, "balance_is": balance_is }, context) self.write(cr, uid, btakeover.id, { "state": "assumed", "date": date }) return True _name = "account.btakeover" _columns = { "name": fields.char("Name", size=64, required=True), "date": fields.date("Date"), "journal_id": fields.many2one("account.journal", "Journal", required=True, domain=[("type", "=", "general")]), "line_ids": fields.one2many("account.btakeover.line", "btakeover_id", "Lines"), "state": fields.selection([("draft", "Draft"), ("assumed", "Assumed")], "State", readonly=True), "account_id": fields.many2one("account.account", "Account", required=True) } _defaults = { "date": util.currentDate(), "state": "draft", }
def _build_sheet(self, cr, uid, date_from=None, date_to=None, months=None, employee=None, sheets=None, context=None): # check context date if not context is None: if not date_from: date_from = context.get("date_from") if not date_to: date_to = context.get("date_to") # check months if date_from and months: date_to = util.getNextDayOfMonth(date_from, inMonth=months) # if employ was passed if employee: date_cur = util.currentDate() if not date_from: date_from = util.getFirstOfMonth(date_cur) if not date_to: date_to = util.getEndOfMonth(date_cur) cr.execute( "SELECT s.id FROM hr_timesheet_sheet_sheet s " " WHERE (( s.date_from <= %s AND s.date_to >= %s) " " OR ( s.date_from <= %s AND s.date_to >= %s) " " OR ( s.date_from >= %s AND s.date_to <= %s)) " " AND s.employee_id = %s " " ORDER BY s.date_from ", (date_from, date_from, date_to, date_to, date_from, date_to, employee.id)) sheet_ids = [r[0] for r in cr.fetchall()] sheets = self.browse(cr, uid, sheet_ids, context=context) # if sheets was passed elif sheets: if not date_from: date_from = sheets[0].date_from if not date_to: date_to = sheets[-1].date_to # return if no sheet if not sheets or not date_from or not date_to: return None cr.execute( "SELECT s.id FROM hr_timesheet_sheet_sheet s " " WHERE s.date_to = ( SELECT MAX(s2.date_to) FROM hr_timesheet_sheet_sheet s2 " " WHERE s2.date_to < %s AND s2.employee_id = s.employee_id )" " AND s.employee_id = %s " " ORDER BY s.date_from ", (sheets[0].date_from, sheets[0].employee_id.id)) query_res = cr.fetchall() sheet_before = None if query_res: sheet_before = self.browse(cr, uid, query_res[0][0], context=context) days = [] res = { "date_from": date_from, "date_to": date_to, "days": days, "employee": sheets[0].employee_id } dt_to = util.strToDate(date_to) dt_from = util.strToDate(date_from) total_timesheet = 0.0 total_target = 0.0 total = 0.0 total_saldo = 0.0 current_saldo = 0.0 leaves_taken = 0.0 sick_leaves = 0.0 last_saldo = 0.0 remaining_leaves = sheets[0].remaining_leaves max_leaves = sheets[0].remaining_leaves if sheet_before: current_saldo = sheet_before.current_saldo last_saldo = current_saldo leave_obj = self.pool.get("resource.calendar.leaves") timesheet_line_obj = self.pool.get("hr.analytic.timesheet") for sheet in sheets: timesheet_data = self.get_timesheet_data(cr, sheet.user_id.id, sheet.id, context=context) sheet_dt_from = util.strToDate(sheet.date_from) sheet_dt_cur = sheet_dt_from sheet_dt_to = util.strToDate(sheet.date_to) delta_day = relativedelta(days=1) while sheet_dt_cur <= sheet_dt_to and sheet_dt_cur <= dt_to: date_day = util.dateToStr(sheet_dt_cur) timesheet_day = timesheet_data.get(date_day) if timesheet_day: # vars day_saldo = timesheet_day.get("total_saldo") or 0.0 # increment saldo current_saldo += day_saldo # check if date is in date from if sheet_dt_cur >= dt_from: # get vars day_total_timesheet = timesheet_day.get( "total_timesheet_day") or 0.0 day_target = timesheet_day.get("total_target") or 0.0 day_attendance = timesheet_day.get( "total_attendance_day") or 0.0 # get attendance attendance = [] attendance_text = [] attendance_lines = timesheet_day.get( "attendances", None) if attendance_lines: for attendance_line in attendance_lines: timestamp_to = attendance_line["to"] time_only = timestamp_to and timestamp_to.split( " ")[1] or None if time_only != "24:00:00": time_from = util.timeToStrHours( attendance_line["from"]) time_to = util.timeToStrHours(timestamp_to) attendance_text.append( "%s - %s" % (time_from, time_to)) attendance.append({ "time_from": time_from, "time_to": time_to }) # get work work = timesheet_line_obj.browse(cr, uid, timesheet_day.get( "lines", []), context=context) # process leaves leaves = timesheet_day.get("leaves", []) leave_names = [] for leave in leave_obj.browse(cr, uid, [l[0] for l in leaves], context=context): leave_names.append(leave.name) if leave.name: attendance_text.append(leave.name) holiday = leave.holiday_id holiday_status = holiday.holiday_status_id if holiday_status: holiday_categ = holiday_status.categ_id if holiday_categ: if holiday_categ.leave_type == "holiday": leaves_taken += 1 if holiday_categ.leave_type == "sickness": sick_leaves += 1 # ONLY ONE LEAVE per DAY break # increment counters total_timesheet += day_total_timesheet total_target += day_target total += day_attendance total_saldo += day_saldo day = { "day": date_day, "total_timesheet": day_total_timesheet, "total": day_attendance, "total_saldo": day_saldo, "total_target": day_target, "current_saldo": current_saldo, "attendance": attendance, "attendance_text": "\n".join(attendance_text), "work": work, "leaves": leave_names, "leaves_taken": leaves_taken, "remaining_leaves": remaining_leaves, "sick_leaves": sick_leaves, "sheet": sheet } days.append(day) elif sheet_dt_cur < dt_from: last_saldo = current_saldo # next day sheet_dt_cur += delta_day res["max_leaves"] = max_leaves res["last_saldo"] = last_saldo res["current_saldo"] = current_saldo res["leaves_taken"] = leaves_taken res["remaining_leaves"] = remaining_leaves res["total_timesheet"] = total_timesheet res["total_target"] = total_target res["sick_leaves"] = sick_leaves res["total"] = total res["total_saldo"] = total_saldo return res
def _recurring_task_create(self, cr, uid, ids, automatic=False, context=None): if context is None: context = {} task_ids = [] current_date = util.currentDate() if ids: contract_ids = ids else: contract_ids = self.search(cr, uid, [("use_tasks","=",True), ("recurring_task_next","<=", current_date), ("state","=", "open"), ("recurring_task","=", True), ("type", "=", "contract")]) if contract_ids: task_obj = self.pool["project.task"] recurring_task_obj = self.pool["account.analytic.recurring.task"] project_obj = self.pool["project.project"] f = format.LangFormat(cr, uid, context) cr.execute("SELECT company_id, array_agg(id) as ids FROM account_analytic_account WHERE id IN %s GROUP BY company_id", (tuple(contract_ids),)) for company_id, ids in cr.fetchall(): context_contract = dict(context, company_id=company_id, force_company=company_id) for contract in self.browse(cr, uid, ids, context=context_contract): project_ids = project_obj.search(cr, uid, [("analytic_account_id","=",contract.id)], context=context_contract) if not project_ids: raise Warning(_("No Project for generating tasks of contract %s found") % contract.name) project = project_obj.browse(cr, uid, project_ids[0], context=context_contract) try: # get interval interval = contract.recurring_task_interval rule = contract.recurring_rule_type next_date = contract.recurring_task_next or current_date if contract.recurring_task_rule == "daily": # daily dt_interval = relativedelta(days=interval) interval_name = f.formatLang(next_date, date=True) elif contract.recurring_task_rule == "weekly": # weekly dt_interval = relativedelta(weeks=interval) interval_name = _("%s WE%s") % (util.getYearStr(next_date), util.getWeek(next_date)) elif contract.recurring_task_rule == "monthly": # monthly dt_interval = relativedelta(months=interval) interval_name = helper.getMonthYear(cr, uid, next_date, context=context) else: # yearly interval_name = util.getYearStr(next_date) dt_interval = relativedelta(years=interval) # next date next_date = util.dateToStr(util.strToDate(next_date) + dt_interval) # execute task processed_tasks = 0 finished_tasks = 0 for recurring_task in contract.recurring_task_ids: task_values = self._recurring_task_prepare(cr, uid, project, recurring_task, interval_name, next_date, context=context_contract) if task_values: processed_tasks += 1 # execute task if it is not finished task_count = recurring_task.count if not recurring_task.repeat or task_count < recurring_task.repeat: task_count = recurring_task.count + 1 task_ids.append(task_obj.create(cr, uid, task_values, context=context_contract)) recurring_task_obj.write(cr, uid, [recurring_task.id], {"count": task_count}, context=context_contract) # check if task is finished if recurring_task.repeat and task_count >= recurring_task.repeat: finished_tasks += 1 # check if all tasks are finished if finished_tasks and finished_tasks == processed_tasks: values["recurring_task"] = False # update contract values = {"recurring_task_next": next_date} self.write(cr, uid, [contract.id], values, context=context) # commit if automatic if automatic: cr.commit() except Exception: # log error if automatic if automatic: cr.rollback() _logger.exception("Fail to create recurring task for contract %s [%s]", (contract.name, contract.code)) else: raise return task_ids
def barkeeper_status(self, cr, uid, options, context=None): order_obj = self.pool["pos.order"] session_obj = self.pool["pos.session"] config_obj = self.pool["pos.config"] company_obj = self.pool["res.company"] company_id = company_obj._company_default_get(cr, uid, context=context) company = company_obj.browse(cr, uid, company_id, context=context) currency = company.currency_id.symbol # result stat = { "title": _("No Data"), "currency": currency, "name": "", "group": "", "range": "" } # search first order if # and build default options # if no options are passed config_id = None config = None date = None mode = "today" if options: config_id = options.get("config_id") # if mode is today # date is none mode = options.get("mode") if not mode or mode == "today": date = None options["mode"] = "today" else: date = options.get("date") nodata = False if not config_id or not date: # get latest order order_id = None if config_id: config = config_obj.browse(cr, uid, config_id, context=context) order_id = order_obj.search_id( cr, uid, [ '|', ("session_id.config_id", "=", config_id), ('session_id.config_id.parent_user_id', '=', config.user_id.id) ], order="date_order desc", context=None) else: order_id = order_obj.search_id(cr, uid, [("session_id", "!=", False)], order="date_order desc", context=None) # check if order exist if order_id: order = order_obj.browse(cr, uid, order_id, context=context) # get parent config = order.session_id.config_id while config.parent_user_id: parent_config_id = config_obj.search_id( cr, uid, [("user_id", "=", config.parent_user_id.id)], context=context) if not parent_config_id or parent_config_id == config.id: break config = config_obj.browse(cr, uid, parent_config_id, context=context) config_id = config.id options = { "mode": "today", "date": util.timeToDateStr(order.date_order), "config_id": config_id } else: nodata = True # set options stat["options"] = options # if not data return if not config_id: return stat # get current mode if not config or config.id != config_id: config = config_obj.browse(cr, uid, config_id, context=context) config_ids = [config_id] # build title and group description stat["name"] = config.name if config.user_id: group = [] childEntries = config_obj.search_read( cr, uid, [("parent_user_id", "=", config.user_id.id)], ["name", "sign_pid"], context=context) for childEntry in childEntries: group.append(childEntry["sign_pid"] or childEntry["name"]) config_ids.append(childEntry["id"]) if group: group.insert(0, config.sign_pid or config.name) stat["group"] = ", ".join(group) # return if no default data if nodata: return stat # find start statDate = options.get("date") if not statDate: options["date"] = statDate = util.currentDate() # add amount orderDicts = [] def addAmount(amount, amountStat, sections, count=False): for section in sections: subsections = None sectionStat = None if len(section) == 1: key = section[0] sectionStat = amountStat.get(key) if sectionStat is None: sectionStat = { "amount": 0.0, "count": 0, "currency": currency } amountStat[key] = sectionStat elif len(section) >= 2: field = section[0] key = section[1] if len(section) >= 3: subsections = section[2] keyStat = amountStat.get(field) if keyStat is None: keyStat = {} amountStat[field] = keyStat orderDicts.append((amountStat, field, keyStat)) sectionStat = keyStat.get(key) if sectionStat is None: sectionStat = { "key": key, "amount": 0.0, "count": 0, "currency": currency } keyStat[key] = sectionStat sectionStat["amount"] = sectionStat["amount"] + amount if count: sectionStat["count"] = sectionStat["count"] + 1 if subsections: addAmount(amount, sectionStat, subsections, count=count) # setup range time_keyfunc = lambda date_order: helper.strToLocalDateStr( cr, uid, date_order, context=context) if mode == "year": stat["title"] = _("Year") startDate = util.getFirstOfYear(statDate) endDate = util.getFirstOfNextYear(statDate) dt_delta = relativedelta(years=1) time_keyfunc = lambda date_order: helper.strToLocalDateStr( cr, uid, date_order, context=context)[:7] elif mode == "month": stat["title"] = _("Month") startDate = util.getFirstOfMonth(statDate) endDate = util.getFirstOfNextMonth(statDate) dt_delta = relativedelta(months=1) elif mode == "week": stat["title"] = _("Week") startDate = util.getFirstOfWeek(statDate) endDate = util.getFirstOfNextWeek(statDate) dt_delta = relativedelta(weeks=1) else: time_keyfunc = lambda date_order: "%s:00" % helper.strToLocalTimeStr( cr, uid, date_order, context=context).split(" ")[1][:2] stat["title"] = _("Day") startDate = statDate endDate = util.getNextDayDate(statDate) dt_delta = relativedelta(hours=1) # query session build range session_ids = session_obj.search(cr, uid, [("start_at", ">=", startDate), ("start_at", "<", endDate), ("config_id", "in", config_ids)], order="start_at asc", context=context) stat["range"] = helper.getRangeName(cr, uid, startDate, util.getPrevDayDate(endDate), context=context) # query orders order_ids = order_obj.search(cr, uid, [("session_id", "in", session_ids)], order="date_order asc", context=context) orders = order_obj.browse(cr, uid, order_ids, context=context) # build base addAmount(0, stat, [("total", )]) if orders: firstOrder = orders[0] lastOrder = orders[-1] curTime = util.strToTime(firstOrder.date_order) timeEnd = util.strToTime(lastOrder.date_order) while curTime <= timeEnd: time_key = time_keyfunc(util.timeToStr(curTime)) addAmount(0, stat, [("byTime", time_key)]) curTime += dt_delta # iterate orders for order in orders: # check if it is relevant fpos_order = order.fpos_order_id notbalance = fpos_order.tag != "s" user = order.user_id # add turnover for journal for st in order.statement_ids: journal = st.journal_id amount = notbalance and st.amount or 0.0 addAmount( amount, stat, [("byJournal", journal.name), ("byUser", user.name, [("byJournal", journal.name)])], True) # add to order time_key = time_keyfunc(order.date_order) amount = notbalance and order.amount_total or 0.0 addAmount(amount, stat, [("total", ), ("byTime", time_key, [("byUser", user.name)])], True) # sort dicts for (parent, key, value) in orderDicts: parent[key] = value and sorted(value.values(), key=lambda en: en["key"]) or [] return stat
class account_analytic_account(osv.osv): def name_get(self, cr, uid, ids, context=None): ids = util.idList(ids) res = super(account_analytic_account,self).name_get(cr,uid,ids,context=context) if ids: cr.execute("SELECT a.id, p.name FROM account_analytic_account AS a " " INNER JOIN res_partner AS p ON p.id = a.partner_id " " WHERE a.id IN %s", (tuple(ids),)) partner_names = {} for row in cr.fetchall(): partner_names[row[0]] = row[1] new_res = [] for value in res: cur_id = value[0] cur_name = value[1] name = partner_names.get(cur_id) if name: new_res.append((cur_id,cur_name + " [" + name + "]")) else: new_res.append(value) return new_res return res def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100): res = super(account_analytic_account,self).name_search(cr,uid,name,args=args,operator=operator,context=context,limit=limit) if not res: account_ids = self.search(cr, uid, [("partner_id.name", operator, name)], limit=limit, context=context) if account_ids: return self.name_get(cr, uid, account_ids, context=context) order_res = self.pool.get("sale.order").name_search(cr,uid,name,args=None,operator=operator,context=context,limit=limit) res = [] if order_res: ids = [x[0] for x in order_res] analytic_id_for_order = {} cr.execute("SELECT id,project_id FROM sale_order WHERE id IN %s AND project_id IS NOT NULL",(tuple(ids),)) for row in cr.fetchall(): analytic_id_for_order[row[0]]=row[1] for tup in order_res: analytic_id = analytic_id_for_order.get(tup[0]) if analytic_id: res.append((analytic_id,tup[1])) return res def on_change_template(self, cr, uid, ids, template_id, date_start=False, context=None): res = super(account_analytic_account, self).on_change_template(cr, uid, ids, template_id, date_start=date_start, context=context) if template_id: template = self.browse(cr, uid, template_id, context=context) values = res["value"] if not ids: # take shop shop = template.shop_id if shop: values["shop_id"] = shop.id # overtake prepaid values["recurring_prepaid"] = template.recurring_prepaid recurring_task_obj = self.pool("account.analytic.recurring.task") # overtake recurring task values recurring_task_vals = [] for recurring_task in template.recurring_task_ids: recurring_task_copy = recurring_task_obj.copy_data(cr, uid, recurring_task.id, context=context) del recurring_task_copy["analytic_account_id"] recurring_task_vals.append((0, 0, recurring_task_copy)) values["recurring_task"] = template.recurring_task values["recurring_task_interval"] = template.recurring_task_interval values["recurring_task_rule"] = template.recurring_task_rule values["recurring_task_ids"] = recurring_task_vals return res def unlink(self, cr, uid, ids, context=None): # unlink project if it is contract project_obj = self.pool.get('project.project') for account in self.browse(cr, uid, ids, context=context): if account.is_contract: project_ids = project_obj.search(cr, uid, [('analytic_account_id','in',ids)]) if project_ids: project_obj.unlink(cr, uid, project_ids, context=context) return super(account_analytic_account, self).unlink(cr, uid, ids, context=context) def _prepare_invoice_data(self, cr, uid, contract, context=None): invoice = super(account_analytic_account, self)._prepare_invoice_data(cr, uid, contract, context=context) # invoice name to contract name invoice["name"] = contract.name # determine user user_id = contract.manager_id or contract.user_id if user_id: invoice["user_id"] = user_id.id # determine shop if contract.shop_id: invoice["shop_id"] = contract.shop_id.id else: # shop from template template = contract.template_id if template and template.shop_id: invoice["shop_id"] = template.shop_id.id else: parent = contract.parent_id if parent: # get shop from parent if parent.shop_id: invoice["shop_id"] = parent.shop_id.id else: # shop from autocreate shop_obj = self.pool["sale.shop"] shop_ids = shop_obj.search(cr, uid, [("autocreate_order_parent_id","=",parent.id)], limit=2) if not shop_ids: shop_ids = shop_obj.search(cr, uid, [("project_id","=",parent.id)], limit=2) # check if only one shop is assinged if len(shop_ids) == 1: invoice["shop_id"] = shop_ids[0] # performance period if contract.recurring_invoices: # get next date function def getNextDate(cur_date,sign=1): interval = contract.recurring_interval*sign if contract.recurring_rule_type == 'daily': return cur_date+relativedelta(days=+interval) elif contract.recurring_rule_type == 'weekly': return cur_date+relativedelta(weeks=+interval) elif contract.recurring_rule_type == 'monthly': return cur_date+relativedelta(months=+interval) else: return cur_date+relativedelta(years=+interval) cur_date = util.strToDate(contract.recurring_next_date or util.currentDate()) if contract.recurring_prepaid: invoice["perf_enabled"] = True invoice["perf_start"] = cur_date invoice["perf_end"] = getNextDate(cur_date) else: invoice["perf_enabled"] = True invoice["perf_start"] = getNextDate(cur_date,-1) invoice["perf_end"] = cur_date # first of month and last of month if contract.recurring_rule_type == 'monthly': invoice["perf_end"] = util.strToDate(util.getEndOfMonth(invoice["perf_end"])) if contract.recurring_interval > 0: interval = -(contract.recurring_interval-1) invoice["perf_start"] = util.strToDate(util.getFirstOfMonth(invoice["perf_end"]))+relativedelta(months=interval) # convert dt to str invoice["perf_start"] = util.dateToStr(invoice["perf_start"]) invoice["perf_end"] = util.dateToStr(invoice["perf_end"]) return invoice def _root_account(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids) for obj in self.browse(cr, uid, ids, context): parent = obj.parent_id if parent: while parent.parent_id: parent = parent.parent_id res[obj.id] = parent.id return res def _relids_account(self, cr, uid, ids, context=None): res = self.search(cr, uid, [("id","child_of",ids)], context=context) return res def onchange_recurring_task(self, cr, uid, ids, recurring_task, date_start=False, context=None): if date_start and recurring_task: return {'value': {'recurring_task_next': date_start}} return {} def recurring_task_create(self, cr, uid, ids, context=None): return self._recurring_task_create(cr, uid, ids, context=context) def _cron_recurring_task_create(self, cr, uid, context=None): return self._recurring_task_create(cr, uid, [], automatic=True, context=context) def _recurring_task_prepare(self, cr, uid, project, recurring_task, interval_name, next_date, context=None): name = "%s %s" % (recurring_task.name, interval_name) values = { "name": name, "description": recurring_task.description, "project_id": project.id, "planned_hours": recurring_task.planned_hours, "sequence": recurring_task.sequence, "date_deadline": util.getPrevDayDate(next_date), } product = recurring_task.product_id if product: values["inv_product_id"] = product.id return values def _recurring_task_create(self, cr, uid, ids, automatic=False, context=None): if context is None: context = {} task_ids = [] current_date = util.currentDate() if ids: contract_ids = ids else: contract_ids = self.search(cr, uid, [("use_tasks","=",True), ("recurring_task_next","<=", current_date), ("state","=", "open"), ("recurring_task","=", True), ("type", "=", "contract")]) if contract_ids: task_obj = self.pool["project.task"] recurring_task_obj = self.pool["account.analytic.recurring.task"] project_obj = self.pool["project.project"] f = format.LangFormat(cr, uid, context) cr.execute("SELECT company_id, array_agg(id) as ids FROM account_analytic_account WHERE id IN %s GROUP BY company_id", (tuple(contract_ids),)) for company_id, ids in cr.fetchall(): context_contract = dict(context, company_id=company_id, force_company=company_id) for contract in self.browse(cr, uid, ids, context=context_contract): project_ids = project_obj.search(cr, uid, [("analytic_account_id","=",contract.id)], context=context_contract) if not project_ids: raise Warning(_("No Project for generating tasks of contract %s found") % contract.name) project = project_obj.browse(cr, uid, project_ids[0], context=context_contract) try: # get interval interval = contract.recurring_task_interval rule = contract.recurring_rule_type next_date = contract.recurring_task_next or current_date if contract.recurring_task_rule == "daily": # daily dt_interval = relativedelta(days=interval) interval_name = f.formatLang(next_date, date=True) elif contract.recurring_task_rule == "weekly": # weekly dt_interval = relativedelta(weeks=interval) interval_name = _("%s WE%s") % (util.getYearStr(next_date), util.getWeek(next_date)) elif contract.recurring_task_rule == "monthly": # monthly dt_interval = relativedelta(months=interval) interval_name = helper.getMonthYear(cr, uid, next_date, context=context) else: # yearly interval_name = util.getYearStr(next_date) dt_interval = relativedelta(years=interval) # next date next_date = util.dateToStr(util.strToDate(next_date) + dt_interval) # execute task processed_tasks = 0 finished_tasks = 0 for recurring_task in contract.recurring_task_ids: task_values = self._recurring_task_prepare(cr, uid, project, recurring_task, interval_name, next_date, context=context_contract) if task_values: processed_tasks += 1 # execute task if it is not finished task_count = recurring_task.count if not recurring_task.repeat or task_count < recurring_task.repeat: task_count = recurring_task.count + 1 task_ids.append(task_obj.create(cr, uid, task_values, context=context_contract)) recurring_task_obj.write(cr, uid, [recurring_task.id], {"count": task_count}, context=context_contract) # check if task is finished if recurring_task.repeat and task_count >= recurring_task.repeat: finished_tasks += 1 # check if all tasks are finished if finished_tasks and finished_tasks == processed_tasks: values["recurring_task"] = False # update contract values = {"recurring_task_next": next_date} self.write(cr, uid, [contract.id], values, context=context) # commit if automatic if automatic: cr.commit() except Exception: # log error if automatic if automatic: cr.rollback() _logger.exception("Fail to create recurring task for contract %s [%s]", (contract.name, contract.code)) else: raise return task_ids _inherit = "account.analytic.account" _columns = { "order_id" : fields.many2one("sale.order", "Order", ondelete="cascade", copy=False, select=True), "shop_id" : fields.many2one("sale.shop", "Shop", select=True), "recurring_prepaid" : fields.boolean("Prepaid"), "root_account_id" : fields.function(_root_account, type="many2one", obj="account.analytic.account", string="Root", select=True, store={ "account.analytic.account" : (_relids_account, ["parent_id"], 10) }), "is_contract": fields.boolean("Contract"), "section_id": fields.related("order_id", "section_id", type="many2one", relation="crm.case.section", string="Sales Team"), "categ_ids" : fields.related("order_id", "categ_ids", type="many2many", relation="crm.case.categ", string="Tags", domain="['|', ('section_id', '=', section_id), ('section_id', '=', False), ('object_id.model', '=', 'crm.lead')]", context="{'object_name': 'crm.lead'}"), "recurring_task": fields.boolean("Recurring Tasks"), "recurring_task_ids": fields.one2many("account.analytic.recurring.task", "analytic_account_id", "Recurring Tasks", copy=True), "recurring_task_rule": fields.selection([ ("daily", "Day(s)"), ("weekly", "Week(s)"), ("monthly", "Month(s)"), ("yearly", "Year(s)")], "Task Recurrency", help="Task automatically repeat at specified interval"), "recurring_task_interval": fields.integer("Repeat Task Every", help="Repeat every (Days/Week/Month/Year)"), "recurring_task_next": fields.date("Date of Next Task(s)"), "src_order_id" : fields.many2one("sale.order", "Source Order", ondelete="set null", copy=False, select=True), "src_section_id": fields.related("src_order_id", "section_id", type="many2one", relation="crm.case.section", string="Source Sales Team"), "src_categ_ids" : fields.related("src_order_id", "categ_ids", type="many2many", relation="crm.case.categ", string="Source Tags", domain="['|', ('section_id', '=', src_section_id), ('section_id', '=', False), ('object_id.model', '=', 'crm.lead')]", context="{'object_name': 'crm.lead'}") } _defaults = { "recurring_task_interval": 1, "recurring_task_next": lambda *a: util.currentDate(), "recurring_task_rule": "monthly" }
class account_dunning_wizard(osv.osv_memory): def create_reminders(self, cr, uid, ids, context=None): invoice_obj = self.pool.get("account.invoice") reminder_obj = self.pool.get("account.reminder") profile_line_obj = self.pool.get("account.dunning_profile_line") profile_obj = self.pool.get("account.dunning_profile") partner_obj = self.pool.get("res.partner") reminder_line_obj = self.pool.get("account.reminder.line") user = self.pool.get("res.users").browse(cr, uid, uid) # get profiles for shop profiles = profile_obj.browse(cr, uid, profile_obj.search(cr, uid, []), context=context) all_shops = set([s.id for s in profiles.mapped('shop_ids')]) for wizard in self.browse(cr, uid, ids): cr.execute( "SELECT inv.partner_id FROM account_invoice inv WHERE inv.state='open' " " UNION " " SELECT r.partner_id FROM account_reminder r") partner_ids = [r[0] for r in cr.fetchall()] reminder_ids = [] # check if there any partner ids if not partner_ids: break # shop id shop_ids = set() if wizard.profile_id.shop_ids: for shop in wizard.profile_id.shop_ids: shop_ids.add(shop.id) customers = partner_obj.browse(cr, uid, partner_ids, context=context) for customer in customers: # get active reminder id reminder_id = reminder_obj.search_id( cr, uid, [("partner_id", "=", customer.id), ("profile_id", "=", wizard.profile_id.id)]) if not customer.noremind: commercial_partner = customer.commercial_partner_id # check balance # not commercial_partner.credit (should never happen, but it happens) if not commercial_partner.credit or commercial_partner.credit > commercial_partner.debit or reminder_id: # check invoice invoice_ids = invoice_obj.search( cr, uid, [("partner_id", "=", customer.id), ("type", "=", "out_invoice"), ("noremind", "=", False)]) if not invoice_ids: continue lines = [] max_profile_line = None profile_line = None # check invoices for inv in invoice_obj.browse(cr, uid, invoice_ids): # check if shop specific reminder defined if all_shops: inv_shop_id = inv.shop_id and inv.shop_id.id or 0 # check profile is a general reminder # or continue if not if not shop_ids and inv_shop_id in all_shops: continue # check if it is a shop specific reminder # or continue if not if shop_ids and not inv_shop_id in shop_ids: continue if (user.company_id == inv.company_id ) and inv.payment_term and not inv.noremind: reminder_line_id = reminder_line_obj.search_id( cr, uid, [("reminder_id", "=", reminder_id), ("invoice_id", "=", inv.id)]) if inv.state == "open": profile_line = profile_line_obj.line_next( cr, uid, wizard.profile_id, inv.profile_line_id, wizard.date, inv.date_due) # check if no dunning option if profile_line and profile_line.payment_no_dunning and inv.residual > 0 and inv.residual < inv.amount_total: profile_line = None invoice_obj.write( cr, uid, inv.id, { "profile_line_id": profile_line and profile_line.id or None, "dunning_date": wizard.date }, context) # check next remind if profile_line and inv.residual: line_values = { "invoice_id": inv.id, "profile_line_id": profile_line and profile_line.id or None, "amount": inv.residual } # update remind if not reminder_line_id: lines.append((0, 0, line_values)) else: lines.append((1, reminder_line_id, line_values)) # determine max profile if max_profile_line: if max_profile_line.sequence < profile_line.sequence: max_profile_line = profile_line else: max_profile_line = profile_line #update or create reminder if max_profile_line: values = { "date": wizard.date, "partner_id": customer.id, "profile_id": wizard.profile_id.id, "max_profile_line_id": max_profile_line.id, "line_ids": lines, "state": "validated" } # create or update reminder if reminder_id: reminder_obj.write(cr, uid, reminder_id, values, context) else: reminder_id = reminder_obj.create( cr, uid, values, context) # update lines reminder_line_ids = [] for line in lines: values = line[2] values["reminder_id"] = reminder_id line_id = line[1] if not line_id: line_id = reminder_line_obj.create( cr, uid, values, context) else: reminder_line_obj.write( cr, uid, line_id, values, context) # add line reminder_line_ids.append(line_id) # only add if there are lines if reminder_line_ids: # delete unused lines unused_line_ids = reminder_line_obj.search( cr, uid, [("reminder_id", "=", reminder_id), ("id", "not in", reminder_line_ids)], context=context) reminder_line_obj.unlink(cr, uid, unused_line_ids, context=context) # add reminder reminder_ids.append(reminder_id) # remove untouched, unused unused_reminder_ids = reminder_obj.search( cr, uid, [("id", "not in", reminder_ids), ("profile_id", "=", wizard.profile_id.id)]) reminder_obj.unlink(cr, uid, unused_reminder_ids, context=context) return { "name": _("Reminders"), "res_model": "account.reminder", "type": "ir.actions.act_window", "view_type": "form", "view_mode": "tree,form", "clear_breadcrumbs": True } def _default_profile_id(self, cr, uid, context=None): company_id = self.pool.get('res.users')._get_company(cr, uid, context=context) return self.pool.get("account.dunning_profile").search_id( cr, uid, [("company_id", "=", company_id)], context=context) _name = "account.dunning_wizard" _columns = { "date": fields.date("Reminder date", required=True), "profile_id": fields.many2one("account.dunning_profile", "Profile", required=True), } _defaults = { "date": lambda *a: util.currentDate(), "profile_id": _default_profile_id }