daily pastebin goal
9%
SHARE
TWEET

Untitled

a guest Dec 16th, 2018 59 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ## -*- coding: utf-8 -*-
  2. import itertools
  3. import time
  4. import xml.dom.minidom
  5.  
  6. from openobject.i18n import format
  7. from openobject.widgets import JSLink, CSSLink
  8. from openobject.i18n.format import format_date_custom
  9.  
  10. from openerp.utils import rpc, node_attributes
  11. from openerp.widgets import TinyWidget, ConcurrencyInfo
  12.  
  13. from view_calendar.widgets._base import ICalendar, TinyCalendar, TinyEvent, choice_colors
  14. from view_calendar.widgets.utils import Day, Week, Month, Year
  15. from view_calendar.widgets import GanttCalendar
  16. from view_calendar.widgets.widgets import _get_selection_day, MiniCalendar, GroupBox, Sidebar
  17.  
  18. from mitr.widgets.utils import ProjectWeek
  19. from mitr.utils.weeks import weeks_from,  parse_datetime2date
  20. from calendar import timegm
  21. from mitr.utils.weeks import fmt_striftime_th
  22. from datetime import timedelta, datetime
  23. from random import randrange
  24. from mitr.settings import COLOR_KEYS
  25.  
  26. ACTUAL_FACTOR = 0.1
  27. ACTUAL_COLOR = "#666666"
  28.  
  29. class OsTinyEvent(TinyEvent):
  30.  
  31.     params = ['starts', 'ends', 'title', 'description', 'color', 'record_id', 'create_date', 'create_uid', 'write_uid', 'write_date', 'actual', 'plan', 'progress' ]
  32.  
  33.     def __init__(self, record, starts, ends, title='', description='', dayspan=0, color=None, classes=None, actual=0, plan=0, progress=0):
  34.  
  35.         super(OsTinyEvent, self).__init__(record, starts, ends, title=title, description=description, dayspan=dayspan, color=color, classes=classes)
  36.  
  37.         self.actual = actual
  38.         self.plan = plan
  39.         self.progress = progress
  40.  
  41.  
  42. class MitrGanttCalendar(ICalendar):
  43.  
  44.     template = 'mitr/widgets/templates/gantt.mako'
  45.  
  46.     params = ['title', 'level', 'groups', 'days', 'events', 'calendar_fields', 'date_format',
  47.               'selected_day', 'mode', 'headers', 'subheaders', 'model', 'ids']
  48.     member_widgets = ['sidebar']
  49.  
  50.     level = None
  51.     groups = None
  52.     title = None
  53.     days = None
  54.     headers = None
  55.     subheaders = None
  56.     mode = 'week'
  57.  
  58.     sidebar = None
  59.  
  60.     css = [CSSLink("view_calendar", 'css/calendar.css'),
  61.            CSSLink("view_calendar", 'css/screen.css'),
  62.            CSSLink("view_calendar", 'css/calendar_gantt.css'),
  63.            CSSLink("mitr", 'css/gantt.css')]
  64.     javascript = [JSLink("view_calendar", 'javascript/calendar_date.js'),
  65.                   JSLink("view_calendar", 'javascript/calendar_utils.js'),
  66.                   JSLink("view_calendar", 'javascript/calendar_box.js'),
  67.                   JSLink("view_calendar", 'javascript/calendar_month.js'),
  68.                   JSLink("view_calendar", 'javascript/calendar_week.js'),
  69.                   #JSLink("view_calendar", 'javascript/calendar_gantt.js'),
  70.                   JSLink("mitr", 'javascript/mitr_calendar_gantt.js')
  71.                   ]
  72.  
  73.     def __init__(self, model, ids, view, domain=[], context={}, options=None, conditions=[]):
  74.  
  75.         self.level = None
  76.         self.groups = []
  77.         self.days = []
  78.         self.headers = []
  79.        
  80.         super(MitrGanttCalendar, self).__init__(model, ids, view, domain, context, options)
  81.        
  82.         # y, m, d = time.localtime()[:3]
  83.         # if options:
  84.         #     y, m, d = options.date1[:3]
  85.         # if ids:
  86.         proxy = rpc.RPCProxy(self.model)
  87.  
  88.         if not self.ids:
  89.             self.ids = proxy.search(conditions, order="date_start")
  90.         ctx = rpc.session.context.copy()
  91.         start_week_id = proxy.search(conditions, order='date_start', limit=1)
  92.         if not start_week_id:
  93.             return None
  94.         start_week = time.strptime(proxy.read(start_week_id)[0]['date_start'], "%Y-%m-%d %H:%M:%S")
  95.         y = start_week.tm_year
  96.         m = start_week.tm_mon
  97.         d = start_week.tm_mday
  98.         end_week = time.strptime(proxy.read(proxy.search(conditions, order='date_end DESC', limit=1))[0]['date_end'], "%Y-%m-%d %H:%M:%S")
  99.         weeks = weeks_from(start_week, end_week) + 2
  100.         #y, m, d = time.strptime(self._result[0]['date_start'], "%y-%m-%d ")
  101.         #raise Exception(weeks)
  102.         day = Day(y, m, d)
  103.  
  104.         w = ProjectWeek(day, weeks)
  105.         # wp = w - 1
  106.         # wn = w + 1
  107.         #self.days = wp.days + w.days + wn.days
  108.         self.days = w.days
  109.         self.title = _(u"%s - %s") % (ustr(self.days[0]), ustr(self.days[-1]))
  110.         self.selected_day = _get_selection_day(day, self.selected_day, 'week')
  111.  
  112.         self.headers = [(7, _("สัปดาห์ที่ %s") % fmt_striftime_th(w[0]+(w1*7), '%W (%b %Y)', ['%b'])) for w1 in range(0,weeks)]
  113.         #self.headers = [(7, _("สัปดาห์ที่ %s") % (w[0]+(w1*7)).strftime('%W (%b %Y)')) for w1 in range(0,weeks)]
  114.         self.subheaders = [format_date_custom(x, "E d") for x in itertools.chain(w)]
  115.  
  116.  
  117.         if self.level:
  118.             field = self.level['link']
  119.             fields = rpc.RPCProxy(self.model).fields_get([field], rpc.session.context)
  120.             self.fields.update(fields)
  121.  
  122.         self.events = self.get_events(self.days)
  123.         self.groups = self.get_groups(self.events)
  124.  
  125.         minical = MiniCalendar(day)
  126.         groupbox = GroupBox(self.colors, self.color_values, day,
  127.                 group_relation=self.fields[self.color_field],
  128.                 title=(self.color_field or None) and self.fields[self.color_field]['string'], mode=self.mode)
  129.  
  130.         self.sidebar = Sidebar(minical, groupbox, self.use_search)
  131.  
  132.     def parse(self, root, fields):
  133.  
  134.         info_fields = []
  135.         attrs = node_attributes(root)
  136.  
  137.         for node in root.childNodes:
  138.             attrs = node_attributes(node)
  139.  
  140.             if node.localName == 'field':
  141.                 info_fields.append(attrs['name'])
  142.  
  143.             if node.localName == 'level':
  144.                 self.level = attrs
  145.                 info_fields += self.parse(node, fields)
  146.  
  147.         return info_fields
  148.  
  149.     def get_event_widget(self, event):
  150.         title = ''       # the title
  151.         description = [] # the description
  152.         if self.info_fields:
  153.  
  154.             f = self.info_fields[0]
  155.             s = event[f]
  156.  
  157.             if isinstance(s, (tuple, list)): s = s[-1]
  158.  
  159.             title = ustr(s)
  160.  
  161.             for f in self.info_fields[1:]:
  162.                 s = event[f]
  163.                 if isinstance(s, (tuple, list)):
  164.                     s = s[-1]
  165.                 if s:
  166.                     description.append(ustr(s))
  167.         starts = event.get(self.date_start)
  168.         ends = event.get(self.date_stop)
  169.         #ends = event.get(self.date_delay) or 1.0
  170.         span = 0
  171.  
  172.         """if starts and ends:
  173.  
  174.             n = 0
  175.             h = ends
  176.  
  177.             if ends == self.day_length:
  178.                 span = 1
  179.  
  180.             elif ends > self.day_length:
  181.                 n = ends / self.day_length
  182.                 h = ends % self.day_length
  183.  
  184.                 n = int(math.floor(n))
  185.  
  186.                 if h > 0:
  187.                     span = n + 1
  188.                 else:
  189.                     span = n
  190.  
  191.             ends = time.localtime(time.mktime(starts) + (h * 60 * 60) + (n * 24 * 60 * 60))
  192.  
  193.         if starts and self.date_stop:
  194.  
  195.             ends = event.get(self.date_stop)
  196.             if not ends:
  197.                 ends = time.localtime(time.mktime(starts) + 60 * 60)
  198.  
  199.             tds = time.mktime(starts)
  200.             tde = time.mktime(ends)
  201.  
  202.             if tds >= tde:
  203.                 tde = tds + 60 * 60
  204.                 ends = time.localtime(tde)
  205.  
  206.             n = (tde - tds) / (60 * 60)
  207.  
  208.             if n >= self.day_length:
  209.                 span = math.ceil(n / 24)"""
  210.  
  211.         starts = format.format_datetime(starts, "datetime", True)
  212.         ends = format.format_datetime(ends, "datetime", True)
  213.         color_key = event.get(self.color_field)
  214.         #color = self.colors.get(color_key)
  215.         color = (rpc.session['user_name'], rpc.session['uid'], COLOR_KEYS[event['color']])
  216.         classes = self._get_classes(event)
  217.         title = title.strip()
  218.         description = ', '.join(description).strip()
  219.        
  220.         timesheet_res = rpc.RPCProxy('os.res.timesheet')
  221.         task_week_res = rpc.RPCProxy('os.task.week')
  222.        
  223.         actual = timesheet_res.sum_actual_by_task(event['id'])
  224.         plan = task_week_res.sum_plan_by_task(event['id'])
  225.         progress = 0
  226.         if plan != 0:
  227.             progress = (actual/plan) * 100
  228.         if isinstance(event['id'], int):
  229.             event_log = rpc.session.execute('object', 'execute', self.model, 'perm_read', [event['id']])[0]
  230.  
  231.             event['create_date'] = event_log['create_date']
  232.             event['create_uid'] = event_log['create_uid'][1]
  233.             if isinstance(event_log['write_uid'], tuple):
  234.                 event_log['write_uid'] = event_log['write_uid'][1]
  235.             event['write_uid'] = event_log['write_uid']
  236.             event['write_date'] = event_log['write_date']
  237.  
  238.         else:
  239.             color = (rpc.session['user_name'], rpc.session['uid'], ACTUAL_COLOR)
  240.        
  241.         return OsTinyEvent(event, starts, ends, title, description, dayspan=span, color=(color or None) and color[-1], classes=classes, actual=actual, plan=plan, progress=progress)
  242.  
  243.     def get_events(self, days):
  244.         proxy = rpc.RPCProxy(self.model)
  245.  
  246.         """if self.date_stop:
  247.             # use the correct algorithm:
  248.             domain = self.domain + [(self.date_stop, '<=', days[-1].isoformat() + ' 23:59:59'),
  249.                                     (self.date_start, '>=', days[0].isoformat() + ' 00:00:00')]
  250.         else:
  251.             # cannot use the correct algorithm, use the old one:
  252.             first = days[0].month2.prev()[0] #HACK: add prev month
  253.             domain = self.domain + [(self.date_start, '>', first.isoformat()),
  254.                                     (self.date_start, '<', days[-1].next().isoformat())]"""
  255.         domain = self.domain
  256.  
  257.  
  258.         # convert color values from string to python values
  259.         if self.color_values and self.color_field in self.fields:
  260.             try:
  261.                 atr = self.fields[self.color_field]
  262.                 atr['required'] = False
  263.                 wid = get_widget(atr['type'])(**atr)
  264.                 vals = self.color_values[:]
  265.                 for i, v in enumerate(vals):
  266.                     try:
  267.                         vals[i] = wid.validator.to_python(v)
  268.                     except:
  269.                         pass
  270.                 domain.append((self.color_field, "in", vals))
  271.             except Exception:
  272.                 pass
  273.  
  274.         if self.options and self.options.use_search:
  275.             domain += self.options.search_domain
  276.  
  277.         ctx = rpc.session.context.copy()
  278.         ctx.update(self.context)
  279.  
  280.         order_by = ('sequence' in self.fields or 0) and 'sequence'
  281.  
  282.         if self.color_field and self.fields[self.color_field].get('relation') and self.color_field not in [item[0] for item in domain]:
  283.             if self.options and self.options.get('_terp_color_filters'):
  284.                 clr_field = self.options['_terp_color_filters']
  285.             else:
  286.                 search_limit = 10
  287.                 need_to_add_the_user_to_the_list_of_users = False
  288.                 if self.context and self.color_field and \
  289.                     self.context.get('search_default_user_id') and \
  290.                     self.color_field == 'user_id' and \
  291.                     self.fields[self.color_field].get('relation') == 'res.users':
  292.                     need_to_add_the_user_to_the_list_of_users = True
  293.                 clr_field = rpc.RPCProxy(self.fields[self.color_field]['relation']).search([], 0, search_limit, 0, ctx)
  294.                 if need_to_add_the_user_to_the_list_of_users and self.context.get('search_default_user_id') not in clr_field:
  295.                     clr_field[search_limit-1] = self.context.get('search_default_user_id')
  296.  
  297.             domain.append((self.color_field, 'in', clr_field))
  298.         if not self.ids:
  299.             ids = proxy.search(domain, 0, 0, order_by, ctx)
  300.         else:
  301.             ids = self.ids
  302.  
  303.         result = proxy.read(ids, self.fields.keys()+['__last_update', 'color'], ctx)
  304.         ConcurrencyInfo.update(self.model, result)
  305.         self.concurrency_info = ConcurrencyInfo(self.model, ids)
  306.         if self.color_field:
  307.             for evt in result:
  308.                 key = evt[self.color_field]
  309.                 name = key
  310.                 value = key
  311.                 if isinstance(key, list): # M2O, XMLRPC returns List instead of Tuple
  312.                     evt[self.color_field] = key = tuple(key)
  313.  
  314.                 if isinstance(key, tuple): # M2O
  315.                     value, name = key
  316.  
  317.                 self.colors[key] = (name, value, None)
  318.  
  319.             colors = choice_colors(len(self.colors))
  320.             for i, (key, value) in enumerate(self.colors.items()):
  321.                 self.colors[key] = (value[0], value[1], colors[i])
  322.  
  323.         events = []
  324.        
  325.         for evt in result:
  326.             self.convert(evt)
  327.             events.append(self.get_event_widget(evt))
  328.             # add the actual data
  329.             evt2 = self.get_actual_data(evt)
  330.             events.append(self.get_event_widget(evt2))
  331.            
  332.         if self.date_stop:
  333.             result = events
  334.         else:
  335.             # filter out the events which are not in the range
  336.             result = []
  337.             for e in events:
  338.                 if e.starts is None:
  339.                     continue
  340.                 if e.dayspan > 0 and days[0] - e.dayspan < e.starts:
  341.                     result.append(e)
  342.                 if e.dayspan == 0 and days[0] <= e.starts:
  343.                     result.append(e)
  344.         return result
  345.  
  346.     def get_groups(self, events):
  347.  
  348.         if not self.level:
  349.             return []
  350.  
  351.         obj = self.level['object']
  352.         field = self.level['link']
  353.  
  354.         keys = []
  355.         groups = {}
  356.         for evt in events:
  357.             group_id = evt.record[field]
  358.             group_title = 'None'
  359.  
  360.             if not group_id: # create dummy group
  361.                 group_id = 0
  362.  
  363.             if isinstance(group_id, (list, tuple)):
  364.                 group_id, group_title = evt.record[field]
  365.             elif group_id:
  366.                 group_id, group_title = rpc.RPCProxy(obj).name_get([group_id], rpc.session.context)[0]
  367.  
  368.             group = groups.setdefault(group_id, {'id': str(group_id), 'title': group_title, 'model': obj, 'items': [], 'actual':0, 'plan':0, 'progress':0})
  369.  
  370.             group['items'].append(str(evt.record_id))
  371.             # get all event in this group and sum actual and planed then progress
  372.             group['actual'] += evt.actual
  373.             group['plan'] += evt.plan
  374.             group['progress'] += evt.progress
  375.             if group_id not in keys:
  376.                 keys.append(group_id)
  377.  
  378.         return [groups[i] for i in keys]
  379.  
  380.     def get_actual_data(self, evt):
  381.         data = evt.copy()
  382.         data['name'] = ""
  383.         # get timesheets which contain task id
  384.         # find first and last order by date
  385.         timesheet_res = rpc.RPCProxy('os.res.timesheet')
  386.         args = [('task_id', '=', int(data['id'])), "!", ('hour', '=', 0)]
  387.         first_ids = timesheet_res.search(args, order="date", limit=1)
  388.         last_ids = timesheet_res.search(args, order='date DESC', limit=1)
  389.  
  390.         new_date_start = new_date_end = None
  391.         if first_ids and last_ids:
  392.             first = timesheet_res.read(first_ids[0], ('date',))
  393.             last = timesheet_res.read(last_ids[0], ('date',))
  394.             new_date_start = first['date']
  395.             new_date_end =  last['date']
  396.         data['id'] += ACTUAL_FACTOR
  397.         if new_date_start is not None:
  398.             data[self.date_start] = parse_datetime2date(new_date_start).timetuple()
  399.         else:
  400.             start = data[self.date_start]
  401.             new_date = datetime(start.tm_year-5, start.tm_mon, start.tm_mday, start.tm_hour, start.tm_min, start.tm_sec)
  402.             data[self.date_start] = datetime(day=new_date.day, month=new_date.month, year=new_date.year, hour=new_date.hour, minute=new_date.minute, second=new_date.second).timetuple()
  403.         if new_date_end is not None:
  404.             data[self.date_stop] = parse_datetime2date(new_date_end).timetuple()
  405.         else:
  406.             end = data[self.date_start]
  407.             new_date = datetime(end.tm_year-5, end.tm_mon, end.tm_mday, end.tm_hour, end.tm_min, end.tm_sec)
  408.             data[self.date_stop] = datetime(day=new_date.day, month=new_date.month, year=new_date.year, hour=new_date.hour, minute=new_date.minute, second=new_date.second).timetuple()
  409.         """data['id'] += ACTUAL_FACTOR
  410.         start = data[self.date_start]
  411.         new_date = datetime(start.tm_year, start.tm_mon, start.tm_mday, start.tm_hour, start.tm_min, start.tm_sec) + timedelta(days=randrange(0,2))
  412.         data[self.date_start] = datetime(day=new_date.day, month=new_date.month, year=new_date.year, hour=new_date.hour, minute=new_date.minute, second=new_date.second).timetuple()
  413.         end =  evt[self.date_stop]
  414.         new_date = datetime(end.tm_year, end.tm_mon, end.tm_mday, end.tm_hour, end.tm_min, end.tm_sec) + timedelta(days=randrange(0,2))
  415.         data[self.date_stop] = datetime(day=new_date.day, month=new_date.month, year=new_date.year, hour=new_date.hour, minute=new_date.minute, second=new_date.second ).timetuple()"""
  416.        
  417.         return data
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top