@miraiva_test/miravia-order-report 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +61 -0
- package/dist/.keypair.json +5 -0
- package/dist/README.md +249 -0
- package/dist/SKILL.md +329 -0
- package/dist/VERSION +1 -0
- package/dist/executive_summary_prompt_v2.md +574 -0
- package/dist/reference.md +409 -0
- package/dist/requirements.txt +6 -0
- package/dist/scripts/auth_cli.py +1442 -0
- package/dist/scripts/config.py +216 -0
- package/dist/scripts/cred_crypto.py +235 -0
- package/dist/scripts/estimate_time.py +244 -0
- package/dist/scripts/export_orders.py +1549 -0
- package/dist/scripts/i18n.py +1162 -0
- package/dist/scripts/inject_insights.py +96 -0
- package/dist/scripts/login.bat +14 -0
- package/dist/scripts/miravia_client.py +468 -0
- package/dist/scripts/report_v4.py +1694 -0
- package/dist/scripts/run.bat +15 -0
- package/dist/scripts/skill_crypto.py +86 -0
- package/dist/scripts/skill_keypair.py +86 -0
- package/dist/scripts/skill_logger.py +262 -0
- package/dist/scripts/test_v4_render.py +322 -0
- package/dist/scripts/trace_logger.py +97 -0
- package/dist/scripts/validate_render.py +101 -0
- package/dist/static/chart.umd.min.js +20 -0
- package/dist/static/chartjs-plugin-datalabels.min.js +7 -0
- package/dist/static/miravia-logo.svg +61 -0
- package/dist/templates/report_v4.html +1005 -0
- package/lib/build-dist.js +86 -0
- package/lib/clean-dist.js +18 -0
- package/lib/installer.js +444 -0
- package/package.json +34 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# Reference · API Fields & Excel Column Mapping
|
|
2
|
+
|
|
3
|
+
This Skill strictly follows PRD §Order Detail Export clauses. Each row = one **Miravia sub-order** (`order_item_id`).
|
|
4
|
+
|
|
5
|
+
## Data Sources
|
|
6
|
+
|
|
7
|
+
| API | Purpose | Client Method |
|
|
8
|
+
|-----|---------|---------------|
|
|
9
|
+
| `GET /orders/get` | Main order basic info (paginated) | `MiraviaClient.iter_orders()` |
|
|
10
|
+
| `GET /orders/items/get` | Sub-order product / amount / logistics / cancellation info | `MiraviaClient.get_multi_order_items()` |
|
|
11
|
+
| `GET /reverse/getreverseordersforseller` | Refund / reverse orders (joined by `order_item_id`) | `MiraviaClient.get_reverse_orders()` |
|
|
12
|
+
|
|
13
|
+
### Main Order API `/orders/get` Parameters (strictly per official docs)
|
|
14
|
+
|
|
15
|
+
| Parameter | Type | Required | Description |
|
|
16
|
+
|-----------|------|----------|-------------|
|
|
17
|
+
| `created_after` / `created_before` | String | One pair required (with `update_after/before`) | ISO 8601, e.g. `2026-05-19T00:00:00+08:00` |
|
|
18
|
+
| `update_after` / `update_before` | String | Same as above | For incremental sync scenarios |
|
|
19
|
+
| `status` | String | No | Single value: `unpaid / pending / repacked / packed / ready_to_ship / shipped / delivered / returned / canceled / failed / lost` |
|
|
20
|
+
| `limit` | Number | No | Page size, max 100, default 100 |
|
|
21
|
+
| `offset` | Number | No | Default 0; **`offset + limit ≤ 5000`** (server hard limit) |
|
|
22
|
+
| `sort_by` / `sort_direction` | String | No | `created_at` / `updated_at`; `ASC` / `DESC` |
|
|
23
|
+
| `marketplace` | String | No | Marketplace identifier |
|
|
24
|
+
| `country` | String | No | Country |
|
|
25
|
+
| `buyer_id` | String | No | Buyer ID |
|
|
26
|
+
| `channel` | String | No | ★ Channel: `AE` / `Miravia` |
|
|
27
|
+
| `ship_to` | String | No | ★ Ship-to country: `ES` / `PT` |
|
|
28
|
+
| `buyer_ids` | String | No | ★ Batch buyer IDs |
|
|
29
|
+
| `filter_unpaid` | Boolean | No | ★ Filter unpaid orders |
|
|
30
|
+
| `filter_hold` | Boolean | No | ★ Filter orders in hold status |
|
|
31
|
+
|
|
32
|
+
> ⚠️ **Known Pitfalls**:
|
|
33
|
+
> 1. The official docs spell the parameter as `limt` (missing an `i`) — this is a **documentation typo**. The gateway actually accepts `limit` (consistent with Lazada/AE). Code uses `limit` uniformly; do not be misled by the docs.
|
|
34
|
+
> 2. **`offset + limit ≤ 5000`** is a server hard limit; exceeding it returns an error. This Skill exits early in `MiraviaClient.iter_orders` when approaching the limit; if `countTotal > 5000`, callers must split time windows (e.g. by day/hour) and re-fetch.
|
|
35
|
+
> 3. Response fields `data.countTotal` / `data.count` are Strings; use `int(...)` for conversion.
|
|
36
|
+
|
|
37
|
+
### Forward Order `/orders/get` Full Response Fields
|
|
38
|
+
|
|
39
|
+
> Below is the complete response field reference from API docs. ★ = fields newly used in v4 dashboard.
|
|
40
|
+
|
|
41
|
+
#### Main Order Level (`data.orders[]`)
|
|
42
|
+
|
|
43
|
+
| Field | Type | Description |
|
|
44
|
+
|-------|------|-------------|
|
|
45
|
+
| `order_id` | String | Main order ID |
|
|
46
|
+
| `marketplace` | String | Marketplace identifier |
|
|
47
|
+
| `created_at` | String | Order creation time (ISO 8601) |
|
|
48
|
+
| `items_count` | Number | Number of items |
|
|
49
|
+
| `payment_method` | String | Payment method |
|
|
50
|
+
| `buyer_id` | String | Buyer ID |
|
|
51
|
+
| `customer_first_name` | String | Buyer first name |
|
|
52
|
+
| `customer_last_name` | String | Buyer last name |
|
|
53
|
+
| `address_shipping` | Object | Shipping address (OpenAddressDTO) |
|
|
54
|
+
| `warehouse_code` | String | Warehouse code |
|
|
55
|
+
| `voucher_platform` | String | Platform voucher amount |
|
|
56
|
+
| `order_type` | String | Order type |
|
|
57
|
+
| `channel` | String | ★ Channel (AE/Miravia) |
|
|
58
|
+
| `remarks` | String | Buyer remarks |
|
|
59
|
+
| `delivery_info` | String | Delivery info |
|
|
60
|
+
|
|
61
|
+
#### Sub-Order Level (`order_items[]` / `/orders/items/get`)
|
|
62
|
+
|
|
63
|
+
| Field | Type | Description |
|
|
64
|
+
|-------|------|-------------|
|
|
65
|
+
| `order_item_id` | String | Sub-order ID |
|
|
66
|
+
| `status` / `Status` | String | Sub-order status |
|
|
67
|
+
| `updated_at` | String | Update time |
|
|
68
|
+
| `product_id` | String | Product ID |
|
|
69
|
+
| `name` | String | Product name |
|
|
70
|
+
| `product_main_image` | String | Product main image URL |
|
|
71
|
+
| `sku` | String | Platform SKU |
|
|
72
|
+
| `shop_sku` | String | Seller SKU |
|
|
73
|
+
| `quantity` | Number | Quantity |
|
|
74
|
+
| `item_price` | String | Unit price |
|
|
75
|
+
| `paid_price` | String | Paid amount |
|
|
76
|
+
| `voucher_amount` | String | Total voucher amount |
|
|
77
|
+
| `voucher_platform` | String | Platform discount |
|
|
78
|
+
| `voucher_seller` | String | Seller discount |
|
|
79
|
+
| `voucherSellerLPI` | String | ★ Seller LPI voucher |
|
|
80
|
+
| `VoucherCode` | String | ★ Voucher code |
|
|
81
|
+
| `voucherCodeSeller` | String | ★ Seller voucher code |
|
|
82
|
+
| `shipping_amount` | String | Shipping amount |
|
|
83
|
+
| `shippingFeeOriginal` | String | ★ Original shipping fee |
|
|
84
|
+
| `shippingFeeDiscountSeller` | String | ★ Seller shipping discount |
|
|
85
|
+
| `currency` | String | Currency |
|
|
86
|
+
| `WalletCredits` | String | ★ Wallet credits deduction |
|
|
87
|
+
| `TaxAmount` | String | ★ Tax amount |
|
|
88
|
+
| `ShippingType` | String | ★ Shipping type |
|
|
89
|
+
| `ShippingProviderType` | String | Logistics provider type |
|
|
90
|
+
| `ShipmentProvider` | String | Logistics provider name |
|
|
91
|
+
| `TrackingCode` | String | Tracking number |
|
|
92
|
+
| `PackageId` | String | Package ID |
|
|
93
|
+
| `IsDigital` | String | ★ Digital product flag (`1`/`0`) |
|
|
94
|
+
| `isSOF` | String | ★ Seller-own-fulfillment flag (`1`/`0`) |
|
|
95
|
+
| `isFBL` | String | ★ Fulfilled-by-Lazada/Miravia flag (`1`/`0`) |
|
|
96
|
+
| `isReroute` | String | ★ Reroute flag (`1`/`0`) |
|
|
97
|
+
| `CancelReturnInitiator` | String | Cancel/return initiator |
|
|
98
|
+
| `Reason` | String | Cancellation reason |
|
|
99
|
+
| `ReasonDetail` | String | Cancellation reason detail |
|
|
100
|
+
| `refundAmount` | String | ★ Forward order refund amount |
|
|
101
|
+
| `orderFlag` | String | ★ Order flag |
|
|
102
|
+
| `channel` | String | ★ Sub-order channel (AE/Miravia) |
|
|
103
|
+
| `shipTo` | String | ★ Ship-to country (ES/PT) |
|
|
104
|
+
| `returnable` | Boolean | ★ Whether returnable |
|
|
105
|
+
| `sellerRemarkText` | String | ★ Seller remarks |
|
|
106
|
+
| `buyerRemarkText` | String | ★ Buyer remarks |
|
|
107
|
+
| `Variation` | String | ★ Variation attributes (color, size, etc.) |
|
|
108
|
+
|
|
109
|
+
#### Address Level (`OpenAddressDTO`, nested in `address_shipping`)
|
|
110
|
+
|
|
111
|
+
| Field | Type | Description |
|
|
112
|
+
|-------|------|-------------|
|
|
113
|
+
| `FirstName` | String | Recipient first name |
|
|
114
|
+
| `LastName` | String | Recipient last name |
|
|
115
|
+
| `Phone` | String | Phone |
|
|
116
|
+
| `Phone2` | String | Alternate phone |
|
|
117
|
+
| `Address1` ~ `Address5` | String | Address lines 1-5 |
|
|
118
|
+
| `CustomerEmail` | String | Email |
|
|
119
|
+
| `City` | String | ★ City |
|
|
120
|
+
| `PostCode` | String | Postal code |
|
|
121
|
+
| `Country` | String | Country |
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
### Reverse Order API `/reverse/getreverseordersforseller` Parameters (complete, strictly per official docs)
|
|
126
|
+
|
|
127
|
+
#### Common Parameters (same as all Open APIs)
|
|
128
|
+
`app_key` / `timestamp` / `access_token` / `sign_method` / `sign` are required; `isv_channel` is optional. Injected uniformly by `MiraviaClient._common_params()` + `generate_sign()`; business logic need not handle these.
|
|
129
|
+
|
|
130
|
+
#### Business Parameters (13 total)
|
|
131
|
+
|
|
132
|
+
| Parameter | Type | Required | Description |
|
|
133
|
+
|-----------|------|----------|-------------|
|
|
134
|
+
| `page_size` | Number | **Yes** | Page size, default 10; this Skill defaults to 100 |
|
|
135
|
+
| `page_no` | Number | **Yes** | Page number, starting from 1 |
|
|
136
|
+
| `trade_order_id` | Number | No | **Filter by forward main order ID** — single-order reverse query entry |
|
|
137
|
+
| `reverse_order_id` | Number | No | Filter by reverse order ID |
|
|
138
|
+
| `reverse_tracking_number` | String | No | Filter by return tracking number, e.g. `TN23423` |
|
|
139
|
+
| `trade_order_time_range_start_time_stamp` | Number | No | Main order creation start time, **millisecond timestamp** |
|
|
140
|
+
| `trade_order_time_range_end_time_stamp` | Number | No | Main order creation end time, **millisecond timestamp** |
|
|
141
|
+
| `reverse_order_line_time_range_start_time_stamp` | Number | No | Reverse order line creation start time, **millisecond timestamp** |
|
|
142
|
+
| `reverse_order_line_time_range_end_time_stamp` | Number | No | Reverse order line creation end time, **millisecond timestamp** |
|
|
143
|
+
| `reverse_status_list` | String[] | No | JSON array string, see "reverse_status enum" below |
|
|
144
|
+
| `ofc_status_list` | String[] | No | JSON array string, return logistics status, see "ofc_status enum" below |
|
|
145
|
+
| `dispute_in_progress` | Boolean | No | Whether dispute is in progress |
|
|
146
|
+
| `marketplace` | String | No | Marketplace: `ae` / `miravia`, empty returns all |
|
|
147
|
+
|
|
148
|
+
##### reverse_status Enum (used in both request filter and response fields)
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
REQUEST_INITIATE Buyer initiated request
|
|
152
|
+
REQUEST_REJECT Request rejected
|
|
153
|
+
REQUEST_CANCEL Request cancelled
|
|
154
|
+
CANCEL_SUCCESS Cancellation succeeded
|
|
155
|
+
REPLACE_PENDING Replacement pending
|
|
156
|
+
REPLACE_WAIT_AUDIT Replacement awaiting audit
|
|
157
|
+
REPLACE_SUCCESS Replacement succeeded (note: official docs have typo: dREPLACE_SUCCESS)
|
|
158
|
+
REFUND_PENDING ★ Refund pending (key status to monitor)
|
|
159
|
+
REFUND_AUTHORIZED Refund authorized
|
|
160
|
+
REFUND_SUCCESS ★ Refund succeeded (key status to monitor)
|
|
161
|
+
REFUND_REJECT Refund rejected
|
|
162
|
+
REQUEST_COMPLETE Request completed
|
|
163
|
+
SELLER_AGREE_RETURN Seller agreed to return
|
|
164
|
+
SELLER_REJECT_RETURN Seller rejected return
|
|
165
|
+
BUYER_RETURN_ITEM ★ Buyer has returned item (key status to monitor)
|
|
166
|
+
SELLER_AGREE_REFUND Seller agreed to refund
|
|
167
|
+
SELLER_REJECT_REFUND Seller rejected refund
|
|
168
|
+
CS_APPROVING CS reviewing
|
|
169
|
+
AGREE_CANCEL_ORDER Agreed to cancel order
|
|
170
|
+
REJECT_CANCEL_ORDER Rejected cancel order
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
##### ofc_status Enum (OrderFulfillmentCenter / return logistics status)
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
RETURN_PICKUP_PENDING Pending pickup
|
|
177
|
+
RETURN_TPL_RECEIVED ★ 3PL received, in transit to seller/warehouse
|
|
178
|
+
RETURN_DELIVERED ★ Delivered to seller/warehouse
|
|
179
|
+
RETURN_STOCK_INBOUND ★ Miravia warehouse inbound completed
|
|
180
|
+
RETURN_QC_DONE ★ Warehouse QC completed
|
|
181
|
+
RETURN_LOGISTIC_CLOSURE ★ Warehouse refund/reject decision made
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
##### request_type Enum (response field, reverse request type)
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
CANCEL Cancellation
|
|
188
|
+
RETURN Return
|
|
189
|
+
REPLACEMENT Replacement
|
|
190
|
+
ONLY_REFUND Refund only
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
##### refund_payment_method Enum (response field, refund method)
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
CARD_APPLE_PAY / CARD_GOOGLE_PAY / DIRECTDEBIT_PAYPAL / MIXEDCARD
|
|
197
|
+
NO_REFUND / ONLINE_BANKING_BIZUM / WALLET_PAYPAL_PAYLATER
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
##### shipping_type Enum (response field, return shipping method)
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
DEFAULT / PICK_UP / DROP_OFF / CUSTOMER_SEND
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### Two Correct Approaches for Single-Order Queries
|
|
207
|
+
|
|
208
|
+
| Seller Need | Recommended Parameters |
|
|
209
|
+
|-------------|----------------------|
|
|
210
|
+
| Check refund/return full status for a specific order | `trade_order_id=<main_order_id>` + `page_size=100, page_no=1` (no time window needed) |
|
|
211
|
+
| Known reverse order ID, query details | `reverse_order_id=<reverse_order_id>` |
|
|
212
|
+
| Known return tracking number, reverse lookup order | `reverse_tracking_number=<TN...>` |
|
|
213
|
+
| Batch refund rate diagnosis / Top refund SKUs | `trade_order_time_range_start_time_stamp/...end...` (milliseconds) + `reverse_status_list=[REFUND_SUCCESS,REFUND_PENDING,...]` |
|
|
214
|
+
|
|
215
|
+
> ⚠️ **Historical Pitfalls** (retained as warning): The following parameters **do not exist** and will be silently ignored by the server (returning all data); do not use them:
|
|
216
|
+
> - `start_create_time` / `end_create_time` (incorrect field names, and not millisecond timestamps)
|
|
217
|
+
> - `status` (single value) and enums like `REQUESTING / REFUNDING / CLOSED / REJECTED`
|
|
218
|
+
>
|
|
219
|
+
> The server has a deep pagination limit around `page_no >= ~31` (offset > 3000).
|
|
220
|
+
> This Skill uses `max_pages=30` in batch scenarios; if `total` exceeds the limit, split time windows and re-fetch.
|
|
221
|
+
> **For single-order queries**, use `trade_order_id` for exact filtering — results are typically 1 to a few records, never hitting pagination limits.
|
|
222
|
+
|
|
223
|
+
### Reverse Order `/reverse/getreverseordersforseller` Full Response Fields
|
|
224
|
+
|
|
225
|
+
> Below is the complete response field reference from API docs. ★ = fields newly used in v4 dashboard.
|
|
226
|
+
> ⚠️ The reverse sub-order `refundAmount` unit is **cents**; divide by 100 to convert to currency units.
|
|
227
|
+
> ⚠️ `requestType` is at the **main order level**, not sub-order level; `_flatten()` must propagate it from main to sub-order level.
|
|
228
|
+
|
|
229
|
+
#### Main Order Level (`data.items[]`, `OpenApiReverseOrderResponse`)
|
|
230
|
+
|
|
231
|
+
| Field | Type | Description |
|
|
232
|
+
|-------|------|-------------|
|
|
233
|
+
| `reverseOrderId` | Number | Reverse order ID |
|
|
234
|
+
| `tradeOrderId` | Number | Forward main order ID |
|
|
235
|
+
| `requestType` | String | ★ Refund type: `CANCEL` / `RETURN` / `ONLY_REFUND` / `REPLACEMENT` |
|
|
236
|
+
| `shippingType` | String | ★ Shipping method (see `shipping_type` enum) |
|
|
237
|
+
| `rtm` | Boolean | ★ Whether seller warehouse |
|
|
238
|
+
| `bizType` | String | ★ Business type |
|
|
239
|
+
| `marketplace` | String | Marketplace identifier |
|
|
240
|
+
| `shipFrom` | String | ★ Ship-from location |
|
|
241
|
+
| `instantRefund` | Boolean | ★ Whether instant (small-amount) refund |
|
|
242
|
+
| `reverseOrderLineDTOList` | Array | Reverse sub-order list |
|
|
243
|
+
|
|
244
|
+
#### Sub-Order Level (`reverseOrderLineDTOList[]`, `OpenApiReverseOrderLineDTO`)
|
|
245
|
+
|
|
246
|
+
| Field | Type | Description |
|
|
247
|
+
|-------|------|-------------|
|
|
248
|
+
| `reverseOrderLineId` | Number | Reverse sub-order ID |
|
|
249
|
+
| `tradeOrderLineId` | Number | Forward sub-order ID (= `order_item_id`) |
|
|
250
|
+
| `platformTradeOrderItemId` | Number | Platform sub-order ID |
|
|
251
|
+
| `marketplace` | String | Marketplace identifier |
|
|
252
|
+
| `reverseStatus` | String | Reverse status, see `reverse_status` enum |
|
|
253
|
+
| `ofcStatus` | String | Return logistics status, see `ofc_status` enum |
|
|
254
|
+
| `isDispute` | Boolean | Whether in dispute |
|
|
255
|
+
| `isNeedRefund` | Boolean | Whether refund is needed |
|
|
256
|
+
| `actions` | String | Available actions |
|
|
257
|
+
| `refundAmount` | Number | Refund amount (**unit: cents**, divide by 100) |
|
|
258
|
+
| `refundCurrency` | String | Refund currency |
|
|
259
|
+
| `refundPaymentMethod` | String | ★ Refund payment method, see enum |
|
|
260
|
+
| `itemUnitPrice` | Number | Item unit price |
|
|
261
|
+
| `isFastRefund` | Boolean | Whether fast refund |
|
|
262
|
+
| `isInstantRefund` | Boolean | Whether instant refund |
|
|
263
|
+
| `isNotReceived` | Boolean | ★ Whether buyer has not received goods |
|
|
264
|
+
| `reasonText` | String | Refund reason text |
|
|
265
|
+
| `reasonCode` | String | ★ Refund reason code |
|
|
266
|
+
| `dutyParty` | String | ★ Refund duty party: `SELLER` / `PLATFORM` / `LOGISTIC` / `pending` |
|
|
267
|
+
| `whqcDecision` | String | ★ Warehouse QC decision |
|
|
268
|
+
| `trackingNumber` | String | Return tracking number |
|
|
269
|
+
| `returnShippingFee` | Number | ★ Return shipping fee |
|
|
270
|
+
| `affordReturnShippingFee` | Boolean | ★ Whether seller bears return shipping |
|
|
271
|
+
| `returnable` | Boolean | ★ Whether returnable |
|
|
272
|
+
| `goodsStatus` | String | ★ Goods status |
|
|
273
|
+
| `refundItemCounts` | Number | ★ Refund item count |
|
|
274
|
+
| `returnOrderLineGmtCreate` | String | Reverse sub-order creation time |
|
|
275
|
+
| `returnOrderLineGmtModified` | String | Reverse sub-order update time |
|
|
276
|
+
| `tradeOrderGmtCreate` | String | Forward main order creation time |
|
|
277
|
+
| `buyer` | Object | Buyer info (contains `userId`) |
|
|
278
|
+
| `sellerSkuId` | String | ★ Seller SKU ID |
|
|
279
|
+
| `platformSkuId` | String | ★ Platform SKU ID |
|
|
280
|
+
| `eanNumber` | String | ★ EAN barcode |
|
|
281
|
+
| `productDTO` | Object | ★ Product info {`id`, `sku`} |
|
|
282
|
+
| `features` | Object | Extended features |
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Field Mapping
|
|
287
|
+
|
|
288
|
+
> All column names are defined in `scripts/export_orders.py` constant `EXPORT_COLUMNS`.
|
|
289
|
+
|
|
290
|
+
### Main Order Basic Info (from `/orders/get`)
|
|
291
|
+
| Excel Column | API Field | Description |
|
|
292
|
+
|--------------|-----------|-------------|
|
|
293
|
+
| `order_id` | `order_id` | Main order ID |
|
|
294
|
+
| `marketplace` | `marketplace` / `country` | Marketplace |
|
|
295
|
+
| `created_at` | `created_at` | Order creation time |
|
|
296
|
+
| `items_count` | `items_count` | Total items in order |
|
|
297
|
+
| `payment_method` | `payment_method` | Payment method |
|
|
298
|
+
| `buyer_id` | `customer_first_name` / `buyer_id` | Buyer identifier (masked) |
|
|
299
|
+
| `ship_address` | `address_shipping` concatenated | Shipping address |
|
|
300
|
+
| `ship_country` | `address_shipping.country` | Ship-to country |
|
|
301
|
+
| `warehouse_code` | `warehouse_code` | Shipping warehouse |
|
|
302
|
+
| `buyer_remark` | `remarks` | Buyer remarks |
|
|
303
|
+
| `seller_remark` | `delivery_info` | Seller remarks |
|
|
304
|
+
|
|
305
|
+
### Sub-Order Basic (from `/orders/items/get`)
|
|
306
|
+
| Excel Column | API Field |
|
|
307
|
+
|--------------|-----------|
|
|
308
|
+
| `order_item_id` | `order_item_id` |
|
|
309
|
+
| `item_status` | `status` |
|
|
310
|
+
| `item_updated_at` | `updated_at` |
|
|
311
|
+
|
|
312
|
+
### Products
|
|
313
|
+
| Excel Column | API Field |
|
|
314
|
+
|--------------|-----------|
|
|
315
|
+
| `product_id` | `product_id` |
|
|
316
|
+
| `product_name` | `name` |
|
|
317
|
+
| `product_url` | `product_main_image` |
|
|
318
|
+
| `sku` | `sku` |
|
|
319
|
+
| `shop_sku` | `shop_sku` |
|
|
320
|
+
| `quantity` | Fixed 1 (API returns one row per item) |
|
|
321
|
+
| `unit_price` | `item_price` |
|
|
322
|
+
|
|
323
|
+
### Amounts
|
|
324
|
+
| Excel Column | API Field |
|
|
325
|
+
|--------------|-----------|
|
|
326
|
+
| `buyer_paid` | `paid_price` |
|
|
327
|
+
| `discount_total` | `voucher_amount` |
|
|
328
|
+
| `discount_platform` | `voucher_platform` |
|
|
329
|
+
| `discount_seller` | `voucher_seller` |
|
|
330
|
+
| `shipping_paid` | `shipping_amount` |
|
|
331
|
+
| `shipping_disc_total` | `shipping_amount_voucher` |
|
|
332
|
+
| `shipping_disc_platform` | `shipping_service_cost` |
|
|
333
|
+
| `shipping_disc_seller` | `shipping_amount_seller` |
|
|
334
|
+
| `currency` | `currency` |
|
|
335
|
+
|
|
336
|
+
### Logistics
|
|
337
|
+
| Excel Column | API Field |
|
|
338
|
+
|--------------|-----------|
|
|
339
|
+
| `shipment_type` | `shipment_type` |
|
|
340
|
+
| `tracking_no` | `tracking_code` |
|
|
341
|
+
| `package_id` | `package_id` |
|
|
342
|
+
| `shipping_provider` | `shipping_provider_type` / `shipping_provider` |
|
|
343
|
+
|
|
344
|
+
### Cancellation
|
|
345
|
+
| Excel Column | Source |
|
|
346
|
+
|--------------|--------|
|
|
347
|
+
| `is_canceled` | `cancel_return_initiator` non-empty or `status in ('canceled','cancelled')` |
|
|
348
|
+
| `cancel_initiator` | `cancel_return_initiator` |
|
|
349
|
+
| `cancel_reason` | `reason` / `reason_detail` |
|
|
350
|
+
|
|
351
|
+
### Refunds (from `/reverse/getreverseordersforseller`, joined by `trade_order_line_id == order_item_id`)
|
|
352
|
+
| Excel Column | API Field |
|
|
353
|
+
|--------------|-----------|
|
|
354
|
+
| `refund_id` | `reverse_order_id` / `dispute_id` |
|
|
355
|
+
| `refund_apply_at` | `reverse_order_lines[].return_order_line_gmt_create` / `trade_order_gmt_create` |
|
|
356
|
+
| `refund_status` | `reverse_order_lines[].reverse_status` |
|
|
357
|
+
| `refund_amount` | `reverse_order_lines[].refund_amount` |
|
|
358
|
+
| `refund_reason` | `reverse_order_lines[].reason_text` |
|
|
359
|
+
| `is_fast_refund` | `reverse_order_lines[].is_fast_refund` |
|
|
360
|
+
| `is_instant_refund` | `reverse_order_lines[].is_instant_refund` |
|
|
361
|
+
| `refund_tracking_no` | `reverse_order_lines[].tracking_number` |
|
|
362
|
+
|
|
363
|
+
## HTML Report Fields
|
|
364
|
+
|
|
365
|
+
### v4 Unified Dashboard (`templates/report_v4.html`)
|
|
366
|
+
|
|
367
|
+
Data is injected via `window.DATA = {...}` JSON; frontend JS renders dynamically. 6 Tabs:
|
|
368
|
+
|
|
369
|
+
| Tab | Key Metrics |
|
|
370
|
+
|-----|-------------|
|
|
371
|
+
| Overview | KPI cards (orders/GMV/refund rate/cancel rate), executive summary, country distribution |
|
|
372
|
+
| Sales Performance | Daily trends, net revenue, AOV tiers, payment methods, seller discounts, shipping stats, order status |
|
|
373
|
+
| Cancellations & Refunds | Cancel initiator, seller approval rate, cancel reasons, refund types, duty party, refund reasons, fast refund, refund SKUs |
|
|
374
|
+
| Product Insights | Top SKUs, SKU matrix (volume × refund rate), category distribution, discount depth, FBM ratio, digital vs physical |
|
|
375
|
+
| Buyers & Markets | Buyer KPIs, country detail table, city distribution, country sparklines, payment × country, anomalous buyers |
|
|
376
|
+
| Logistics & Fulfillment | Logistics provider distribution, FBM comparison, delivery types |
|
|
377
|
+
|
|
378
|
+
Frontend interactions: Time range filter (7d/15d/30d/all) + Platform switch (All/Miravia/M2A)
|
|
379
|
+
|
|
380
|
+
## Signature Rules Quick Reference
|
|
381
|
+
|
|
382
|
+
```
|
|
383
|
+
api_path + key1 + value1 + key2 + value2 + ... (keys sorted ascending, empty values filtered out, sign excluded)
|
|
384
|
+
↓ HMAC-SHA256(secret)
|
|
385
|
+
↓ .hexdigest().upper()
|
|
386
|
+
= sign
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Implementation: `scripts/miravia_client.py::generate_sign`
|
|
390
|
+
|
|
391
|
+
## Excel Text Format Specification
|
|
392
|
+
|
|
393
|
+
The following columns contain long numeric string IDs and **must be written as text format** to avoid Excel displaying them in scientific notation or losing precision:
|
|
394
|
+
|
|
395
|
+
```
|
|
396
|
+
order_id, order_item_id, product_id, sku, shop_sku,
|
|
397
|
+
package_id, tracking_no, refund_id, refund_tracking_no, buyer_id
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Implementation: `scripts/export_orders.py::export_dataframe` uses `TEXT_ID_COLUMNS`, converting to pure strings + openpyxl `number_format='@'` as double insurance.
|
|
401
|
+
|
|
402
|
+
## Error Handling Conventions
|
|
403
|
+
|
|
404
|
+
| Error Code | Behavior |
|
|
405
|
+
|------------|----------|
|
|
406
|
+
| `IncompleteSignature` / `InvalidAccessToken` | Terminate; prompt user to re-authorize |
|
|
407
|
+
| HTTP network errors | Auto-retry 3 times (exponential backoff, max 5s) |
|
|
408
|
+
| `/reverse/...` failure | Soft failure, continue generating report without refund columns |
|
|
409
|
+
| Sub-order count ≥ `--max-orders` | Exit code 2, suggest narrowing time range |
|