data.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. import json
  2. from ..data_metaclass import DataBaseModel
  3. import copy
  4. import pandas as pd
  5. import settings
  6. import numpy as np
  7. class DataModeGenerateDetail(DataBaseModel):
  8. def __init__(self):
  9. super().__init__()
  10. self.get_online_data.refresh_headers()
  11. def get_real_color_name(self, color_name: str):
  12. _ = ["薄棉", "加厚", "厚棉"]
  13. for i in _:
  14. color_name = color_name.replace(i, "")
  15. return color_name
  16. def get_goods_art_no_info(self, numbers_list=None, goods_art_list=None):
  17. if goods_art_list:
  18. data_list = copy.deepcopy(goods_art_list)
  19. flag = "Goods_Art"
  20. else:
  21. data_list = copy.deepcopy(numbers_list)
  22. flag = "NUM"
  23. _list = []
  24. # 单次请求数少于20个
  25. goods_dict = {}
  26. while data_list:
  27. one_data = data_list.pop()
  28. _list.append(one_data)
  29. if len(_list) == 20 or len(data_list) == 0:
  30. if flag == "NUM":
  31. # 注意,红蜻蜓和惠利玛函数不同
  32. online_goods_art_data = self.get_online_data.get_goods_art_no_info(numbers_list=_list)
  33. else:
  34. online_goods_art_data = self.get_online_data.get_goods_art_no_info(goods_art_list=_list)
  35. if online_goods_art_data:
  36. for key in online_goods_art_data:
  37. # 映射为真实的文件夹名称
  38. goods_dict[key] = online_goods_art_data[key]
  39. _list = []
  40. return goods_dict
  41. def get_basic_goods_art_data_by_hqt_and_hlm(self, folder_name_list):
  42. """
  43. 查询红蜻蜓货号的对应数据,输入写入为编码,可能带有@,可能为货号等 NUN为编码
  44. """
  45. original_folder_name_list = copy.deepcopy(folder_name_list)
  46. # 编号与文件名映射表
  47. return_dict = {}
  48. for folder_name in original_folder_name_list:
  49. folder_name: str
  50. if "NUM" not in folder_name:
  51. # 即为货号
  52. return_dict[folder_name] = {"type": "goods_art_no",
  53. "name": folder_name.upper(),
  54. "文件夹名称": folder_name,
  55. "data": {}
  56. }
  57. else:
  58. if "@" not in folder_name:
  59. return_dict[folder_name] = {"type": "goods_number",
  60. "name": folder_name.upper().replace("NUM", ""),
  61. "文件夹名称": folder_name,
  62. "data": {}
  63. }
  64. else:
  65. return_dict[folder_name] = {"type": "goods_number",
  66. "name": folder_name.upper().replace("NUM", "").split("@")[1],
  67. "文件夹名称": folder_name,
  68. "data": {}
  69. }
  70. # -----------请求货号数据处理------------
  71. goods_art_no_list = [v["name"] for k, v in return_dict.items() if v["type"] == "goods_art_no"]
  72. goods_art_no_all_data = self.get_goods_art_no_info(goods_art_list=goods_art_no_list)
  73. for folder_name, value in return_dict.items():
  74. if value["type"] == "goods_art_no":
  75. if value["name"] in goods_art_no_all_data:
  76. return_dict[folder_name]["data"] = goods_art_no_all_data[value["name"]]
  77. # ------------请求编码数据----------------------
  78. goods_number_list = [v["name"] for k, v in return_dict.items() if v["type"] == "goods_number"]
  79. goods_number_all_data = self.get_goods_art_no_info(numbers_list=goods_number_list)
  80. for folder_name, value in return_dict.items():
  81. if value["type"] == "goods_number":
  82. if value["name"] in goods_number_all_data:
  83. return_dict[folder_name]["data"] = goods_number_all_data[value["name"]]
  84. # 清空没有值的数据
  85. error_key = []
  86. for folder_name, value in return_dict.items():
  87. if not value["data"]:
  88. error_key.append(folder_name)
  89. if error_key:
  90. for folder_name in error_key:
  91. return_dict.pop(folder_name)
  92. return {"code": 0, "message": "", "data": return_dict}
  93. def get_basic_goods_art_data_form_excel(self, folder_name_list, excel_path, keys):
  94. # =====创建虚拟表格并进行连表处理
  95. need_df = pd.DataFrame(columns=["文件夹名称"])
  96. for folder_name in folder_name_list:
  97. new_row = {"文件夹名称": str(folder_name),
  98. }
  99. need_df = need_df._append(new_row, ignore_index=True)
  100. need_df = need_df.fillna(value='')
  101. # 打开表格并进行匹配
  102. _df = pd.read_excel(excel_path, sheet_name=0, header=0)
  103. # 去重数据
  104. duplicates = _df.duplicated(subset=['文件夹名称'], keep="first")
  105. _df = _df.loc[~duplicates]
  106. _df = _df.fillna(value='')
  107. _df = _df.astype(str)
  108. # 数据匹配关联,左关联
  109. need_df = pd.merge(need_df, _df, on=["文件夹名称"], how="left", indicator=False, )
  110. # 补全字段
  111. header_list = need_df.columns.values.tolist()
  112. for key in keys:
  113. if key not in header_list:
  114. need_df[key] = ""
  115. need_df = need_df.fillna(value='')
  116. need_df = need_df.astype(str)
  117. # 数据转字典
  118. return_dict = {}
  119. message = ""
  120. for index, row in need_df.iterrows():
  121. if settings.PROJECT == "红蜻蜓":
  122. if row["商品货号"] and row["款号"] and row["编号"]:
  123. return_dict[row["文件夹名称"]] = {
  124. "type": "goods_art_no",
  125. "name": row["文件夹名称"].upper(),
  126. "文件夹名称": row["文件夹名称"],
  127. "template_name": row["模板名称"],
  128. "data": row.to_dict(),
  129. }
  130. else:
  131. message = "商品货号、款号、编号必须有值"
  132. else:
  133. if row["商品货号"] and row["款号"]:
  134. return_dict[row["文件夹名称"]] = {
  135. "type": "goods_art_no",
  136. "name": row["文件夹名称"].upper(),
  137. "文件夹名称": row["文件夹名称"],
  138. "template_name": row["模板名称"],
  139. "data": row.to_dict(),
  140. }
  141. print("return_dict", return_dict)
  142. if not return_dict:
  143. message += "\n没有找到任何匹配的数据"
  144. return {"code": 99, "message": message, "data": return_dict}
  145. else:
  146. return {"code": 0, "message": message, "data": return_dict}
  147. def check_goods_is_not_deficiency(self, goods_no_dict: dict):
  148. # 数据返回结果为款号列表
  149. error_data = {}
  150. for key, value in goods_no_dict.items():
  151. number = value["货号资料"][0]["编号"].replace("NUM", "")
  152. number_list = [x["编号"].replace("NUM", "") for x in value["货号资料"]]
  153. all_color_name = [self.get_real_color_name(x["颜色名称"]) for x in value["货号资料"]] # 本地数据
  154. goods_no = key
  155. _t_goods_number, all_goods_number = self.get_online_data.get_on_goods_all_art(number=number)
  156. # all_goods_number------》 [{'number': '14250232', 'goods_art_no': 'AC52001173', 'color': '杏色'}]
  157. for i in all_goods_number:
  158. if i["number"] not in number_list:
  159. # 检查款号+颜色名称是否已经存在
  160. real_color = self.get_real_color_name(i["color"])
  161. if real_color not in all_color_name:
  162. if goods_no not in error_data:
  163. error_data[goods_no] = {"message": "颜色:"}
  164. error_data[goods_no]["message"] += "{}缺失 ".format(real_color)
  165. return error_data
  166. def get_basic_template_information(self, _goods_no_dict, excel_path: str):
  167. # 本地的文件夹数据形成一个虚拟表格
  168. original_df = pd.DataFrame(columns=["款号"])
  169. for goods_no in _goods_no_dict:
  170. new_row = {"款号": str(goods_no),
  171. "flag": "是"
  172. }
  173. original_df = original_df._append(new_row, ignore_index=True)
  174. original_df = original_df.fillna(value='')
  175. # EXCEL表格数据
  176. local_df = pd.read_excel(excel_path, sheet_name=0, header=0)
  177. values = {'模板名称': "任意", }
  178. # 确保所有模板都有名称
  179. local_df.fillna(value=values, inplace=True)
  180. # 分组后取第一个有效值(即不是NaN的值);此处用于获取某个款号的所有基础信息
  181. group_local_df = local_df.groupby(['模板名称', '款号']).agg(
  182. lambda x: x.dropna().iloc[0] if not x.dropna().empty else np.nan)
  183. group_local_df = group_local_df.reset_index()
  184. # -----------数据匹配关联,左关联
  185. group_local_df = pd.merge(group_local_df, original_df, on=["款号"], how="left", indicator=False, )
  186. # -----------只取有标记的数据
  187. group_local_df = group_local_df.loc[~group_local_df['flag'].isnull(), :]
  188. group_local_df = group_local_df.loc[group_local_df['模板名称'] != "任意", :]
  189. # -----------数据规整
  190. group_local_df = group_local_df.fillna(value='')
  191. group_local_df = group_local_df.astype(str)
  192. # 组装成字典
  193. temp_goods_no_dict = {}
  194. for index, row in group_local_df.iterrows():
  195. goods_no = row["款号"]
  196. if goods_no not in temp_goods_no_dict:
  197. temp_goods_no_dict[goods_no] = {}
  198. temp_goods_no_dict[goods_no][row["模板名称"]] = row.to_dict()
  199. return temp_goods_no_dict
  200. def check_goods_is_not_deficiency_form_excel(self, goods_no_dict: dict, excel_path: str):
  201. # 检查颜色是否齐全,基于Excel处理
  202. """
  203. 步骤:
  204. 1、goods_no_dict款号生成一个表格(款号+颜色)
  205. 2、excel表格数据进行款号+颜色去重
  206. 3、excel表格关联 上述的款号 进行标记,其他删除
  207. 4、excel表格关联 上述款号与颜色,进行标记
  208. 5、上述未标记的就是没有的颜色(有对应款号)。
  209. 6、对对应的款号进行设置为错误数据
  210. 返回数据结构
  211. {
  212. “A00001--款号”:{“message”:“这个款的错误原因”},
  213. “A00002--款号”:{“message”:“这个款的错误原因”},
  214. }
  215. """
  216. def change_to_int(x):
  217. if pd.isna(x):
  218. return 0
  219. else:
  220. try:
  221. x = int(x)
  222. return str(x)
  223. except:
  224. return x
  225. error_data = {}
  226. # -----------------goods_no_dict款号生成一个表格(款号+颜色)
  227. new_df = pd.DataFrame(columns=['款号', '颜色名称', '款色标记'])
  228. for key, value in goods_no_dict.items():
  229. goods_no = value["款号"]
  230. for color_name in [x["颜色名称"] for x in value["货号资料"]]:
  231. new_row = {"款号": goods_no,
  232. "颜色名称": self.get_real_color_name(color_name),
  233. "款色标记": 1,
  234. }
  235. new_df = new_df._append(new_row, ignore_index=True)
  236. new_df.drop_duplicates(subset=['款号', "颜色名称"], keep='first', inplace=True)
  237. # -------------参考的本地excel表格数据进行款号+颜色去重------------
  238. local_df = pd.read_excel(excel_path, sheet_name=0, header=0)
  239. local_df.fillna(value={'颜色名称': "", }, inplace=True)
  240. local_df = local_df.astype({"颜色名称": str})
  241. header_list = local_df.columns.values.tolist()
  242. for key in ["帮高", "鞋宽", "跟高"]:
  243. if key in header_list:
  244. local_df[key] = local_df[key].apply(change_to_int)
  245. # 颜色名称规整
  246. local_df["颜色名称"] = local_df["颜色名称"].apply(self.get_real_color_name)
  247. local_df.drop_duplicates(subset=['款号', "颜色名称"], keep='first', inplace=True)
  248. # ------------excel表格关联 上述的款号 进行标记,其他删除
  249. _df = new_df.drop_duplicates(subset=['款号'], keep='first', inplace=False)
  250. _df = _df[["款号"]]
  251. _df["对应款号"] = 1
  252. local_df = pd.merge(local_df, _df, on=["款号"], how="left", indicator=False, )
  253. local_df = local_df.loc[local_df['对应款号'] == 1, :]
  254. # ------------excel表格关联 上述款号与颜色,进行标记;取没有关联的颜色数据---------
  255. local_df = pd.merge(local_df, new_df, on=['款号', "颜色名称"], how="left", indicator=False, )
  256. local_df.fillna(value={'款色标记': 0, }, inplace=True)
  257. local_df = local_df.loc[local_df['款色标记'] == 0, :]
  258. print("local_df")
  259. print(local_df)
  260. # ------------数据分组,对对应的款号进行设置为错误数据---------------
  261. grouped_df = local_df.groupby('款号')['颜色名称'].apply(lambda x: '、'.join(x)).reset_index()
  262. for index, row in grouped_df.iterrows():
  263. error_data[row["款号"]] = {"message": "颜色:{}缺失".format(row["颜色名称"])}
  264. print("======error_data")
  265. print(json.dumps(error_data))
  266. return error_data
  267. class DataModeUploadPic(DataBaseModel):
  268. def __init__(self, token):
  269. super().__init__(token)
  270. self.token = token
  271. self.get_online_data.refresh_headers(token)
  272. self.is_deal_goods_no = []
  273. def get_goods_art_no_info(self, numbers_list=None, goods_art_list=None):
  274. return self.get_online_data.get_goods_art_no_info(numbers_list=numbers_list, goods_art_list=goods_art_list,token=self.token)
  275. def upload_pic_list_data(self, data):
  276. return self.get_online_data.upload_pic_list_data(data, token=self.token)
  277. def upload_pic(self,goods_data):
  278. return self.get_online_data.upload_pic(goods_data, token=self.token)
  279. def check_is_uploaded(self,goods_art_no=None):
  280. return self.get_online_data.check_detail_image(goods_art_no, token=self.token)