diff --git a/web/calculators/__init__.py b/web/calculators/__init__.py index e607155..4734d93 100644 --- a/web/calculators/__init__.py +++ b/web/calculators/__init__.py @@ -1,4 +1,10 @@ +from commons.models.data_fujian import DataFujian +from commons.models.data_network import DataNetwork +from commons.models.fujian_survey import FujianSurvey +from commons.models.fuzhou_highway_bureau import FuzhouHighwayBureau +from commons.models.fuzhou_transportation_bureau import FuzhouTransportationBureau from commons.models.price_result import PriceResult +from commons.models.sanming_steel import SanmingSteel class Helper: @@ -47,6 +53,12 @@ class Calculator: fluctuating_recommend = 0 price_fujian = 0 fluctuating_fujian = 0 + weight_ftb = 0 + weight_ss = 0 + weight_fhb = 0 + weight_network = 0 + weight_survey = 0 + unit = "" spec = '' @@ -87,6 +99,11 @@ class Calculator: 'fluctuating_recommend': self.fluctuating_recommend, 'price_fujian': self.price_fujian, 'fluctuating_fujian': self.fluctuating_fujian, + 'weight_ftb': self.weight_ftb, + 'weight_ss': self.weight_ss, + 'weight_fhb': self.weight_fhb, + 'weight_network': self.weight_network, + 'weight_survey': self.weight_survey, 'unit': self.unit, 'spec': self.spec, } @@ -103,30 +120,57 @@ class Calculator: self.price_fujian, self.fluctuating_fujian = self._get_fujian_price() return self + # todo 缺少三明钢铁导入数据 + # todo-0 价格计算改为直接从表读取 不再进行多余计算 + # todo 计算验证 + def _get_ftb_price(self): - return 0, 0 + query = FuzhouTransportationBureau.get_query(self.year, self.month, material_id=self.material_id) + data = query.first() + price = data.price if data else 0 + fluctuating = self._get_fluctuating('price_ftb', price) + return price, fluctuating def _get_ss_price(self): - return 0, 0 + query = SanmingSteel.get_query(self.year, self.month, name='高线', spec='φ10mm') + data = query.first() + price = int(data.price) if data else 0 + fluctuating = int(self._get_fluctuating('price_ss', price)) + return price, fluctuating def _get_fhb_price(self): - return 0, 0 + query = FuzhouHighwayBureau.get_query(self.year, self.month, material_id=self.material_id) + data = query.first() + price = data.price if data else 0 + fluctuating = self._get_fluctuating('price_fhb', price) + return price, fluctuating def _get_network_price(self): - return 0, 0 + query = DataNetwork.get_query(self.year, self.month, material_id=self.material_id) + data = query.first() + price = data.price if data else 0 + fluctuating = self._get_fluctuating('price_network', price) + return price, fluctuating def _get_survey_price(self): - return 0, 0 + query = FujianSurvey.get_query(self.year, self.month, material_id=self.material_id) + data = query.first() + price = data.price if data else 0 + fluctuating = self._get_fluctuating('price_survey', price) + return price, fluctuating def _get_fujian_price(self): - return 0, 0 + query = DataFujian.get_query(self.year, self.month, number=self.material_id) + data = query.first() + price = data.price if data else 0 + fluctuating = self._get_fluctuating('price_fujian', price) + return price, fluctuating def _get_last_month_price(self): return getattr(self.previous_prices, 'price_recommend', 0) - def _get_calculate_price(self, round_dit=0): - prices = ( - self.price_ftb, self.price_ss, self.price_fhb, self.price_network, self.price_survey, self.price_last_month) + def _get_calculate_price(self, round_dit=2): + prices = (self.price_ftb, self.price_ss, self.price_fhb, self.price_network, self.price_survey, self.price_last_month) total = sum(float(i) for i in prices) if total == 0: return 0 @@ -135,6 +179,8 @@ class Calculator: return result def _get_recommend_price(self, round_by=10): + self._get_weight() + if not self.previous_prices: return 0, 0 @@ -142,14 +188,38 @@ class Calculator: if not previous_price: previous_price = int(getattr(self.previous_prices, 'price_calculate', 0)) + self._fluctuatings = [ + self.fluctuating_ftb * self.weight_ftb, + self.fluctuating_ss * self.weight_ss, + self.fluctuating_fhb * self.weight_fhb, + self.fluctuating_network * self.weight_network, + self.fluctuating_survey * self.weight_survey, + ] fluctuating = sum(self._fluctuatings) / len(self._fluctuatings) - fluctuating = round(fluctuating / round_by) * round_by + fluctuating = round(fluctuating, 2) + # fluctuating = round(fluctuating / round_by) * round_by price = fluctuating + previous_price - price = round(price / round_by) * round_by + price = round(price, 2) + # price = round(price / round_by) * round_by return price, fluctuating + def _get_weight(self): + # 如果有上月数据按上月权重计算 无则平均数 + if self._previous_prices: + self.weight_ftb = self._previous_prices.weight_ftb + self.weight_ss = self._previous_prices.weight_ss + self.weight_fhb = self._previous_prices.weight_fhb + self.weight_network = self._previous_prices.weight_network + self.weight_survey = self._previous_prices.weight_survey + else: + self.weight_ftb = 1 if self.fluctuating_ftb else 0 + self.weight_ss = 1 if self.fluctuating_ss else 0 + self.weight_fhb = 1 if self.fluctuating_fhb else 0 + self.weight_network = 1 if self.fluctuating_network else 0 + self.weight_survey = 1 if self.fluctuating_survey else 0 + def save(self): result = self.result() PriceResult(**result).upsert() @@ -157,7 +227,7 @@ class Calculator: def _get_fluctuating(self, field_name, price): previous_price = getattr(self.previous_prices, field_name, 0) or price fluctuating = price - previous_price if price else 0 - return fluctuating + return round(fluctuating, 2) if __name__ == '__main__': diff --git a/web/commons/models/data_fujian.py b/web/commons/models/data_fujian.py index 5ecd397..077e517 100644 --- a/web/commons/models/data_fujian.py +++ b/web/commons/models/data_fujian.py @@ -40,11 +40,13 @@ class DataFujian(db.Model, Model, BaseModelMixin): return result @classmethod - def get_query(cls, year=None, month=None, name=None, spec=None, name_in=None, region='福州'): + def get_query(cls, year=None, month=None, name=None, spec=None, name_in=None, region='福州', number=None): query = cls.query if year and month: query = query.filter(cls.year == year) query = query.filter(cls.month == month) + if number: + query = query.filter(cls.number == number) if name: query = query.filter(cls.name == name) if name_in: diff --git a/web/commons/models/data_network.py b/web/commons/models/data_network.py index ce74568..a8b7aaa 100644 --- a/web/commons/models/data_network.py +++ b/web/commons/models/data_network.py @@ -41,12 +41,14 @@ class DataNetwork(db.Model, Model, BaseModelMixin): return result @classmethod - def get_query(cls, year, month, name=None, spec=None, region="福州"): + def get_query(cls, year, month, name=None, spec=None, region="福州", material_id=None): start_date = datetime.date(year, month, 1) end_date = start_date + relativedelta(months=1) query = cls.query query = query.filter(cls.date >= start_date) query = query.filter(cls.date < end_date) + if material_id: + query = query.filter(cls.material_id == material_id) if name: query = query.filter(cls.name.like(f'%{name}%')) if spec: diff --git a/web/commons/models/fujian_survey.py b/web/commons/models/fujian_survey.py index 6b59f07..eb266b4 100644 --- a/web/commons/models/fujian_survey.py +++ b/web/commons/models/fujian_survey.py @@ -36,7 +36,7 @@ class FujianSurvey(db.Model, Model, BaseModelMixin): return result @classmethod - def get_query(cls, year=None, month=None, name=None, spec=None, name_in=None, region='福州'): + def get_query(cls, year=None, month=None, name=None, spec=None, name_in=None, region='福州', material_id=None): query = cls.query if year and month: start_date = datetime.date(year, month, 1) @@ -45,6 +45,8 @@ class FujianSurvey(db.Model, Model, BaseModelMixin): query = query.filter(cls.date < end_date) if name: query = query.filter(cls.name == name) + if material_id: + query = query.filter(cls.material_id == material_id) if name_in: query = query.filter(cls.name.in_(name_in)) if spec: diff --git a/web/commons/models/fuzhou_highway_bureau.py b/web/commons/models/fuzhou_highway_bureau.py index d9f7a64..f169638 100644 --- a/web/commons/models/fuzhou_highway_bureau.py +++ b/web/commons/models/fuzhou_highway_bureau.py @@ -35,7 +35,7 @@ class FuzhouHighwayBureau(db.Model, Model, BaseModelMixin): return result @classmethod - def get_query(cls, year, month, name, spec=None, region='福州'): + def get_query(cls, year, month, name=None, spec=None, region='福州', material_id=None): start_date = datetime.date(year, month, 1) end_date = start_date + relativedelta(months=1) query = cls.query @@ -45,6 +45,8 @@ class FuzhouHighwayBureau(db.Model, Model, BaseModelMixin): query = query.filter(cls.name == name) if spec: query = query.filter(cls.spec == spec) + if material_id: + query = query.filter(cls.material_id == material_id) if region: query = query.filter(cls.region.like(f'%{region}%')) return query diff --git a/web/commons/models/fuzhou_transportation_bureau.py b/web/commons/models/fuzhou_transportation_bureau.py index 73366db..7d2d3ce 100644 --- a/web/commons/models/fuzhou_transportation_bureau.py +++ b/web/commons/models/fuzhou_transportation_bureau.py @@ -35,7 +35,7 @@ class FuzhouTransportationBureau(db.Model, Model, BaseModelMixin): return result @classmethod - def get_query(cls, year, month, name, spec=None, region='福州'): + def get_query(cls, year, month, name=None, spec=None, region='福州', material_id=None): start_date = datetime.date(year, month, 1) end_date = start_date + relativedelta(months=1) query = cls.query @@ -47,4 +47,6 @@ class FuzhouTransportationBureau(db.Model, Model, BaseModelMixin): query = query.filter(cls.spec.like(f'%{spec}%')) if region: query = query.filter(cls.region.like(f'%{region}%')) + if material_id: + query = query.filter(cls.material_id == material_id) return query diff --git a/web/commons/models/price_result.py b/web/commons/models/price_result.py index 8e9fc04..ec66c9e 100644 --- a/web/commons/models/price_result.py +++ b/web/commons/models/price_result.py @@ -29,6 +29,11 @@ class PriceResult(db.Model, Model, OperationTrackMixin, BaseModelMixin): fluctuating_recommend = Column('FLUCTUATING_RECOMMEND', Numeric(16, 4), default=0, comment='推荐浮动') price_fujian = Column('PRICE_FUJIAN', Numeric(16, 4), default=0, comment='住建厅价格') fluctuating_fujian = Column('FLUCTUATING_FUJIAN', Numeric(16, 4), default=0, comment='住建厅浮动') + weight_ftb = Column('WEIGHT_FTB', Numeric(16, 4), default=0, comment='') + weight_ss = Column('WEIGHT_SS', Numeric(16, 4), default=0, comment='') + weight_fhb = Column('WEIGHT_FHB', Numeric(16, 4), default=0, comment='') + weight_network = Column('WEIGHT_NETWORK', Numeric(16, 4), default=0, comment='') + weight_survey = Column('WEIGHT_SURVEY', Numeric(16, 4), default=0, comment='') spec = Column('SPEC', String(128), default='', comment='规格') unit = Column('UNIT', String(128), default='', comment='单位') diff --git a/web/tasks/once/calculate.py b/web/tasks/once/calculate.py index 7ca515a..a5a949b 100644 --- a/web/tasks/once/calculate.py +++ b/web/tasks/once/calculate.py @@ -19,37 +19,67 @@ def calculate(year=2023, month=8): """ 计算生成趋势表 """ - # todo-1 价格计算触发器 - for Calculator in [ - AsphaltDomesticCalculator, - AsphaltImportedCalculator, - Cement325Calculator, - Cement425Calculator, - Oil0Calculator, - Oil89Calculator, - Oil92Calculator, - SteelPlateCalculator, - Reber300Calculator, - Reber400Calculator, - SteelSectionCalculator, - SteelStrandCalculator, - ModifierCalculator, - AsphaltDomesticModifierCalculator, - AsphaltImportedModifierCalculator, + from calculators import Calculator + + for material_id, name, spec, unit in [ + ['2001001', 'HPB300钢筋', '', 't'], + ['2001002', 'HRB400钢筋', '', 't'], + ['2001008', '钢绞线', '普通,无松弛,Φ15.24', 't'], + ['2003004', '型钢', '工字钢, 角钢 Ⅰ20', 't'], + ['2003005', '钢板', 'A3, δ=5~40mm', 't'], + ['2003005001', '钢板', 'Q355', 't'], + ['5509001', '32.5级水泥', '旋窑', 't'], + ['5509002', '42.5级水泥', '旋窑', 't'], + ['5509003', '52.5级水泥', '', 't'], + ['3001001002', '石油沥青', '国产', 't'], + ['3001001001', '石油沥青', '进口', 't'], + ['3001002002', '改性石油沥青', '进口', 't'], + ['3001002001', '改性石油沥青', '国产', 't'], + ['3003002001', '汽油', '89#', 'kg'], + ['3003002002', '汽油', '92#', 'kg'], + ['3003003', '柴油', '0#', 'kg'], ]: calculator = Calculator(year=year, month=month) + calculator.name = name + calculator.material_id = material_id + calculator.unit = unit + calculator.spec = spec _result = calculator.run() calculator.save() print(_result) + # # todo-1 价格计算触发器 + # for Calculator in [ + # AsphaltDomesticCalculator, + # AsphaltImportedCalculator, + # Cement325Calculator, + # Cement425Calculator, + # Oil0Calculator, + # Oil89Calculator, + # Oil92Calculator, + # SteelPlateCalculator, + # Reber300Calculator, + # Reber400Calculator, + # SteelSectionCalculator, + # SteelStrandCalculator, + # # ModifierCalculator, + # AsphaltDomesticModifierCalculator, + # AsphaltImportedModifierCalculator, + # ]: + # calculator = Calculator(year=year, month=month) + # _result = calculator.run() + # calculator.save() + # print(_result) + + if __name__ == '__main__': from core.factory import ClientApp with ClientApp().app_context(): - for i in range(2, 12): - calculate(2022, i+1) - for i in range(0, 12): - calculate(2023, i+1) - for i in range(0, 9): + # for i in range(2, 12): + # calculate(2022, i+1) + # for i in range(0, 12): + # calculate(2023, i+1) + for i in range(6, 9): calculate(2024, i+1) diff --git a/web/tasks/once/collect.py b/web/tasks/once/collect.py index d8c0f5e..fbb7bdd 100644 --- a/web/tasks/once/collect.py +++ b/web/tasks/once/collect.py @@ -13,9 +13,9 @@ if __name__ == '__main__': from core.factory import ClientApp with ClientApp().app_context(): - for i in range(2, 12): - collect(2022, i + 1) - for i in range(0, 12): - collect(2023, i + 1) - for i in range(0, 9): + # for i in range(2, 12): + # collect(2022, i + 1) + # for i in range(0, 12): + # collect(2023, i + 1) + for i in range(10, 12): collect(2024, i + 1)