mazda_upload.py 7.8 KB

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