mazda_upload.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import pandas as pd
  2. import numpy as np
  3. import json
  4. from requests_oauthlib import OAuth2Session
  5. from dataclasses import dataclass
  6. from datetime import datetime
  7. from dateutil.relativedelta import relativedelta
  8. @dataclass
  9. class MazdaConfig:
  10. domain: str
  11. webservice: str
  12. module: str
  13. auth_url: str
  14. token_url: str
  15. client_id: str
  16. client_secret: str
  17. username: str
  18. password: str
  19. dealer_number: str
  20. cfg = MazdaConfig(
  21. domain="https://mappsacc.mazdaeur.com",
  22. webservice="/dogma-restapi-dms/api",
  23. module="/vehicles/workshop/order-report",
  24. auth_url="/oauth/authorize",
  25. token_url="/oauth/token",
  26. client_id="E7FC943B-B73F-F48E-B71A-419EA4CD4AC7",
  27. client_secret="^bH=rk@c58zrr^Apc#9fzy$c",
  28. username="mmd88888.cdk",
  29. password="MazdaCX30",
  30. dealer_number="15972/MMD",
  31. )
  32. redirect_uri = "https://localhost:8085/"
  33. base_dir = "C:/projekte/mazda/"
  34. def date_format(d: datetime):
  35. if d == 0:
  36. return "" # '0000-00-00T00:00:00.000Z'
  37. date_str = d.isoformat(sep="T")
  38. if len(date_str) == 19:
  39. return date_str + ".000Z"
  40. return date_str[:-3] + "Z"
  41. def convert_csv(import_csv, export_json, year, month):
  42. date_min = datetime(year, month, 5, 0, 0, 0)
  43. date_max = datetime(year, month, 5, 0, 0, 0) + relativedelta(days=5)
  44. date_cols = ["invoiceDate", "orderDate", "orderCompletionDate", "vehicleIntakeDate", "nextMotDueDate"]
  45. df = pd.read_csv(import_csv, encoding="latin-1", decimal=",", sep=";", parse_dates=date_cols)
  46. df = df.fillna(0)[(df["invoiceDate"] >= date_min) & (df["invoiceDate"] <= date_max)]
  47. df = df.sort_values(by=["invoiceDate", "invoiceNumber", "orderNumber", "lineNumber"])
  48. df["vin"] = np.where(df["vin"] == 0, "0" * 17, df["vin"])
  49. # print(df[['currency','documentType','invoiceCategory','invoiceDate','invoiceNumber']].drop_duplicates().info())
  50. invoices_filter = ["currency", "documentType", "invoiceCategory", "invoiceDate", "invoiceNumber"]
  51. invoices = df[invoices_filter].drop_duplicates().to_dict("records")
  52. invoice_items_filter = [
  53. "invoiceNumber",
  54. "orderLineNumber",
  55. "orderNumber",
  56. "amount",
  57. "discount",
  58. "portion",
  59. "unitPrice",
  60. ]
  61. invoice_items = df[invoice_items_filter].groupby("invoiceNumber")
  62. for invoice in invoices:
  63. invoice["invoiceDate"] = date_format(invoice["invoiceDate"])
  64. items = invoice_items.get_group(invoice["invoiceNumber"])
  65. items.pop("invoiceNumber")
  66. invoice["invoiceItems"] = items.to_dict("records")
  67. orders = (
  68. df[["orderNumber", "orderDate", "orderCompletionDate", "vehicleIntakeDate"]]
  69. .drop_duplicates()
  70. .to_dict("records")
  71. )
  72. orders_vehicle_filter = ["orderNumber", "licensePlate", "nextMotDueDate", "odometer", "odometerUnit", "vin"]
  73. orders_vehicle = df[orders_vehicle_filter].drop_duplicates().groupby("orderNumber")
  74. orders_items = (
  75. df[
  76. [
  77. "orderNumber",
  78. "lineNumber",
  79. "orderItemType",
  80. "category",
  81. "descriptionOperation",
  82. "hours",
  83. "operationCode",
  84. "standardHours",
  85. "descriptionOther",
  86. "type",
  87. "descriptionPart",
  88. "isDamageCausal",
  89. "manufacturer",
  90. "partNumber",
  91. "quantity",
  92. "serialNumber",
  93. "unit",
  94. "company",
  95. "descriptionPurchase",
  96. "invoiceCode",
  97. "invoiceDate",
  98. "invoiceNumber",
  99. ]
  100. ]
  101. .drop_duplicates()
  102. .groupby("orderNumber")
  103. )
  104. for order in orders:
  105. order["vehicle"] = orders_vehicle.get_group(order["orderNumber"]).to_dict("records")[0]
  106. order["vehicle"]["nextMotDueDate"] = date_format(order["vehicle"]["nextMotDueDate"])
  107. # odo_str = str(order["vehicle"]["odometer"])
  108. order["vehicle"]["odometer"] = int(order["vehicle"]["odometer"])
  109. order["orderDate"] = date_format(order["orderDate"])
  110. order["orderCompletionDate"] = date_format(order["orderCompletionDate"])
  111. order["vehicleIntakeDate"] = date_format(order["vehicleIntakeDate"])
  112. items = orders_items.get_group(order["orderNumber"]).to_dict("records")
  113. order["items"] = []
  114. for item in items:
  115. if item["orderItemType"] == "operation":
  116. order["items"].append(
  117. {
  118. "lineNumber": item["lineNumber"],
  119. "operation": {
  120. "category": item["category"],
  121. "description": item["descriptionOperation"],
  122. "hours": item["hours"],
  123. "operationCode": item["operationCode"],
  124. "standardHours": item["standardHours"],
  125. },
  126. }
  127. )
  128. elif item["orderItemType"] == "part":
  129. order["items"].append(
  130. {
  131. "lineNumber": item["lineNumber"],
  132. "part": {
  133. "description": item["descriptionPart"],
  134. "isDamageCausal": item["isDamageCausal"],
  135. "manufacturer": item["manufacturer"],
  136. "partNumber": item["partNumber"],
  137. "quantity": item["quantity"],
  138. "serialNumber": str(item["serialNumber"]),
  139. "unit": str(item["unit"]),
  140. },
  141. }
  142. )
  143. elif item["orderItemType"] == "other":
  144. order["items"].append(
  145. {
  146. "lineNumber": item["lineNumber"],
  147. "other": {"description": item["descriptionOther"], "type": item["type"]},
  148. }
  149. )
  150. else:
  151. order["items"].append(
  152. {
  153. "lineNumber": item["lineNumber"],
  154. "purchaseInvoice": {
  155. "company": item["company"],
  156. "description": item["descriptionPurchase"],
  157. "invoiceCode": item["invoiceCode"],
  158. "invoiceDate": date_format(item["invoiceDate"]),
  159. "invoiceNumber": item["invoiceNumber"],
  160. },
  161. }
  162. )
  163. res = {
  164. "creationDate": date_format(datetime.now()),
  165. "invoices": invoices,
  166. "orders": orders,
  167. "timeRangeBegin": date_format(date_min),
  168. "timeRangeEnd": date_format(date_max),
  169. }
  170. json.dump(res, open(export_json, "w"), indent=2)
  171. return res
  172. def upload(oauth: OAuth2Session, data):
  173. headers = {
  174. "accept": "application/vnd.mazdaeur.dms.v5+json",
  175. "x-mme-organisation": cfg.dealer_number,
  176. "X-mazda-org": cfg.dealer_number,
  177. "Content-Type": "application/json",
  178. # 'Authorization': 'Bearer ' + token
  179. }
  180. invoices = data["invoices"]
  181. orders = data["orders"]
  182. data["orders"] = []
  183. for i in invoices:
  184. data["invoices"] = [i]
  185. order_no = [item["orderNumber"] for item in i["invoiceItems"]]
  186. data["orders"] = [o for o in orders if o["orderNumber"] in order_no]
  187. r = oauth.post(cfg.domain + cfg.webservice + cfg.module, json.dumps(data), headers=headers)
  188. print(f"{i['invoiceNumber']} => {r.status_code}")
  189. if r.status_code not in [200, 202]:
  190. with open(base_dir + f"logs/invoice_{i['invoiceNumber']}.log", "wb") as fwh:
  191. fwh.write(r.content)
  192. def main():
  193. data = convert_csv(base_dir + "data/Workshop_Order_Report.csv", base_dir + "temp/mazda_export.json", 2021, 6)
  194. # data = json.load(open(base_dir + 'mazda_export.json', 'r'))
  195. upload(None, data)
  196. if __name__ == "__main__":
  197. main()