data.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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["款号"]:
  123. return_dict[row["商品货号"]] = {
  124. "type": "goods_art_no",
  125. "name": row["商品货号"].upper(),
  126. "template_name": row["模板名称"],
  127. "data": row.to_dict(),
  128. }
  129. else:
  130. message = "商品货号、款号、编号必须有值"
  131. else:
  132. if row["商品货号"] and row["款号"]:
  133. return_dict[row["商品货号"]] = {
  134. "type": "goods_art_no",
  135. "name": row["商品货号"].upper(),
  136. "文件夹名称": row["商品货号"],
  137. "template_name": row["模板名称"],
  138. "data": row.to_dict(),
  139. }
  140. print("return_dict", return_dict)
  141. if not return_dict:
  142. message += "\n没有找到任何匹配的数据"
  143. return {"code": 99, "message": message, "data": return_dict}
  144. else:
  145. return {"code": 0, "message": message, "data": return_dict}
  146. def check_goods_is_not_deficiency(self, goods_no_dict: dict):
  147. # 数据返回结果为款号列表
  148. error_data = {}
  149. for key, value in goods_no_dict.items():
  150. number = value["货号资料"][0]["编号"].replace("NUM", "")
  151. number_list = [x["编号"].replace("NUM", "") for x in value["货号资料"]]
  152. all_color_name = [self.get_real_color_name(x["颜色名称"]) for x in value["货号资料"]] # 本地数据
  153. goods_no = key
  154. _t_goods_number, all_goods_number = self.get_online_data.get_on_goods_all_art(number=number)
  155. # all_goods_number------》 [{'number': '14250232', 'goods_art_no': 'AC52001173', 'color': '杏色'}]
  156. for i in all_goods_number:
  157. if i["number"] not in number_list:
  158. # 检查款号+颜色名称是否已经存在
  159. real_color = self.get_real_color_name(i["color"])
  160. if real_color not in all_color_name:
  161. if goods_no not in error_data:
  162. error_data[goods_no] = {"message": "颜色:"}
  163. error_data[goods_no]["message"] += "{}缺失 ".format(real_color)
  164. return error_data
  165. def get_basic_template_information(self, _goods_no_dict, excel_path: str):
  166. # 本地的文件夹数据形成一个虚拟表格
  167. original_df = pd.DataFrame(columns=["款号"])
  168. for goods_no in _goods_no_dict:
  169. new_row = {"款号": str(goods_no),
  170. "flag": "是"
  171. }
  172. original_df = original_df._append(new_row, ignore_index=True)
  173. original_df = original_df.fillna(value='')
  174. # EXCEL表格数据
  175. local_df = pd.read_excel(excel_path, sheet_name=0, header=0)
  176. values = {'模板名称': "任意", }
  177. # 确保所有模板都有名称
  178. local_df.fillna(value=values, inplace=True)
  179. # 分组后取第一个有效值(即不是NaN的值);此处用于获取某个款号的所有基础信息
  180. group_local_df = local_df.groupby(['模板名称', '款号']).agg(
  181. lambda x: x.dropna().iloc[0] if not x.dropna().empty else np.nan)
  182. group_local_df = group_local_df.reset_index()
  183. # -----------统一款号列的数据类型为字符串,避免merge时报错
  184. group_local_df["款号"] = group_local_df["款号"].astype(str)
  185. original_df["款号"] = original_df["款号"].astype(str)
  186. # -----------数据匹配关联,左关联
  187. group_local_df = pd.merge(group_local_df, original_df, on=["款号"], how="left", indicator=False, )
  188. # -----------只取有标记的数据
  189. group_local_df = group_local_df.loc[~group_local_df['flag'].isnull(), :]
  190. group_local_df = group_local_df.loc[group_local_df['模板名称'] != "任意", :]
  191. # -----------数据规整
  192. group_local_df = group_local_df.fillna(value='')
  193. group_local_df = group_local_df.astype(str)
  194. # 组装成字典
  195. temp_goods_no_dict = {}
  196. for index, row in group_local_df.iterrows():
  197. goods_no = row["款号"]
  198. if goods_no not in temp_goods_no_dict:
  199. temp_goods_no_dict[goods_no] = {}
  200. temp_goods_no_dict[goods_no][row["模板名称"]] = row.to_dict()
  201. return temp_goods_no_dict
  202. def check_goods_is_not_deficiency_form_excel(self, goods_no_dict: dict, excel_path: str):
  203. # 检查颜色是否齐全,基于Excel处理
  204. """
  205. 步骤:
  206. 1、goods_no_dict款号生成一个表格(款号+颜色)
  207. 2、excel表格数据进行款号+颜色去重
  208. 3、excel表格关联 上述的款号 进行标记,其他删除
  209. 4、excel表格关联 上述款号与颜色,进行标记
  210. 5、上述未标记的就是没有的颜色(有对应款号)。
  211. 6、对对应的款号进行设置为错误数据
  212. 返回数据结构
  213. {
  214. “A00001--款号”:{“message”:“这个款的错误原因”},
  215. “A00002--款号”:{“message”:“这个款的错误原因”},
  216. }
  217. """
  218. def change_to_int(x):
  219. if pd.isna(x):
  220. return 0
  221. else:
  222. try:
  223. x = int(x)
  224. return str(x)
  225. except:
  226. return x
  227. error_data = {}
  228. # -----------------goods_no_dict款号生成一个表格(款号+颜色)
  229. new_df = pd.DataFrame(columns=['款号', '颜色名称', '款色标记'])
  230. for key, value in goods_no_dict.items():
  231. goods_no = value["款号"]
  232. for color_name in [x["颜色名称"] for x in value["货号资料"]]:
  233. new_row = {"款号": goods_no,
  234. "颜色名称": self.get_real_color_name(color_name),
  235. "款色标记": 1,
  236. }
  237. new_df = new_df._append(new_row, ignore_index=True)
  238. new_df.drop_duplicates(subset=['款号', "颜色名称"], keep='first', inplace=True)
  239. # -------------参考的本地excel表格数据进行款号+颜色去重------------
  240. local_df = pd.read_excel(excel_path, sheet_name=0, header=0)
  241. local_df.fillna(value={'颜色名称': "", }, inplace=True)
  242. local_df = local_df.astype({"颜色名称": str})
  243. header_list = local_df.columns.values.tolist()
  244. for key in ["帮高", "鞋宽", "跟高"]:
  245. if key in header_list:
  246. local_df[key] = local_df[key].apply(change_to_int)
  247. # 颜色名称规整
  248. local_df["颜色名称"] = local_df["颜色名称"].apply(self.get_real_color_name)
  249. local_df.drop_duplicates(subset=['款号', "颜色名称"], keep='first', inplace=True)
  250. # ------------统一款号列的数据类型为字符串,避免merge时报错
  251. local_df["款号"] = local_df["款号"].astype(str)
  252. new_df["款号"] = new_df["款号"].astype(str)
  253. # ------------excel表格关联 上述的款号 进行标记,其他删除
  254. _df = new_df.drop_duplicates(subset=['款号'], keep='first', inplace=False)
  255. _df = _df[["款号"]]
  256. _df["对应款号"] = 1
  257. local_df = pd.merge(local_df, _df, on=["款号"], how="left", indicator=False, )
  258. local_df = local_df.loc[local_df['对应款号'] == 1, :]
  259. # ------------excel表格关联 上述款号与颜色,进行标记;取没有关联的颜色数据---------
  260. local_df = pd.merge(local_df, new_df, on=['款号', "颜色名称"], how="left", indicator=False, )
  261. local_df.fillna(value={'款色标记': 0, }, inplace=True)
  262. local_df = local_df.loc[local_df['款色标记'] == 0, :]
  263. print("local_df")
  264. print(local_df)
  265. # ------------数据分组,对对应的款号进行设置为错误数据---------------
  266. grouped_df = local_df.groupby('款号')['颜色名称'].apply(lambda x: '、'.join(x)).reset_index()
  267. for index, row in grouped_df.iterrows():
  268. error_data[row["款号"]] = {"message": "颜色:{}缺失".format(row["颜色名称"])}
  269. print("======error_data")
  270. print(json.dumps(error_data))
  271. return error_data
  272. class DataModeUploadPic(DataBaseModel):
  273. def __init__(self, token):
  274. super().__init__(token)
  275. self.token = token
  276. self.get_online_data.refresh_headers(token)
  277. self.is_deal_goods_no = []
  278. def get_goods_art_no_info(self, numbers_list=None, goods_art_list=None):
  279. return self.get_online_data.get_goods_art_no_info(numbers_list=numbers_list, goods_art_list=goods_art_list,token=self.token)
  280. def upload_pic_list_data(self, data):
  281. return self.get_online_data.upload_pic_list_data(data, token=self.token)
  282. def upload_pic(self,goods_data):
  283. return self.get_online_data.upload_pic(goods_data, token=self.token)
  284. def check_is_uploaded(self,goods_art_no=None):
  285. return self.get_online_data.check_detail_image(goods_art_no, token=self.token)