diff --git a/src/ifc5d/ifc5d/csv2ifc.py b/src/ifc5d/ifc5d/csv2ifc.py index 7632b10f44..11e14365cd 100644 --- a/src/ifc5d/ifc5d/csv2ifc.py +++ b/src/ifc5d/ifc5d/csv2ifc.py @@ -20,6 +20,8 @@ import csv import ifcopenshell import ifcopenshell.api import ifcopenshell.util.unit +import ifcopenshell.util.selector +import ifcopenshell.util.element import locale @@ -67,11 +69,15 @@ class Csv2Ifc: identification = row[self.headers["Identification"]] if "Identification" in self.headers else None quantity = row[self.headers["Quantity"]] unit = row[self.headers["Unit"]] + assignments = { + "PropertyName": row[self.headers["Property"]], + "Query": row[self.headers["Query"]], + } if self.has_categories: cost_values = { k: locale.atof(row[v]) for k, v in self.headers.items() - if k not in ["Hierarchy", "Identification", "Name", "Quantity", "Unit", "Subtotal"] and row[v] + if k not in ["Hierarchy", "Identification", "Name", "Quantity", "Unit", "Subtotal", "Property", "Query"] and row[v] } else: cost_values = row[self.headers["Value"]] @@ -82,6 +88,7 @@ class Csv2Ifc: "Quantity": float(quantity) if quantity else None, "Unit": str(unit) if unit else None, "CostValues": cost_values, + "assignments": assignments, "children": [], } @@ -107,7 +114,7 @@ class Csv2Ifc: cost_item["ifc"].Name = cost_item["Name"] cost_item["ifc"].Identification = cost_item["Identification"] - if not cost_item["CostValues"]: + if not cost_item["CostValues"] and cost_item["children"]: if not self.is_schedule_of_rates: cost_value = ifcopenshell.api.run("cost.add_cost_value", self.file, parent=cost_item["ifc"]) cost_value.Category = "*" @@ -115,7 +122,11 @@ class Csv2Ifc: for category, value in cost_item["CostValues"].items(): cost_value = ifcopenshell.api.run("cost.add_cost_value", self.file, parent=cost_item["ifc"]) cost_value.AppliedValue = self.file.createIfcMonetaryMeasure(value) - cost_value.Category = category + if category != "Rate" or category != "Price": + if "Rate" in category or"Price" in category: + category = category.replace("Rate","") + category = category.strip() + cost_value.Category = category else: cost_value = ifcopenshell.api.run("cost.add_cost_value", self.file, parent=cost_item["ifc"]) cost_value.AppliedValue = self.file.createIfcMonetaryMeasure(cost_item["CostValues"]) @@ -144,6 +155,15 @@ class Csv2Ifc: "cost.add_cost_item_quantity", self.file, cost_item=cost_item["ifc"], ifc_class=quantity_class ) quantity[3] = cost_item["Quantity"] + + if cost_item["assignments"]["PropertyName"] and cost_item["assignments"]["Query"]: + print("for query",cost_item["assignments"]["Query"]) + results = ifcopenshell.util.selector.filter_elements(self.file, cost_item["assignments"]["Query"]) + + results = [r for r in results if has_property(self.file, r, cost_item["assignments"]["PropertyName"])] + if results: + ifcopenshell.api.run("cost.assign_cost_item_quantity", self.file, cost_item=cost_item["ifc"], products=results, prop_name=cost_item["assignments"]["PropertyName"]) + self.create_cost_items(cost_item["children"], cost_item["ifc"]) def create_unit(self, symbol): @@ -158,3 +178,11 @@ class Csv2Ifc: def create_boilerplate_ifc(self): self.file = ifcopenshell.file(schema="IFC4") + +def has_property(self, product, property_name): + qtos = ifcopenshell.util.element.get_psets(product, qtos_only=True) + for qset, quantities in qtos.items(): + for quantity, value in quantities.items(): + if quantity == property_name: + return True + return False \ No newline at end of file diff --git a/src/ifc5d/sample_cost_schedule_house_FR.csv b/src/ifc5d/sample_cost_schedule_house_FR.csv new file mode 100644 index 0000000000..18480f0873 --- /dev/null +++ b/src/ifc5d/sample_cost_schedule_house_FR.csv @@ -0,0 +1,147 @@ +Hierarchy,Identification,Name,Quantity,Unit,Contract,Rate,Material Rate,Labor Rate,Subtotal,Property,Query +1,DB,Design and build,,,,,,,,, +2,DB.1,Design,,,,,,,,, +3,DB.1.1,Architecte,1,unit,40000,,,,40000,, +3,DB.1.2,Bet structure,1,unit,10000,,,,10000,, +3,DB.1.3,Bet lots techniques,1,unit,8000,,,,8000,, +2,DB.2,Construction,,,,,,,,, +3,DB.2.1,Go & etancheite,,,,,,,,, +4,DB.2.1.1,Gros oeuvre,,,,,,,,, +4,DB.2.1.2,Etancheite,,,,,,,,, +5,DB.2.1.2.1,Forme de pente et chape de lissage,,,,97,,,,NetArea,"IfcSlab, location=Roof" +5,DB.2.1.2.2,Ecran pare-vapeur et isolation thermique,,,,47,,,,NetArea,"IfcSlab, location=Roof" +5,DB.2.1.2.3,Systeme d’etancheite bicouche,,,,23,,,,NetArea,"IfcCovering, type=Etancheite_H" +5,DB.2.1.2.4,Reliefs d’etancheite bicouche,,,,7,,,,Length,"IfcWall, type=”BLK150”, location=Roof" +5,DB.2.1.2.5,Protection horizontales d’etancheite par carreaux de ciment,,,,,,,,NetArea,"IfcCovering, type=Etancheite_H" +5,DB.2.1.2.6,Protection des reliefs d’etancheite,,,,,,,,, +5,DB.2.1.2.7,Etancheite legere,,,,,,,,, +5,DB.2.1.2.8,Fourniture et pose de gargouilles y compris crapaudines,3,unit,,,,,,, +,,,,,,,,,,, +4,DB.2.1.3,Gros oeuvre piscine,,,,,,,,, +5,DB.2.1.3.1,Fouilles en pleine masse dans tous terrains y compris rocher,,,,,,,,, +5,DB.2.1.3.2,Remblaiement ou evacuation aux decharges publiques,,,,,,,,, +5,DB.2.1.3.3,Beton de proprete,,,,,,,,, +5,DB.2.1.3.4,Beton hydrofuge pour tous les ouvrages en fondation et elevation,,,,,,,,, +5,DB.2.1.3.5,Aciers a haute limite elastique fe500 pour les ouvrages en fondation et elevation,,,,,,,,, +,,,,,,,,,,, +4,DB.2.1.4,Maconnerie et briquetage en elevation,,,,,,,,, +5,DB.2.1.5.1,Cloisons en briques creuses 7t,,,,,,,,, +5,DB.2.1.5.2,Doubles cloisons en briques creuses 7t+vide10+7t,,,,,,,,, +,,,,,,,,,,, +,,,,,,,,,,, +4,DB.2.1.5,Enduits interieurs et exterieurs,,,,,,,,, +5,DB.2.1.5.1,"Enduit interieur au mortier de ciment sur murs et plafonds y +Compris baguettes d'angles",,,,,,,,, +5,DB.2.1.5.1.1,Enduit interieur au platre,,,,,,,,, +5,DB.2.1.5.1.2,"Enduit projete exterieur au mortier de ciment y compris baguettes +D'angles",,,,,,,,, +5,DB.2.1.5.1.3,Enduit de couronnement d'acroteres y compris facon de larmier,,,,,,,,, +,,,,,,,,,,, +4,DB.2.1.5,Reseaux sous dallage,,,,,,,,, +5,DB.2.1.5.1,Canalisation en buse pvc type assainissement serie i,,,,,,,,, +6,DB.2.1.5.1.1,Tranchee ,,,,,,,,, +6,DB.2.1.5.1.2,P.v.c diametre de 200 mm,,,,,,,,, +,,,,,,,,,,, +5,DB.2.1.5.2,Regards en beton arme ,,,,,,,,, +6,DB.2.1.5.2.1,Regards visitable de 50x50 cm,,,,,,,,, +6,DB.2.1.5.2.2,Regards non visitable de 40x40 cm,,,,,,,,, +4,DB.2.1.5,Divers,,,,,,,,, +5,DB.2.1.5.1,Gaine technique d’aeration et habillage des descentes des eaux ,,,,,,,,, +,,,,,,,,,,, +3,DB.2.2,Fluides,,,,,,,,, +4,DB.2.2.1,Plomberie,,,,,,,,, +4,DB.2.2.2,Climatisation,,,,,,,,, +4,DB.2.2.3,Sanitaire,,,,,,,,, +3,DB.2.3,Electricite,,,,,,,,, +4,DB.2.3.1,Eclairage et appareillage,,,,,,,,, +4,DB.2.3.2,Panneaux solaires,,,,,,,,, +3,DB.2.4,Architecture interieure,,,,,,,,, +4,DB.2.4.1,Menuiserie metallique,,,,,,,,, +5,DB.2.4.1.1,G.c 1 en vitrage bord àbord 10*10*2(1unite) rail en alu encastre,,,,,,,,, +5,DB.2.4.1.2,G.c 2 en vitrage bord àbord 10*10*2(1unite) rail en alu encastre,,,,,,,,, +,,,,,,,,,,, +4,DB.2.4.2,Menuiserie bois,,,,,,,,, +5,DB.2.4.2.1,Portes,,,,,,,,, +6,DB.2.4.2.1.1,P1,,,,,,,,Count,"IfcDoor, type=P1" +6,DB.2.4.2.1.2,P2,,,,,,,,Count,"IfcDoor, type=P2-LEFT + IfcDoor, type=P2-RIGHT" +6,DB.2.4.2.1.3,P3,,,,,,,,Count,"IfcDoor, type=P3-LEFT + IfcDoor, type=P3-RIGHT" +,,,,,,,,,,, +5,DB.2.4.2.2,Placards et habillage,,,,,,,,, +6,DB.2.4.2.2.1,Fourniture placard type 1,,,,,,,,, +6,DB.2.4.2.2.2,Fourniture placard type 2,,,,,,,,, +6,DB.2.4.2.2.3,Fourniture placard type 3 ,,,,,,,,, +6,DB.2.4.2.2.3,Fourniture placard type 4,,,,,,,,, +,,,,,,,,,,, +4,DB.2.4.3,Revetement sol parquet,,,,,,,,, +5,DB.2.4.3.1,Fourniture parquet contrecolle 18mm dont epaisseur noyer americain 3mm,,,,,300,,,NetArea,"IfcCovering, type=RS-2" +5,DB.2.4.3.2,Fournitur basic underlay,,,,,50,,,NetArea,"IfcCovering, type=RS-2" +5,DB.2.4.3.3,"Fourniture profilpas finition laiton 2,5mm",,,,,20,,,Width,IfcDoor +5,DB.2.4.3.4,"Pose du parquet y compris isolant acoustique, chappe de ciment, sous-couche et barre de seuil",,,,,,74,,NetArea,"IfcCovering, type=RS-2" +,,,,,,,,,,, +4,DB.2.4.4,Revetement sol marbre,,,,,,,,, +5,DB.2.4.4.1,Fourniture marbre sols,,,,,,,,NetArea,"IfcCovering, type=RS-5" +5,DB.2.4.4.2,Fourniture marbre- sols sdb,,,,,,,,NetArea,"IfcCovering, type=RS-2" +5,DB.2.4.4.3,Fourniture marbre murs sdb ,,,,,,,,, +5,DB.2.4.4.4,Fourniture marbre marche escalier y/c nez,,,,,,,,, +5,DB.2.4.4.5,Pose marbre sols y compris chappe de ciment,,,,,,,,, +5,DB.2.4.4.6,Pose marbre murs,,,,,,,,, +5,DB.2.4.4.7,Pose marbre marches,,,,,,,,, +,,,,,,,,,,, +4,DB.2.4.5,Revetement carreaux,,,,,,,,, +5,DB.2.4.5.1,Revetements,,,,,,,,, +6,DB.2.4.5.1.1,Revêtement sol: cuisine - carreaux - gres cerame (30*60cm) - choix sous validation d'echantillons par l'architecte et le maitre d'ouvrage,,,,,,,,, +6,DB.2.4.5.1.2,Revêtement sol: salle de jeux - carreaux - gres cerame (30*60cm) - choix sous validation d'echantillons par l'architecte et le maitre d'ouvrage,,,,,,,,, +6,DB.2.4.5.1.3,Revêtement sol: (reserve) - gres cerame (30*60cm) - choix sous validation d'echantillons par l'architecte et le maitre d'ouvrage - ,,,,,,,,, +6,DB.2.4.5.1.4,Revêtement mural cuisine - carreaux - effet vitrage noir,,,,,,,,, +5,DB.2.4.5.2,Plinthes,,,,,,,,, +6,DB.2.4.5.2.1,Plinthes - duropolymer orac decor ref : sx157,,,,,,,,, +6,DB.2.4.5.2.2,Plinthes marches - - duropolymer orac decor ref : sx157,,,,,,,,, +,,,,,,,,,,, +4,DB.2.4.6,Peinture,,,,,,,,, +5,DB.2.4.6.1,Fourniture et pose peinture murs - marmorex astral y/c preparation (5 couches),,,,,,,,, +5,DB.2.4.6.2,Fourniture et pose peinture contremarche escalier - marmorex astral y/c preparation (5 couches,,,,,,,,, +5,DB.2.4.6.3,Fourniture et pose peinture murs cuisine - alpha tacto astral y/c preparation (5 couches),,,,,,,,, +5,DB.2.4.6.4,Foruniture et pose peinture faux-plafond - jotun acrylique mate blanc y/c preparation (5 couches),,,,,,,,, +5,DB.2.4.6.5,Fourniture et pose peinture murs sdb - jotun acrylique semi-brillant blanc special piece humide y/c preparation (5 couches),,,,,,,,, +5,DB.2.4.6.6,Fourniture et pose peinture faux-plafond sdb + cuisine - jotun acrylique semi-brillant blanc special piece humide y/c preparation (5 couches),,,,,,,,, +,,,,,,,,,,, +4,DB.2.4.7,Faux plafonds,,,,,,,,, +5,DB.2.4.7.1,Type 1,,,,,,,,, +5,DB.2.4.7.2,Type 2,,,,,,,,, +5,DB.2.4.7.3,Type 3 – hydrofuge – exterieur,,,,,,,,, +5,DB.2.4.7.4,Trappes d’acces,,,,,,,,, +,,,,,,,,,,, +4,DB.2.4.8,Cuisine,1,unit,,,,,,, +,,,,,,,,,,, +3,DB.2.5,Facade,,,,,,,,, +4,DB.2.5.1,Revetement exterieur ,,,,,,,,, +5,DB.2.5.1.1,Revetement mural: plus value enduit mural hydrofuge (monocouche),,,,,,,,, +5,DB.2.5.1.2,Revetement mural: pierre volcanique grise ,,,,,,,,, +5,DB.2.5.1.3,Revetement mural: bardage en bois iroko ou tole alu section carre ou rectangulaire avec habillage bois technowood (voir detail architecte),,,,,,,,, +5,DB.2.5.1.4,Revêtement sol: terrasses et cour - tech - choix sous validation d'echantillons par l'architecte et le maitre d'ouvrage ,,,,,,,,, +5,DB.2.5.1.5,Revetement sol: seuill entree en pierre de taza,,,,,,,,, +5,DB.2.5.1.6,Revetement sol: sous bassement perimetre villa en pierre de taza ,,,,,,,,, +,,,,,,,,,,, +4,DB.2.5.2,Menuiserie aluminium,,,,,,,,, +5,DB.2.5.2.1,Fenetres,,,,,,,,, +6,DB.2.5.2.1.1,F1,,,,,,,,, +6,DB.2.5.2.1.2,F2,,,,,,,,, +,,,,,,,,,,, +5,DB.2.5.2.2,Chassis ouvrants,,,,,,,,, +6,DB.2.5.2.2.1,Ch1,,,,,,,,, +6,DB.2.5.2.2.2,Ch2,,,,,,,,, +6,DB.2.5.2.2.3,Ch3,,,,,,,,, +,,,,,,,,,,, +5,DB.2.5.2.3,Portes coulissantes/ mur rideau,,,,,,,,, +6,DB.2.5.2.3.1,P4,,,,,,,,, +6,DB.2.5.2.3.2,P5,,,,,,,,, +6,DB.2.5.2.3.3,P6,,,,,,,,, +,,,,,,,,,,, +5,DB.2.5.2.4,Volets roulants,,,,,,,,, +6,DB.2.5.2.4.1,Type 1,,,,,,,,, +6,DB.2.5.2.4.2,Type 2,,,,,,,,, +6,DB.2.5.2.4.3,Type 3,,,,,,,,, +3,DB.2.6,Exterieur,,,,,,,,, +4,DB.2.6.1,Cloture,,,,,,,,, +4,DB.2.6.2,Piscine,,,,,,,,, +4,DB.2.6.3,Jardin,,,,,,,,, diff --git a/src/ifc5d/sample_cost_schedule_house_FR.ods b/src/ifc5d/sample_cost_schedule_house_FR.ods new file mode 100644 index 0000000000..3d8cb6bb1b Binary files /dev/null and b/src/ifc5d/sample_cost_schedule_house_FR.ods differ