Source code for tendril.costing.breakup

#!/usr/bin/env python
# encoding: utf-8

# Copyright (C) 2016-2019 Chintalagiri Shashank
#
# This file is part of tendril.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
Hierarchical Analysis of Costing Information
--------------------------------------------
"""

import json

from six import viewitems

from tendril.conventions.electronics import parse_ident
from tendril.utils.types.currency import native_currency_defn
from tendril.utils.types.currency import CurrencyValue


[docs]class CostingBreakupBase(object): def __init__(self, name): self._name = name self._currency_symbol = native_currency_defn.symbol @property def name(self): return self._name @property def currency_symbol(self): return self._currency_symbol @property def total_cost(self): raise NotImplementedError @property def sections(self): raise NotImplementedError @property def content(self): return [{'name': k, 'children': v} for k, v in self._content] @property def _content(self): raise NotImplementedError @property def json(self): return json.dumps( {'name': self._name, 'children': self.content } )
[docs]class OBomCostingBreakup(CostingBreakupBase): def __init__(self, name): super(OBomCostingBreakup, self).__init__(name) self._devices = {} self._total_cost = CurrencyValue(0, native_currency_defn)
[docs] def insert(self, ident, cost): d, v, f = parse_ident(ident) if d not in self._devices.keys(): self._devices[d] = [] self._devices[d].append( {'name': ident, 'size': cost.native_value} ) self._total_cost += cost
[docs] def sort(self): for d in self._devices.keys(): self._devices[d].sort(key=lambda x: x['size'], reverse=True)
@property def sections(self): return None @property def total_cost(self): return self._total_cost @property def _content(self): return sorted(viewitems(self._devices), key=lambda x: sum(y['size'] for y in x[1]), reverse=True)
[docs]class HierachicalCostingBreakup(CostingBreakupBase): def __init__(self, name): super(HierachicalCostingBreakup, self).__init__(name) self._sections = {} self._counters = {} @property def sections(self): if self.total_cost == 0: return [] seclist = [ (k, int((v.total_cost / self.total_cost) * 100), v.total_cost) for k, v in viewitems(self._sections) ] return sorted(seclist, key=lambda x: x[1], reverse=True) @property def total_cost(self): return sum([v.total_cost for k, v in viewitems(self._sections)])
[docs] def insert(self, ident, breakup): if ident not in self._sections.keys(): self._sections[ident] = breakup else: if ident in self._counters.keys(): self._counters[ident] += 1 else: self._counters[ident] = 2 newname = '.'.join([ident, '1']) self._sections[newname] = self._sections.pop(ident) newname = '.'.join([ident, str(self._counters[ident])]) self._sections[newname] = breakup
@property def _content(self): return sorted(viewitems(self._sections), key=lambda x: x[1].total_cost, reverse=True)