Coverage for mindsdb / integrations / handlers / google_content_shopping_handler / google_content_shopping_tables.py: 0%

197 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-21 00:36 +0000

1import pandas as pd 

2from mindsdb_sql_parser import ast 

3from pandas import DataFrame 

4 

5from mindsdb.integrations.libs.api_handler import APITable 

6from mindsdb.integrations.utilities.date_utils import parse_utc_date 

7from mindsdb.integrations.utilities.sql_utils import extract_comparison_conditions 

8 

9 

10class AccountsTable(APITable): 

11 """ 

12 Table class for the Google Content API for Shopping Accounts table. 

13 """ 

14 

15 def select(self, query: ast.Select) -> DataFrame: 

16 """ 

17 Lists the sub-accounts in your Merchant Center account. 

18 

19 Args: 

20 query (ast.Select): SQL query to parse. 

21 

22 Returns: 

23 Response: Response object containing the results. 

24 """ 

25 

26 # Parse the query to get the conditions. 

27 conditions = extract_comparison_conditions(query.where) 

28 # Get the start and end times from the conditions. 

29 params = {} 

30 accepted_params = ['view', 'label', 'name'] 

31 for op, arg1, arg2 in conditions: 

32 if arg1 == 'accountId': 

33 if op == '=': 

34 params[arg1] = arg2 

35 elif op == '>': 

36 params['startId'] = arg2 

37 elif op == '<': 

38 params['endId'] = arg2 

39 else: 

40 raise NotImplementedError 

41 if arg1 in accepted_params: 

42 if op != '=': 

43 raise NotImplementedError 

44 params[arg1] = arg2 

45 else: 

46 raise NotImplementedError 

47 

48 if query.limit is not None: 

49 params['maxResults'] = query.limit.value 

50 

51 # Get the accounts from the API. 

52 accounts = self.handler. \ 

53 call_application_api(method_name='get_accounts', params=params) 

54 

55 selected_columns = [] 

56 for target in query.targets: 

57 if isinstance(target, ast.Star): 

58 selected_columns = self.get_columns() 

59 break 

60 elif isinstance(target, ast.Identifier): 

61 selected_columns.append(target.parts[-1]) 

62 else: 

63 raise ValueError(f"Unknown query target {type(target)}") 

64 

65 if len(accounts) == 0: 

66 accounts = pd.DataFrame([], columns=selected_columns) 

67 else: 

68 accounts.columns = self.get_columns() 

69 for col in set(accounts.columns).difference(set(selected_columns)): 

70 accounts = accounts.drop(col, axis=1) 

71 return accounts 

72 

73 def delete(self, query: ast.Delete): 

74 """ 

75 Deletes accounts from your Merchant Center account. 

76 

77 Args: 

78 query (ast.Delete): SQL query to parse. 

79 

80 Returns: 

81 Response: Response object containing the results. 

82 """ 

83 

84 # Parse the query to get the conditions. 

85 conditions = extract_comparison_conditions(query.where) 

86 # Get the start and end times from the conditions. 

87 params = {} 

88 for op, arg1, arg2 in conditions: 

89 if arg1 == 'accountId': 

90 if op == '=': 

91 params[arg1] = arg2 

92 elif op == '>': 

93 params['startId'] = arg2 

94 elif op == '<': 

95 params['endId'] = arg2 

96 elif arg1 == 'force': 

97 if op != '=': 

98 raise NotImplementedError 

99 params[arg1] = arg2 

100 else: 

101 raise NotImplementedError 

102 

103 # Delete the events in the Google Calendar API. 

104 self.handler.call_application_api(method_name='delete_accounts', params=params) 

105 

106 def get_columns(self) -> list: 

107 """Gets all columns to be returned in pandas DataFrame responses""" 

108 return [ 

109 'name', 

110 'kind', 

111 'websiteUrl', 

112 'adultContent', 

113 'sellerId', 

114 'users', 

115 'id', 

116 'youtubeChannelLinks', 

117 'googleMyBusinessLink', 

118 'businessInformation', 

119 'automaticImprovements', 

120 'adsLinks', 

121 'cssId', 

122 'labelIds', 

123 'accountManagement', 

124 'automaticLabelIds', 

125 'conversionSettings' 

126 ] 

127 

128 

129class OrdersTable(APITable): 

130 """ 

131 Table class for the Google Content API for Shopping Orders table. 

132 """ 

133 

134 def select(self, query: ast.Select) -> DataFrame: 

135 """ 

136 Lists the orders in your Merchant Center account. 

137 

138 Args: 

139 query (ast.Select): SQL query to parse. 

140 

141 Returns: 

142 Response: Response object containing the results. 

143 """ 

144 

145 # Parse the query to get the conditions. 

146 conditions = extract_comparison_conditions(query.where) 

147 # Get the start and end times from the conditions. 

148 params = {} 

149 accepted_params = ['statuses', 'acknowledged'] 

150 for op, arg1, arg2 in conditions: 

151 if arg1 == 'orderId': 

152 if op == '=': 

153 params[arg1] = arg2 

154 elif op == '>': 

155 params['startId'] = arg2 

156 elif op == '<': 

157 params['endId'] = arg2 

158 else: 

159 raise NotImplementedError 

160 if arg1 == 'placedDateStart' or arg1 == 'placedDateEnd': 

161 if op != '=': 

162 raise NotImplementedError 

163 params[arg1] = parse_utc_date(arg2) 

164 if arg1 in accepted_params: 

165 params[arg1] = parse_utc_date(arg2) 

166 if op != '=': 

167 raise NotImplementedError 

168 params[arg1] = arg2 

169 else: 

170 raise NotImplementedError 

171 

172 if query.order_by is not None: 

173 if query.order_by[0].value == 'placedDate': 

174 if query.order_by[1].value == 'ASC': 

175 params['orderBy'] = 'placedDateAsc' 

176 else: 

177 params['orderBy'] = 'placedDateDesc' 

178 raise NotImplementedError 

179 else: 

180 raise NotImplementedError 

181 

182 if query.limit is not None: 

183 params['maxResults'] = query.limit.value 

184 

185 # Get the orders from the API. 

186 orders = self.handler. \ 

187 call_application_api(method_name='get_orders', params=params) 

188 

189 selected_columns = [] 

190 for target in query.targets: 

191 if isinstance(target, ast.Star): 

192 selected_columns = self.get_columns() 

193 break 

194 elif isinstance(target, ast.Identifier): 

195 selected_columns.append(target.parts[-1]) 

196 else: 

197 raise ValueError(f"Unknown query target {type(target)}") 

198 

199 if len(orders) == 0: 

200 orders = pd.DataFrame([], columns=selected_columns) 

201 else: 

202 orders.columns = self.get_columns() 

203 for col in set(orders.columns).difference(set(selected_columns)): 

204 orders = orders.drop(col, axis=1) 

205 return orders 

206 

207 def delete(self, query: ast.Delete): 

208 """ 

209 Deletes orders in your Merchant Center account. 

210 

211 Args: 

212 query (ast.Delete): SQL query to parse. 

213 

214 Returns: 

215 Response: Response object containing the results. 

216 """ 

217 

218 # Parse the query to get the conditions. 

219 conditions = extract_comparison_conditions(query.where) 

220 # Get the start and end times from the conditions. 

221 params = {} 

222 for op, arg1, arg2 in conditions: 

223 if arg1 == 'orderId': 

224 if op == '=': 

225 params[arg1] = arg2 

226 elif op == '>': 

227 params['startId'] = arg2 

228 elif op == '<': 

229 params['endId'] = arg2 

230 else: 

231 raise NotImplementedError 

232 else: 

233 raise NotImplementedError 

234 

235 # Delete the events in the Google Calendar API. 

236 self.handler.call_application_api(method_name='delete_orders', params=params) 

237 

238 def get_columns(self) -> list: 

239 """Gets all columns to be returned in pandas DataFrame responses""" 

240 return [ 

241 'id', 

242 'merchantId', 

243 'merchantOrderId', 

244 'kind', 

245 'lineItems', 

246 'status', 

247 'paymentStatus', 

248 'acknowledged', 

249 'placedDate', 

250 'deliveryDetails', 

251 'customer', 

252 'shippingCost', 

253 'shippingCostTax', 

254 'refunds', 

255 'shipments', 

256 'billingAddress', 

257 'promotions', 

258 'taxCollector', 

259 'netPriceAmount', 

260 'netTaxAmount', 

261 'pickupDetails', 

262 'annotations' 

263 ] 

264 

265 

266class ProductsTable(APITable): 

267 """ 

268 Table class for the Google Content API for Shopping Products table. 

269 """ 

270 

271 def select(self, query: ast.Select) -> DataFrame: 

272 """ 

273 Lists the products in your Merchant Center account. 

274 

275 Args: 

276 query (ast.Select): SQL query to parse. 

277 

278 Returns: 

279 Response: Response object containing the results. 

280 """ 

281 

282 # Parse the query to get the conditions. 

283 conditions = extract_comparison_conditions(query.where) 

284 params = {} 

285 for op, arg1, arg2 in conditions: 

286 if arg1 == 'productId': 

287 if op == '=': 

288 params[arg1] = arg2 

289 elif op == '>': 

290 params['startId'] = arg2 

291 elif op == '<': 

292 params['endId'] = arg2 

293 else: 

294 raise NotImplementedError 

295 else: 

296 raise NotImplementedError 

297 

298 if query.limit is not None: 

299 params['maxResults'] = query.limit.value 

300 

301 # Get the products from the API. 

302 products = self.handler. \ 

303 call_application_api(method_name='get_products', params=params) 

304 

305 selected_columns = [] 

306 for target in query.targets: 

307 if isinstance(target, ast.Star): 

308 selected_columns = self.get_columns() 

309 break 

310 elif isinstance(target, ast.Identifier): 

311 selected_columns.append(target.parts[-1]) 

312 else: 

313 raise ValueError(f"Unknown query target {type(target)}") 

314 

315 if len(products) == 0: 

316 products = pd.DataFrame([], columns=selected_columns) 

317 else: 

318 products.columns = self.get_columns() 

319 for col in set(products.columns).difference(set(selected_columns)): 

320 products = products.drop(col, axis=1) 

321 return products 

322 

323 def update(self, query: ast.Update): 

324 """ 

325 Updates products in your Merchant Center account. 

326 

327 Args: 

328 query (ast.Update): SQL query to parse. 

329 

330 Returns: 

331 Response: Response object containing the results. 

332 """ 

333 

334 params = {} 

335 values = query.values[0] 

336 # Get the event data from the values. 

337 accepted_params = self.get_columns() 

338 for col, val in zip(query.update_columns, values): 

339 if col in accepted_params: 

340 params[col] = val 

341 else: 

342 raise NotImplementedError 

343 

344 params['updateMask'] = ','.join(params.keys()) 

345 # Parse the query to get the conditions. 

346 conditions = extract_comparison_conditions(query.where) 

347 # Get the start and end times from the conditions. 

348 

349 for op, arg1, arg2 in conditions: 

350 if arg1 == 'productId': 

351 if op == '=': 

352 params[arg1] = arg2 

353 elif op == '>': 

354 params['startId'] = arg2 

355 elif op == '<': 

356 params['endId'] = arg2 

357 else: 

358 raise NotImplementedError 

359 else: 

360 raise NotImplementedError 

361 

362 # Update the products in the Google Merchant Center API. 

363 self.handler.call_application_api(method_name='update_products', params=params) 

364 

365 def delete(self, query: ast.Delete): 

366 """ 

367 Deletes products in your Merchant Center account. 

368 

369 Args: 

370 query (ast.Delete): SQL query to parse. 

371 

372 Returns: 

373 Response: Response object containing the results. 

374 """ 

375 

376 # Parse the query to get the conditions. 

377 conditions = extract_comparison_conditions(query.where) 

378 # Get the start and end times from the conditions. 

379 params = {} 

380 for op, arg1, arg2 in conditions: 

381 if arg1 == 'productId': 

382 if op == '=': 

383 params[arg1] = arg2 

384 elif op == '>': 

385 params['startId'] = arg2 

386 elif op == '<': 

387 params['endId'] = arg2 

388 else: 

389 raise NotImplementedError 

390 elif arg1 == 'feedId': 

391 if op != '=': 

392 raise NotImplementedError 

393 params[arg1] = arg2 

394 else: 

395 raise NotImplementedError 

396 

397 # Delete the products in the Google Merchant Center API. 

398 self.handler.call_application_api(method_name='delete_products', params=params) 

399 

400 def get_columns(self) -> list: 

401 """Gets all columns to be returned in pandas DataFrame responses""" 

402 return [ 

403 'id', 

404 'offerId', 

405 'title', 

406 'description', 

407 'link', 

408 'imageLink', 

409 'contentLanguage', 

410 'targetCountry', 

411 'channel', 

412 'channelExclusivity', 

413 'price', 

414 'salePrice', 

415 'salePriceEffectiveDate', 

416 'gtin', 

417 'mpn', 

418 'brand', 

419 'condition', 

420 'adult', 

421 'multipack', 

422 'isBundle', 

423 'energyEfficiencyClass', 

424 'minEnergyEfficiencyClass', 

425 'maxEnergyEfficiencyClass', 

426 'ageGroup', 

427 'color', 

428 'expirationDate', 

429 'disclosureDate', 

430 'availability', 

431 'source' 

432 ]