diff Generic/base.py @ 17:a7b9f7e7dfa4

Improvements importing FIEBDC files
author Miguel Ángel Bárcena Rodríguez <miguelangel@obraencurso.es>
date Sat, 02 Nov 2013 19:26:09 +0100
parents 2ac1551ad2ab
children 7bd4ca56607d
line wrap: on
line diff
--- a/Generic/base.py	Fri Apr 19 00:04:20 2013 +0200
+++ b/Generic/base.py	Sat Nov 02 19:26:09 2013 +0100
@@ -3,7 +3,7 @@
 ## File base.py
 ## This file is part of pyArq-Presupuestos.
 ##
-## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez
+## Copyright (C) 2010-2013 Miguel Ángel Bárcena Rodríguez
 ##                         <miguelangel@obraencurso.es>
 ##
 ## pyArq-Presupuestos is free software: you can redistribute it and/or modify
@@ -303,6 +303,7 @@
         addFile
         {get/set}Labels
         addLabel
+        getChildPositions:
     """
     __slots__ = ["_Record__code", "_Record__synonyms",
                  "_Record__recordType", "_Record__unit",
@@ -332,10 +333,10 @@
         self.__labels = tuple[11]
 
     def __init__(self, decimals, code, synonyms, hierarchy, unit, summary,
-                 prices, type, subtype, parents=[], text=""):
+                 prices, type_, subtype, parents=[], text=""):
         self.code = code
         self.synonyms = synonyms
-        self.recordType = (hierarchy, type, subtype)
+        self.recordType = (hierarchy, type_, subtype)
         self.unit = unit
         self.summary = summary
         self.setPrices(prices, decimals)
@@ -542,9 +543,9 @@
         self.__children = children
 
     def appendChild(self, child_code, decimals, factor=0.0, yield_=0.0,
-                    measure=0.0, measure_list=[], type ="", label=""):
+                    measure=0.0, measure_list=[], type_ ="", label=""):
         """appendChildren(self, child_code, factor=0.0, yield_=0.0,
-                    measure=0.0, measure_list=[], type ="", label=""))
+                    measure=0.0, measure_list=[], type_ ="", label=""))
         
         position:
         child_code:
@@ -552,7 +553,7 @@
         yield_:
         measure:
         measure_list:
-        type:
+        type_:
         label:
         
         Append a child to the list of children
@@ -560,7 +561,7 @@
         _measure = Measure(decimals, self.recordType,
                            measure, [], label, factor, yield_)
         if len(measure_list) > 0:
-            measure.buildMeasure(_measure, measure_list, type, decimals,
+            _measure.buildMeasure( measure_list, type_, decimals,
                                  self.recordType)
         _position = len(self.__children)
         _child = Decomposition(_position, child_code, [_measure])
@@ -615,7 +616,7 @@
                 _description = file[2]
                 if not os.path.exists(file[0]):
                     raise ValueError, _("Incorrect path")
-                _file = File(file_path, type, description)
+                _file = File(file_path, type_, description)
                 _files.append(_file)
             else:
                 raise ValueError, utils.mapping(_(
@@ -623,8 +624,8 @@
         self.__files = _files
         
 
-    def addFile(self, file_path, type, description):
-        """addFile(self, file_path, type, description)
+    def addFile(self, file_path, type_, description):
+        """addFile(self, file_path, type_, description)
         
         Add a file to a record instance
         """
@@ -636,7 +637,7 @@
             if _ofile.name == _name:
                 _isin = True
         if not _isin:
-            _file = File(_name, type, description)
+            _file = File(_name, type_, description)
             self.__files.append(_file)
 
     def getLabels(self):
@@ -667,6 +668,18 @@
         if not label in self.__labels:
             self.__labels.append(label)
 
+    def getChildPositions(self, child_code):
+        """getChildPath(self, child_code):
+        
+        Try to return positions of a childcode
+        """
+        children = self.children
+        positions = []
+        for child in children:
+            if child.code == child_code:
+                positions.append(child.position)
+        return positions
+
     recordType = property(getRecordType, setRecordType, None,
         """Record Type object
         """)
@@ -707,7 +720,7 @@
         Parametric Record object
     Constructor:
         base.ParametricRecord(code, synonyms, hierarchy, unit, summary, prices,
-                              type, subtype, text="")
+                              type_, subtype, text="")
     Ancestry:
     +-- object
       +-- Record
@@ -763,9 +776,9 @@
         self.__parametric_text = tuple[19]
     
     def __init__(self, budget, code, synonyms, hierarchy, unit, summary,
-                 prices, type, subtype, parents=[], text=""):
+                 prices, type_, subtype, parents=[], text=""):
         Record.__init__(self, budget, code, synonyms, hierarchy, unit, summary,
-                 prices, type, subtype, parents=[], text="")
+                 prices, type_, subtype, parents=[], text="")
         self.__parameters = {}
         self.__select_comment = ""
         self.__vars = {}
@@ -1091,8 +1104,8 @@
         """If fixed is True the yield is not calculated from measure
         """)
 
-    def buildMeasure(self, list_lines, type, decimals, recordType):
-        """setMeasure(self, list_lines, type, decimals)
+    def buildMeasure(self, list_lines, type_, decimals, recordType):
+        """setMeasure(self, list_lines, type_, decimals)
         
         list_lines: list of measure lines
             [ [linetype, comment, units, length, width, height, formula], ... ]
@@ -1129,13 +1142,14 @@
             _measure_line = MeasureLine(decimals, _type, _comment, _units,
                                         _length, _width, _height, _formula)
             _lines.append(_measure_line)
-        if type == "M":
+
+        if type_ == "M":
             self.lines = _lines
-        elif type == "A":
+        elif type_ == "A":
             self.lines.extend(_lines)
         else:
             raise ValueError, utils.mapping(_("Type must be M or A. Type: $1"),
-                                            (type,))
+                                            (type_,))
         self.calculateMeasure(decimals, recordType)
 
     def calculateMeasure(self, decimals, recordType):
@@ -1165,7 +1179,7 @@
     Description:
         MeasureLine object
     Constructor:
-        base.MeasureLine(budget, type, comment, units, length, width, height,
+        base.MeasureLine(budget, type_, comment, units, length, width, height,
                          formula)
     Ancestry:
     +-- object
@@ -1191,7 +1205,7 @@
     Methods:
         __getstate__(self)
         __setstate__(self, tuple)
-        __init__(self, decimals, type, comment, units, length, width, height,
+        __init__(self, decimals, type_, comment, units, length, width, height,
                  formula)
         {get/set}LineType
         {get/set}Comment
@@ -1231,12 +1245,12 @@
         self.__formula = tuple[6]
         self.__parcial = tuple[7]
         #self.calculateParcial()
-    def __init__(self, decimals, type, comment, units, length, width, height,
+    def __init__(self, decimals, type_, comment, units, length, width, height,
                  formula):
         self.__parcial = 0.0
         self.__parcial_subtotal = 0.0
         self.__acumulated_subtotal = 0.0
-        self.lineType = type
+        self.lineType = type_
         self.comment = comment
         self.setUnits(units, decimals)
         self.setLength(length, decimals)
@@ -1306,11 +1320,11 @@
         _parcial = round(_parcial, _DS)
         self.__parcial = _parcial
 
-    def setLineType(self, type):
-        if not type in [0, 1, 2, 3]:
+    def setLineType(self, type_):
+        if not type_ in [0, 1, 2, 3]:
             raise ValueError, utils.mapping(_("Invalid measure line type ($1)"),
-                  (str(type),))
-        self.__lineType = type
+                  (str(type_),))
+        self.__lineType = type_
     def setComment(self, comment):
         if not isinstance(comment, str):
             raise ValueError, utils.mapping(_("Measure Comment must be a "\
@@ -2005,7 +2019,7 @@
                 datetime.date(*date)
             self.__date = date
         else:
-            raise  TypeError, _("Invalid Date: %s" % str(date))
+            raise  TypeError, utils.mapping(_("Invalid Date: $1"),(str(date),))    
 
     def setComment(self, comment):
         """setOwner(self, comment)
@@ -2256,9 +2270,9 @@
         return _factor
 
     def setTree(self, code, child_code, position, factor, yield_, total,
-                list_lines, label, type):
+                list_lines, label, type_):
         """setTree(self, code, child_code, position, factor,yield_, total,
-        list_lines, label, type)
+        list_lines, label, type_)
         
         code: the parent record code
         child_code: child record code
@@ -2282,17 +2296,25 @@
             width: Width (c)
             height: Height (d)
         label: Record Identifiers that are used by some measure programs.
-        type: type of action
+        type_: type of action
             M: Set measure
             A: Add measure
         Sets the decomposition of a record in a child record
         """
+        if code is None: # No-estructured measures
+            code = self.getRoot()
+            if code == None: # No root
+                print "No-estructured measures. Adding root record", 
+                self.setRecord("root", [], 0, "", "", [0.0,], [(1,1,1970)],
+                                     0, "")       
+                code = self.getRoot()
+
         if not utils.is_valid_code(code)[0]:
             raise ValueError, utils.mapping(_("Invalid parent code: $1"),
                                             (code,))
         if not utils.is_valid_code(child_code)[0]:
-            raise ValueError, utils.mapping(_("Invalid child code: $1"),
-                                           (code,))
+            raise ValueError, utils.mapping(_("Invalid child code: $1 $2"),
+                                           (code,child_code))
         if not isinstance(position, int):
             raise ValueError, utils.mapping(_("Invalid position in measure "\
                   "$1, in code $2"), (parent_code, position))
@@ -2306,6 +2328,7 @@
                       "$1, child code: $2, repeated code: $3"),
                       (code, child_code, _parent_code))
                 return
+
         # Creating reference to parent code in child record
         if child_code in self.__records:
             _child_record = self.__records[child_code]
@@ -2320,8 +2343,21 @@
             # if the code exits retake previous values.
             _record = self.__records[code]
             _child_number = len(_record.children)
-            if position == -1:
+            if position == -1: # New child
                 position = _child_number
+            if position == -2: # No-estructured measures or empty position (error in FIEBDC file)
+                positions = _record.getChildPositions(child_code)
+                if len(positions) == 1:
+                    position = positions[0]
+                    print utils.mapping(_("No-estructured measure or empty position. Parent Code: "\
+                          "$1, Child code: $2, Position: $3"),(code, child_code, position))
+                else:
+                    position = _child_number
+                    print utils.mapping(_("No-estructured measure or empty position. "\
+                          "Repeated child in unspecified position. "\
+                          "It is impossible to determine the position. "\
+                          "New child is added in the decomposition. "\
+                          "Parent code: $1, Child code: $2, Position: $3"),(code, child_code, position))
             if position == _child_number:
                 # The record do not have the child
                 if not isinstance(factor, float): factor = 1.0
@@ -2329,7 +2365,7 @@
                 if not isinstance(total, float): total = 0.0
                 if not isinstance(list_lines, list): list_lines = []
                 _child = _record.appendChild(child_code, self.getDecimals(),
-                         factor, yield_, total, list_lines, type, label)
+                         factor, yield_, total, list_lines, type_, label)
             elif position < _child_number:
                 # The record have the child
                 _child = _record.children[position]
@@ -2351,7 +2387,7 @@
                         yield_ = 0.0
                     _measure.setMeasure(total, self.getDecimals())
                 if isinstance(list_lines, list) and len(list_lines) > 0:
-                    _measure.buildMeasure(list_lines, type, self.getDecimals(),
+                    _measure.buildMeasure(list_lines, type_, self.getDecimals(),
                                           _record.recordType)
                 if isinstance(label, str) and label != "" :
                     _measure.label = label
@@ -2374,14 +2410,15 @@
                       "Position: $3"), (code, child_code, position))
                 return
             if not isinstance(factor, float):
-                factor == 1.0
+                factor = 1.0
             if not isinstance(yield_, float):
                 yield_ = 1.0
+            if not isinstance(total, float):
+                total = 1.0
             _record = self.setRecord(code, [], "", "", "", [], [],
                                      "", "")
             _child = _record.appendChild(child_code, self.getDecimals(),
-                         factor, yield_, total, list_lines, type, label)
-            _child.budgetMeasures[0] = measure
+                         factor, yield_, total, list_lines, type_, label)
 
     def eval_formula(self, formula, a, b, c, d):
         """eval_formula(self, formula, a, b, c, d)
@@ -2474,9 +2511,9 @@
             _record.text = text
 
     def setRecord(self, code, synonyms, hierarchy, unit, summary, price, date,
-                  type, subtype):
+                  type_, subtype):
         """setRecord(self, code, synonyms, hierarchy, unit, summary, price,
-                     date, type, subtype)
+                     date, type_, subtype)
         
         code: Code string
         synonyms: List of synonym codes of the record
@@ -2488,7 +2525,7 @@
         summary: Short description of a record
         price: List of prices
         date: List of dates
-        "type" and "subtype":
+        "type_" and "subtype":
             0 Without classifying
                EA  Auxiliary element
                EU  Unitary element
@@ -2529,6 +2566,8 @@
             else:
                 print _("Only can be one root record")
                 return
+                # TODO: If the root is created in settree. No-estructured measures
+                # TODO  Rewrite root values
         # retake previous values.
         # TODO: test synonyms
         _budget = self
@@ -2536,12 +2575,12 @@
             if code[-1] == "$":
                 _record = ParametricRecord(_budget.getDecimals(), code,
                                            synonyms, hierarchy,
-                                           unit, summary, [], type, subtype,
+                                           unit, summary, [], type_, subtype,
                                            [], "")
             else:
                 _record = Record(_budget.getDecimals(), code, synonyms,
                                  hierarchy, unit,
-                                 summary, [], type, subtype,[], "")
+                                 summary, [], type_, subtype,[], "")
             self.__records[code] = _record
             _prices = [[price[i], date[i]] for i in range(len(price))]
             _record.setPrices(_prices, self.getDecimals())
@@ -2559,14 +2598,14 @@
                 _prices = _record.prices
             else:
                 _prices = [ [price[i], date[i]] for i in range(len(price))]
-            if type == "":
-                type = _record.recordType.type
+            if type_ == "":
+                type_ = _record.recordType.type
             _record.synonyms = synonyms
             _record.unit = unit
             _record.summary = summary
             _record.setPrices(_prices, self.getDecimals())
             _record.recordType.hierarchy = hierarchy
-            _record.recordType.type = type
+            _record.recordType.type = type_
             _record.recordType.subtype = subtype
         return _record
 
@@ -2747,7 +2786,7 @@
                 self.setSheetSection(section, "")
             _sheet = self.getRecord(record_code).getSheet()
             _sheet.addSection(field, section, paragraph)
-    def addFile(self, record_code, filepath, type, description):
+    def addFile(self, record_code, filepath, type_, description):
         if not isinstance(record_code, str):
             raise ValueError, _("The record_code code must be a string")
         if not isinstance(filepath, str):
@@ -2761,7 +2800,7 @@
             return
         #-#
         _record = self.getRecord(record_code)
-        _record.addFile(filepath, type, description)
+        _record.addFile(filepath, type_, description)
     def setCompany(self, company_code, sumamary, name, offices,
                    cif, web, email):
         if not isinstance(company_code, str):
@@ -3018,9 +3057,9 @@
         self.__fax = tuple[8]
         self.__contact_person = tuple[9]
 
-    def __init__(self, type, subname, address, postal_code, town, province,
+    def __init__(self, type_, subname, address, postal_code, town, province,
                  country, phone, fax, contact_person):
-        self.officeType = type
+        self.officeType = type_
         self.subname = subname
         self.address = address
         self.postal_code = postal_code
@@ -3032,8 +3071,8 @@
         self.contact_person = contact_person
     def getOfficeType(self):
         return self.__officeType
-    def setOfficeType(self, type):
-        self.__officeType = type
+    def setOfficeType(self, type_):
+        self.__officeType = type_
     def getSubname(self):
         return self.__subname
     def setSubname(self, subname):
@@ -3249,7 +3288,7 @@
     Description:
         File object
     Constructor:
-        base.File(name, type, description)
+        base.File(name, type_, description)
     Ancestry:
     +-- object
       +-- File
@@ -3260,7 +3299,7 @@
     Methods:
         __getstate__(self)
         __setstate__(self, tuple)
-        __init__(self, path,type, description)
+        __init__(self, path,type_, description)
         {get/set}Name
         {get/set}FileType
         {get/set}Description
@@ -3280,9 +3319,9 @@
         self.__name = tuple[0]
         self.__fileType = tuple[1]
         self.__description = tuple[2]
-    def __init__(self, name, type, description):
+    def __init__(self, name, type_, description):
         self.name = name
-        self.fileType = type
+        self.fileType = type_
         self.description = description
     def getName(self):
         return self.__name
@@ -3290,8 +3329,8 @@
         self.__name = name
     def getFileType(self):
         return self.__fileType
-    def setFileType(self, type):
-        self.__fileType = type
+    def setFileType(self, type_):
+        self.__fileType = type_
     def getDescription(self):
         return self.__description
     def setDescription(self, description):
@@ -3356,7 +3395,7 @@
                                2 -> None,Q,%
                                3 -> None,MC,MCr,MM,MS,ME,MCu,Mal,ML,M
     Constructor:
-        base.File(hierarchy,type,subtype)
+        base.File(hierarchy,type_,subtype)
     Ancestry:
     +-- object
       +-- RecordType
@@ -3385,24 +3424,27 @@
         self.__hierarchy = tuple[0]
         self.__type = tuple[1]
         self.__subtype = tuple[2]
-    def __init__(self, hierarchy, type, subtype):
+    def __init__(self, hierarchy, type_, subtype):
         self.hierarchy = hierarchy
-        self.type = type
+        self.type = type_
         self.subtype = subtype
     def getHierarchy(self):
         return self.__hierarchy
     def setHierarchy(self, hierarchy):
-        if not hierarchy in [-1, 0 , 1 ,2]:
+        if not hierarchy in [-1, 0 , 1 ,2, ""]:
             raise ValueError, utils.mapping(_("Invalid Hierarchy ($1) "\
-                  "The hierarchy must be -1, 0, 1 or 2"), (str(hierarchy)))
+                  "The hierarchy must be -1, 0, 1, 2"), (str(hierarchy),))
+        elif hierarchy == "":
+            print "Hierarchy temporarily set to an empty string"
+        #TODO Check empty Hierarchy in Generic.fiebdc.Read._testBudget
         self.__hierarchy = hierarchy
     def getType(self):
         return self.__type
-    def setType(self, type):
-        if not type in  ["", 0, 1, 2, 3] :
+    def setType(self, type_):
+        if not type_ in  ["", 0, 1, 2, 3] :
             raise ValueError, utils.mapping(_("Invalid type ($1),"\
-                  "the type must be (empty string,0,1,2,3)"),(str(type)))
-        self.__type = type
+                  "the type must be (empty string,0,1,2,3)"),(str(type_)),)
+        self.__type = type_
     def getSubtype(self):
         return self.__subtype
     def setSubtype(self, subtype):
@@ -3412,7 +3454,7 @@
             raise ValueError, utils.mapping(_("Invalid subtype ($1), The "\
                   "subtype must one in (empty string, EA, "\
                   "EU, EC, EF, OB, PA, PU, H, Q, %, MC, MCr, "\
-                  "MM, MS, ME, MCu, MAl, ML, M)"), (str(subtype)))
+                  "MM, MS, ME, MCu, MAl, ML, M)"), (str(subtype),))
         self.__subtype = subtype
     hierarchy = property(getHierarchy, setHierarchy, None,
     """Record Hierarchy