Commit 8163427c by yexing

[yx]update

parent c1160bee
import { xlsx2csv } from "./xlsx.js"; import { xlsx2csv } from "./xlsx.js";
import { Plan, createZip, checkResponse } from "./util.js"; import { createZip, checkResponse } from "./util.js";
import { Plan, makeLogEntry } from "./timezone.js";
import { uploadFile } from "./upload.js"; import { uploadFile } from "./upload.js";
import { TABLE } from "./conf.js"; import { TABLE } from "./conf.js";
const checkOrigin = (u1, u2) => { const checkURL = (u1, u2) => {
if (!u1 || !u2) return false; if (!u1 || !u2) return false;
return u1.startsWith(new URL(u2).origin); return u1.startsWith(new URL(u2).origin) && !u1.includes("signin");
} };
const sendTabMsg = (msg, callback) => { const sendTabMsg = (msg, callback) => {
const uri = msg.data.uri; const uri = msg.data.uri;
chrome.tabs.query({}, (tabs) => { chrome.tabs.query({}, (tabs) => {
const tab = tabs.filter(x => checkOrigin(x.url, uri))[0]; const tab = tabs.filter(x => checkURL(x.url, uri))[0];
if (!tab) { if (!tab) {
const errorMsg = `tab not found, msg: ${JSON.stringify(msg)}` const errorMsg = `tab not found, msg: ${JSON.stringify(msg)}`
callback ? callback(errorMsg) : console.error(errorMsg); callback ? callback(errorMsg) : console.error(errorMsg);
chrome.notifications.create({
type: "basic",
title: "插件提醒",
message: "请重新打开页面!",
iconUrl: chrome.runtime.getURL('icon.png'),
requireInteraction: true,
});
return; return;
} }
console.log(`send ${JSON.stringify(msg)} to ${tab.url}`); console.log(`send ${JSON.stringify(msg)} to ${tab.url}`);
...@@ -106,10 +114,7 @@ function startTask() { ...@@ -106,10 +114,7 @@ function startTask() {
const ackLen = logs.filter(x => x.message.includes("完成")).length; const ackLen = logs.filter(x => x.message.includes("完成")).length;
chrome.runtime.sendMessage({ type: 'progress', logs }); chrome.runtime.sendMessage({ type: 'progress', logs });
if (ackLen === taskNum) { if (ackLen === taskNum) {
logs.push({ logs.push(makeLogEntry("已全部完成"));
time: new Date().toLocaleTimeString(),
message: "已全部完成"
});
chrome.runtime.sendMessage({ type: 'progress', logs }); chrome.runtime.sendMessage({ type: 'progress', logs });
// copy logs // copy logs
chrome.storage.local.set({ isRunning: false, logs }); chrome.storage.local.set({ isRunning: false, logs });
...@@ -124,8 +129,8 @@ function startTask() { ...@@ -124,8 +129,8 @@ function startTask() {
const initTimedTask = () => { const initTimedTask = () => {
for (const [key, { uri, params }] of Object.entries(TABLE)) { for (const [key, { uri, params }] of Object.entries(TABLE)) {
const plan = new Plan(null, params); const plan = new Plan(null, params);
const period = plan.get()?.period; const period = plan.get();
const when = plan.next().dt.getTime(); const when = plan.next().dt.valueOf();
chrome.alarms.create(key, { when }); chrome.alarms.create(key, { when });
console.log(`[timedTask] uri: ${uri} period: ${period} when: ${when}`); console.log(`[timedTask] uri: ${uri} period: ${period} when: ${when}`);
} }
...@@ -135,9 +140,9 @@ chrome.alarms.onAlarm.addListener((alarm) => { ...@@ -135,9 +140,9 @@ chrome.alarms.onAlarm.addListener((alarm) => {
if (!Object.keys(TABLE).includes(key)) return; if (!Object.keys(TABLE).includes(key)) return;
const { uri, params } = TABLE[key]; const { uri, params } = TABLE[key];
const plan = new Plan(null, params); const plan = new Plan(null, params);
const period = !fromDate || !toDate ? plan.get()?.period : [fromDate, toDate]; const period = !fromDate || !toDate ? plan.get() : [fromDate, toDate];
if (!when) { if (!when) {
when = plan.next().dt.getTime(); when = plan.next().dt.valueOf();
chrome.alarms.create(alarm.name, { when }); chrome.alarms.create(alarm.name, { when });
console.log(`[timedTask] uri: ${uri} period: ${period} when: ${when}`); console.log(`[timedTask] uri: ${uri} period: ${period} when: ${when}`);
} }
......
...@@ -24,10 +24,7 @@ const inventoryHealthCallback = async function (response) { ...@@ -24,10 +24,7 @@ const inventoryHealthCallback = async function (response) {
return response.blob(); return response.blob();
} }
const advertCallback = async function (response) { const advertCallback = async function (response) {
let { let { reportType = null, recommendationType = null, startDate = null, endDate = null } = this.options.body;
reportType = null, recommendationType = null,
startDate = null, endDate = null
} = this.options.body;
reportType ||= recommendationType; reportType ||= recommendationType;
const waitDone = async () => { const waitDone = async () => {
try { try {
...@@ -76,21 +73,22 @@ const advertCallback = async function (response) { ...@@ -76,21 +73,22 @@ const advertCallback = async function (response) {
return waitDone(); return waitDone();
} }
const rrCallback = async function (response) { const rrCallback = async function (response) {
const headers = this.options.headers;
const waitDone = async () => { const waitDone = async () => {
let url = new URL(`${this.uri}${this.names.apiName}`); let url = new URL(`${this.uri}${this.names.apiName}`);
url.search = new URLSearchParams({ url.search = new URLSearchParams({
"reportType": "ORDER", reportType: "ORDER",
"reportVersion": "v1", reportVersion: "v1",
"page": "1", page: "1",
"limit": "10" limit: "10"
}).toString(); }).toString();
console.log(`GET ${url}`); console.log(`GET ${url}`);
await sleep(DELAY * 30); // 60s await sleep(DELAY * 30); // 60s
response = await fetch(url, { headers: this.options.headers }); response = await fetch(url, { headers: headers });
console.log(response); console.log(response);
let data = await response.json(); let data = await response.json();
if (data.requests) { if (data.requests) {
const request = data.requests.find(item => item.requestId === requestId); const request = data.requests.find((item) => item.requestId === requestId);
if (request && request.requestStatus === "READY") { if (request && request.requestStatus === "READY") {
return; return;
} }
...@@ -134,7 +132,7 @@ const rrCallback = async function (response) { ...@@ -134,7 +132,7 @@ const rrCallback = async function (response) {
return null; return null;
} }
const gqlCallback = async function (response) { const gqlCallback = async function (response) {
const uri = this.uri, method = "POST", body = this.options.body, [fromDate, toDate] = this.options.period; const uri = this.uri, method = "POST", body = this.options.body, headers = this.options.headers, [fromDate, toDate] = this.options.period;
async function getID(json) { async function getID(json) {
const { campaignReports = null, pagination = null } = json.data.get_coop_campaigns; const { campaignReports = null, pagination = null } = json.data.get_coop_campaigns;
if (!campaignReports?.length) { if (!campaignReports?.length) {
...@@ -155,23 +153,61 @@ const gqlCallback = async function (response) { ...@@ -155,23 +153,61 @@ const gqlCallback = async function (response) {
} }
async function getData(campaignId, pageNumber) { async function getData(campaignId, pageNumber) {
const body = JSON.stringify({ const body = JSON.stringify({
"query": "\n query get_coop_campaign($itemLevelSummary: ItemLevelSummaryReportRequest!) {\n get_coop_campaign(itemLevelSummary: $itemLevelSummary) {\n pagination {\n pageNo\n pageSize\n totalCount\n totalPages\n }\n itemLevelReports {\n id\n name\n imageUrl\n status\n offerPrice\n competitorPrice\n offerId\n sku\n olqScore\n productId\n demand\n googlePrice\n sameSeller14Day {\n gmv\n roas\n }\n traffic {\n clicks\n ctr\n cpc\n adspend\n impressions\n }\n url\n }\n }\n}\n ", "query": `
query get_coop_campaign($itemLevelSummary: ItemLevelSummaryReportRequest!) {
get_coop_campaign(itemLevelSummary: $itemLevelSummary) {
pagination {
pageNo
pageSize
totalCount
totalPages
}
itemLevelReports {
id
name
imageUrl
status
offerPrice
competitorPrice
offerId
sku
olqScore
productId
demand
googlePrice
sameSeller14Day {
gmv
roas
}
issues
traffic {
clicks
ctr
cpc
adspend
impressions
}
url
}
}
}
`,
"variables": { "variables": {
"itemLevelSummary": { itemLevelSummary: {
campaignId, campaignId,
"sort": { sort: {
"attributionType": "same_seller", attributionType: "same_seller",
"sortBy": "adspend", sortBy: "adspend",
"sortOrder": "DESC" sortOrder: "DESC",
}, },
"startDate": fromDate, startDate: fromDate,
"endDate": toDate, endDate: toDate,
"page": { page: {
pageNumber, pageNumber,
"limit": 10 limit: 10,
} },
} },
} },
}); });
response = await fetch(uri, { headers, method, body }); response = await fetch(uri, { headers, method, body });
console.log(response); console.log(response);
...@@ -186,7 +222,7 @@ const gqlCallback = async function (response) { ...@@ -186,7 +222,7 @@ const gqlCallback = async function (response) {
ItemID: itemLevelReport.id, ItemID: itemLevelReport.id,
SKU: itemLevelReport.sku, SKU: itemLevelReport.sku,
Spend: itemLevelReport.traffic?.adspend || 0 Spend: itemLevelReport.traffic?.adspend || 0
} };
}); });
data.push(...item); data.push(...item);
const { pageNo, totalPages } = pagination; const { pageNo, totalPages } = pagination;
...@@ -205,6 +241,10 @@ const gqlCallback = async function (response) { ...@@ -205,6 +241,10 @@ const gqlCallback = async function (response) {
} }
const newJson = { status: "OK", data } const newJson = { status: "OK", data }
newJson.__route = "search_engine_marketing"; newJson.__route = "search_engine_marketing";
if (this.params.requestType === "OPEN_CYCLE") {
newJson["payCycleStatus"] = "open";
this.names.showName += " open";
}
newJson["walmartid"] = this.partnerId; newJson["walmartid"] = this.partnerId;
newJson["Starttime"] = fromDate; newJson["Starttime"] = fromDate;
newJson["Endtime"] = toDate; newJson["Endtime"] = toDate;
...@@ -236,16 +276,14 @@ const getPeriods = async (options = {}) => { ...@@ -236,16 +276,14 @@ const getPeriods = async (options = {}) => {
console.error(`response 获取失败: ${JSON.stringify(data)}`); console.error(`response 获取失败: ${JSON.stringify(data)}`);
throw new Error(response); throw new Error(response);
} }
response.shift(); // response.shift();
const { start = 0, end = 3, monthly = false } = options; const { start = 0, end = 3, isBimester = false } = options;
let periods; let periods;
if (monthly) { if (isBimester) {
const prevMouth = fmt0(getMouth(null, -1)).slice(0, -3); const prevMouth = getMouth(null, -1);
const curMouth = fmt0(new Date()).slice(0, -3); const curMouth = fmt0(new Date()).slice(0, -3);
const reg = new RegExp(`^${prevMouth}|^${curMouth}`); const reg = new RegExp(`^${prevMouth}|^${curMouth}`);
periods = response.filter( periods = response.filter((x) => reg.test(x.payPeriodFromDate) || reg.test(x.settleDate));
x => reg.test(x.payPeriodFromDate) || reg.test(x.settleDate)
);
} else { } else {
periods = response.slice(start, end); periods = response.slice(start, end);
} }
...@@ -265,7 +303,7 @@ const createAdvertTask = function (sign, bodyArgs, options = {}) { ...@@ -265,7 +303,7 @@ const createAdvertTask = function (sign, bodyArgs, options = {}) {
return { return {
method: 'POST', method: 'POST',
body: { body: {
"format": "gzip", format: "gzip",
advertiserId, advertiserId,
...bodyArgs, ...bodyArgs,
}, },
...@@ -274,7 +312,7 @@ const createAdvertTask = function (sign, bodyArgs, options = {}) { ...@@ -274,7 +312,7 @@ const createAdvertTask = function (sign, bodyArgs, options = {}) {
} }
} }
const aids = decodeState2(options.initialState)?.advertisers.map(x => x.id) || []; const aids = decodeState2(options.initialState)?.advertisers.map((x) => x.id) || [];
const names = { const names = {
apiName: "campaigns", apiName: "campaigns",
showName: `Advert ${sign}`, showName: `Advert ${sign}`,
...@@ -284,67 +322,62 @@ const createAdvertTask = function (sign, bodyArgs, options = {}) { ...@@ -284,67 +322,62 @@ const createAdvertTask = function (sign, bodyArgs, options = {}) {
request: options.request || "/v1/snapshot/report" request: options.request || "/v1/snapshot/report"
} }
if (aids.length > 1) { if (aids.length > 1) {
return new TaskGroup(aids.map(aid => { return new TaskGroup(
return new Task(names, params, getTaskOptions(aid)); aids.map((aid) => {
}), { unique: true }); return new Task(names, params, getTaskOptions(aid));
}), { unique: true });
} else { } else {
return new Task(names, params, getTaskOptions()); return new Task(names, params, getTaskOptions());
} }
} }
const createOrderTask = function (sign, bodyArgs, options = {}) { const createOrderTask = function (sign, bodyArgs, options = {}) {
const { fromDate, toDate } = bodyArgs; const { fromDate, toDate } = bodyArgs;
return new Task({ return new Task(
apiName: "reportRequests", {
apiName2: "downloadReport", apiName: "reportRequests",
showName: options.showName apiName2: "downloadReport",
}, { showName: options.showName,
"reportType": "ORDER",
"reportVersion": "v1",
"isDSV": "false",
"bizRole": "MP"
}, {
method: 'POST',
body: {
"rowFilters": [
{
"type": "enumFilter",
"values": [
"All"
],
"columnName": "orderGroups"
},
{
"type": "enumFilter",
"values": [
sign
],
"columnName": "fulfilmentTypes"
},
{
"type": "rangeFilter",
"columnName": "orderDate",
"from": fromDate,
"to": toDate
}
],
"additionalInfo": {
"reportSummary": `${sign} Fulfilled - ${fmt2(fromDate)} to ${fmt2(toDate)}`
},
"excludeColumns": [
"Order Type",
"Service PO#",
"Service Status",
"Total Service Cost",
"Service Scheduled Date"
]
}, },
headers: { {
...rrHeaders(), reportType: "ORDER",
reportVersion: "v1",
isDSV: "false",
bizRole: "MP",
}, },
callback: rrCallback, {
ext: "xlsx" method: "POST",
}); body: {
} rowFilters: [
{
type: "enumFilter",
values: ["All"],
columnName: "orderGroups",
},
{
type: "enumFilter",
values: [sign],
columnName: "fulfilmentTypes",
},
{
type: "rangeFilter",
columnName: "orderDate",
from: fromDate,
to: toDate,
},
],
additionalInfo: {
reportSummary: `${sign} Fulfilled - ${fmt2(fromDate)} to ${fmt2(toDate)}`,
},
excludeColumns: ["Order Type", "Service PO#", "Service Status", "Total Service Cost", "Service Scheduled Date"],
},
headers: {
...rrHeaders(),
},
callback: rrCallback,
ext: "xlsx",
}
);
};
export async function createTasks(uri, period) { export async function createTasks(uri, period) {
if (!uri.startsWith(location.origin)) { if (!uri.startsWith(location.origin)) {
return []; return [];
...@@ -359,51 +392,62 @@ export async function createTasks(uri, period) { ...@@ -359,51 +392,62 @@ export async function createTasks(uri, period) {
switch (uri) { switch (uri) {
case TABLE.PAYMENT.uri: case TABLE.PAYMENT.uri:
{ {
const periods = await retry( const periods = (await retry(getPeriods, { isThrow: false }, [{ isBimester: true }])) || [];
getPeriods,
{ isThrow: false },
[{ monthly: true }]
) || [];
await sleep(DELAY); await sleep(DELAY);
const tasks = []; const tasks = [];
Task.uri = uri; Task.uri = uri;
for (const period of periods) { for (const period of periods) {
fromDate = period.payPeriodFromDate; fromDate = period.payPeriodFromDate;
toDate = period.payPeriodToDate; toDate = period.payPeriodToDate;
const settleDate = period.settleDate; const { settleDate, payCycleStatus: requestType } = period;
const reportDate = fmt3(settleDate); const reportDate = fmt3(settleDate);
Task.desc = `${fromDate}_${toDate}`; Task.desc = `${fromDate}_${toDate}`;
if (requestType !== "OPEN_CYCLE") {
tasks.push(
new Task(
{
apiName: "report/reconreport/v1/reconFile",
showName: "Payments new report",
},
{
reportDate,
},
{
ext: "zip",
}
),
new Task(
{
apiName: "report/reconreport/reconFile",
showName: "Payments legacy report",
},
{
reportDate,
},
{
ext: "zip",
}
)
);
}
tasks.push( tasks.push(
new Task({ new Task(
apiName: "report/reconreport/v1/reconFile", {
showName: "Payments new report", apiName: "auroraPaymentsSettlementService/payment/settlementDetails",
}, { showName: "Export This Page",
reportDate },
}, { {
ext: "zip" settleDate,
}), fromDate,
new Task({ toDate,
apiName: "report/reconreport/reconFile", requestType,
showName: "Payments legacy report", },
}, { {
reportDate ext: "json",
}, { callback: jsonCallback,
ext: "zip" next: true,
}), }
)
new Task({
apiName: "auroraPaymentsSettlementService/payment/settlementDetails",
showName: "Export This Page",
}, {
settleDate,
fromDate,
toDate,
requestType: "SETTLED_CYCLE"
}, {
ext: "json",
callback: jsonCallback,
next: true,
}),
); );
} }
return tasks; return tasks;
...@@ -411,39 +455,84 @@ export async function createTasks(uri, period) { ...@@ -411,39 +455,84 @@ export async function createTasks(uri, period) {
case TABLE.GQL.uri: case TABLE.GQL.uri:
{ {
const body = { const body = {
"query": "\n query get_coop_campaigns($campaignSummary: CampaignSummaryRequest!) {\n get_coop_campaigns(campaignSummary: $campaignSummary) {\n pagination {\n pageNo\n pageSize\n totalCount\n totalPages\n }\n campaignReports {\n id\n name\n startDate\n endDate\n status\n labels\n budget\n targetRoas\n sameSeller14Day {\n gmv\n roas\n }\n traffic {\n clicks\n adspend\n cpc\n impressions\n ctr\n }\n }\n }\n}\n ", query: `
"variables": { query get_coop_campaigns($campaignSummary: CampaignSummaryRequest!) {
"campaignSummary": { get_coop_campaigns(campaignSummary: $campaignSummary) {
"startDate": fromDate, pagination {
"endDate": toDate, pageNo
"name": "", pageSize
"statuses": [ totalCount
"RUNNING", totalPages
"COMPLETED", }
"STOPPED", campaignReports {
"ERROR", id
"PAUSED" name
], startDate
"page": { endDate
"limit": 10, status
"pageNumber": 0 labels
} budget
} dailyBudget
} targetRoas
} sameSeller14Day {
gmv
roas
}
traffic {
clicks
adspend
cpc
impressions
ctr
}
biddingStrategyType
campaignRecommendations {
type
subType
recommendedValue
status
}
creationType
}
}
}
`,
variables: {
campaignSummary: {
startDate: fromDate,
endDate: toDate,
name: "",
statuses: ["RUNNING", "COMPLETED", "STOPPED", "ERROR", "PAUSED"],
page: {
limit: 10,
pageNumber: 0,
},
sort: {
sortBy: "status",
sortOrder: "ASC",
attributionType: "same_seller",
},
},
},
};
return [ return [
new Task({ new Task(
apiName: "", {
showName: "Search Engine Marketing", apiName: "",
}, {}, { showName: "Search Engine Marketing",
method: 'POST', },
ext: 'json', {},
body, {
period, method: "POST",
callback: gqlCallback, ext: "json",
next: true, body,
}) period,
] headers: rrHeaders(),
callback: gqlCallback,
next: true,
}
),
];
} }
case TABLE.ORDER.uri: case TABLE.ORDER.uri:
return [ return [
...@@ -455,135 +544,193 @@ export async function createTasks(uri, period) { ...@@ -455,135 +544,193 @@ export async function createTasks(uri, period) {
case TABLE.ADVERT.uri: case TABLE.ADVERT.uri:
{ {
const initialState = await chrome.runtime.sendMessage({ type: "executeScript", data: "initialState" }); const initialState = await chrome.runtime.sendMessage({ type: "executeScript", data: "initialState" });
const initialUrl = performance.getEntriesByType('navigation')[0]?.name || location.href; const initialUrl = performance.getEntriesByType("navigation")[0]?.name || location.href;
Task.partnerId = getValue("partner_id", initialUrl, "&"); Task.partnerId = getValue("partner_id", initialUrl, "&");
Task.uri = uri; Task.uri = uri;
return [ return [
createAdvertTask("Keyword Performance", { createAdvertTask(
"startDate": fromDate, "Keyword Performance",
"endDate": toDate, {
"reportType": "keyword", startDate: fromDate,
"attributionWindow": "days3", endDate: toDate,
"extraFields": ["noDate"], reportType: "keyword",
}, { initialState }), attributionWindow: "days3",
createAdvertTask("Placement Performance", { extraFields: ["noDate"],
"startDate": fromDate, },
"endDate": toDate, { initialState }
"reportType": "placement", ),
"attributionWindow": "days3", createAdvertTask(
"extraFields": ["noDate"], "Placement Performance",
}, { initialState }), {
createAdvertTask("Item Keyword Performance", { startDate: fromDate,
"startDate": fromDate, endDate: toDate,
"endDate": toDate, reportType: "placement",
"reportType": "itemKeyword", attributionWindow: "days3",
"attributionWindow": "days3", extraFields: ["noDate"],
"extraFields": ["noDate"], },
}, { initialState }), { initialState }
createAdvertTask("Item Performance", { ),
"startDate": fromDate, createAdvertTask(
"endDate": toDate, "Item Keyword Performance",
"reportType": "adItem", {
"attributionWindow": "days3", startDate: fromDate,
"extraFields": ["noDate", "splitAttribution"], endDate: toDate,
}, { initialState }), reportType: "itemKeyword",
createAdvertTask("Keyword Recommendations", { attributionWindow: "days3",
"recommendationType": "keywordRecommendations" extraFields: ["noDate"],
}, { },
request: "/v1/snapshot/recommendations", { initialState }
initialState ),
}), createAdvertTask(
"Item Performance",
{
startDate: fromDate,
endDate: toDate,
reportType: "adItem",
attributionWindow: "days3",
extraFields: ["noDate", "splitAttribution"],
},
{ initialState }
),
createAdvertTask(
"Keyword Recommendations",
{
recommendationType: "keywordRecommendations",
},
{
request: "/v1/snapshot/recommendations",
initialState,
}
),
]; ];
} }
default: default:
{ {
const cutOffDate = await retry( const cutOffDate = (await retry(getCutOffDate, { isThrow: false })) || "";
getCutOffDate, const [se, cut] = cutDate([fromDate, toDate], cutOffDate);
{ isThrow: false },
) || "";
const [s, cut] = cutDate([fromDate, toDate], cutOffDate);
Task.uri = uri; Task.uri = uri;
return [ return [
new Task({ new Task(
apiName: "salesReport", {
showName: "WFS Orders" apiName: "salesReport",
}, { showName: "WFS Orders",
fromDate, },
toDate, {
}, { ext: 'json' }), fromDate,
new Task({ toDate,
apiName: "salesReport", },
showName: "WFS Multchannel_Fulfillment_Details" { ext: "json" }
}, { ),
fromDate, new Task(
toDate, {
type: "MCS" apiName: "salesReport",
}, { ext: 'json' }), showName: "WFS Multchannel_Fulfillment_Details",
},
new TaskGroup([ {
new Task({
apiName: "returnsReport",
showName: "Customer returns"
}, {
fromDate, fromDate,
toDate: cut ? cutOffDate : toDate,
}, { ext: 'json' }),
new Task({
apiName: "customerReturnsReportDca",
showName: "New customer returns"
}, {
fromDate: cut ? cutOffDate : fromDate,
toDate, toDate,
}, { ext: 'json' }), type: "MCS",
].slice(...s)), },
{ ext: "json" }
),
new TaskGroup(
[
new Task(
{
apiName: "returnsReport",
showName: "Customer returns",
},
{
fromDate,
toDate: cut ? cutOffDate : toDate,
},
{ ext: "json" }
),
new Task(
{
apiName: "customerReturnsReportDca",
showName: "New customer returns",
},
{
fromDate: cut ? cutOffDate : fromDate,
toDate,
},
{ ext: "json" }
),
].slice(...se)
),
new Task({ new Task(
apiName: "inventoryReconciliation", {
showName: "Inventory reconciliation" apiName: "inventoryReconciliation",
}, { showName: "Inventory reconciliation",
fromDate, },
toDate, {
}), fromDate,
new Task({ toDate,
apiName: "poAudit", }
showName: "Inbound receipts" ),
}, { new Task(
fromDate, {
toDate, apiName: "poAudit",
gtin: "" showName: "Inbound receipts",
}), },
new Task({ {
apiName: "feeDetailReport", fromDate,
showName: "Settlement" toDate,
}, { gtin: "",
startDate: fromDate, }
endDate: toDate, ),
}), new Task(
new Task({ {
apiName: "storageFeeReport", apiName: "feeDetailReport",
showName: "Storage" showName: "Settlement",
}, { },
startDate: fromDate, {
endDate: toDate, startDate: fromDate,
}), endDate: toDate,
new Task({ }
apiName: "inboundTransportationReport", ),
showName: "Inbound transportation" new Task(
}, { {
startDate: fromDate, apiName: "storageFeeReport",
endDate: toDate, showName: "Storage",
}), },
{
startDate: fromDate,
endDate: toDate,
}
),
new Task(
{
apiName: "inboundTransportationReport",
showName: "Inbound transportation",
},
{
startDate: fromDate,
endDate: toDate,
}
),
new Task({ new Task(
apiName: "inventoryHealthReport", {
showName: "Inventory health" apiName: "inventoryHealthReport",
}, {}, { callback: inventoryHealthCallback }), showName: "Inventory health",
new Task({ },
apiName: "inventoryHealthReport", {},
showName: "Inventory health mcs" { callback: inventoryHealthCallback }
}, { ),
reportType: "multichannel" new Task(
}, { callback: inventoryHealthCallback }), {
apiName: "inventoryHealthReport",
showName: "Inventory health mcs",
},
{
reportType: "multichannel",
},
{ callback: inventoryHealthCallback }
),
]; ];
} }
} }
......
...@@ -3,13 +3,13 @@ const p1 = [ ...@@ -3,13 +3,13 @@ const p1 = [
[`11 ${hour}:`, ["01", "10"]], [`11 ${hour}:`, ["01", "10"]],
[`21 ${hour}:`, ['11', '20']], [`21 ${hour}:`, ['11', '20']],
[`01 ${hour}:`, ['21', 0]], [`01 ${hour}:`, ['21', 0]],
[`03 00:`, ['01', 0]] [`05 00:`, ['01', 0]]
];
const p2 = [
[`11 ${hour}:`, ["01", "10"]],
[`21 ${hour}:`, ['11', '20']],
[`03 00:`, ['01', 0]]
]; ];
// const p2 = [
// [`11 ${hour}:`, ["01", "10"]],
// [`21 ${hour}:`, ['11', '20']],
// [`05 00:`, ['01', 0]]
// ];
export const TABLE = { export const TABLE = {
WFS: { WFS: {
name: "WFS", name: "WFS",
...@@ -19,7 +19,7 @@ export const TABLE = { ...@@ -19,7 +19,7 @@ export const TABLE = {
PAYMENT: { PAYMENT: {
name: "放款表", name: "放款表",
uri: "https://seller.walmart.com/aurora/v1/", uri: "https://seller.walmart.com/aurora/v1/",
params: p2 params: p1
}, },
GQL: { GQL: {
name: "营销表", name: "营销表",
......
import { sleep, xpath, createZip, fmt0, addLog } from "./util.js"; import { sleep, xpath, createZip, fmt0 } from "./util.js";
import { addLog } from "./timezone.js";
import { createTasks } from "./base.js"; import { createTasks } from "./base.js";
import { Task } from "./task.js"; import { Task } from "./task.js";
import { uploadFile } from "./upload.js"; import { uploadFile } from "./upload.js";
...@@ -21,7 +22,9 @@ async function run(options = {}) { ...@@ -21,7 +22,9 @@ async function run(options = {}) {
const [key, { name }] = Object.entries(TABLE).find((item) => item[1].uri === uri); const [key, { name }] = Object.entries(TABLE).find((item) => item[1].uri === uri);
let tasks = await createTasks(uri, period); let tasks = await createTasks(uri, period);
tasks = sn ? [tasks.at(sn)] : tasks; tasks = sn ? [tasks.at(sn)] : tasks;
let moment = 3000, idx = 0, len = tasks.length; // 在季度周期过滤掉月度任务
// tasks = tasks.filter((x)=>!x.isMonthly);
let moment = 2000, idx = 0, len = tasks.length;
const allData = [], allFn = [], zipFn = `${Task.partnerId} #${key}# ${fromDate}_${toDate}.zip`; const allData = [], allFn = [], zipFn = `${Task.partnerId} #${key}# ${fromDate}_${toDate}.zip`;
for (const task of tasks) { for (const task of tasks) {
const pf = `${++idx}/${len}`; const pf = `${++idx}/${len}`;
......
...@@ -10,6 +10,80 @@ dayjs.extend(isSameOrBefore); ...@@ -10,6 +10,80 @@ dayjs.extend(isSameOrBefore);
const CST = "Asia/Shanghai"; const CST = "Asia/Shanghai";
const PT = "America/Los_Angeles"; const PT = "America/Los_Angeles";
export class Plan {
constructor(dt, params) {
this.dt = dayjs.tz(dt ?? new Date(), CST);
this.setHandler();
this.table = new Proxy({}, this.handler);
this.params = [];
params?.forEach(param => this._addParam(...param));
}
setHandler() {
this.handler = {
dt: this.dt,
order: [], // 逆序
get(obj, prop) {
if (prop in obj) return obj[prop];
const idx = this.order.find(x => prop - x >= 0);
return obj[idx];
},
set(obj, prop, value) {
const result = Reflect.set(...arguments);
this.order = Object.keys(obj).sort((a, b) => b - a);
let [x1, x2] = value.period, dt = this.dt;
if (this.dt.date() < parseInt(x2) || x2 === 0) {
dt = this.dt.subtract(1, "month");
}
let year = dt.year();
let month = dt.month() + 1;
x2 = x2 === 0 ? dt.daysInMonth() : x2;
month = (month + '').padStart(2, "0");
value.period = [
`${year}-${month}-${x1}`,
`${year}-${month}-${x2}`
];
return result;
}
};
}
get(day = null) {
const it = day ? this.table[day] : this.table[this.dt.date()];
return it?.period;
}
next() {
let dt = this.dt;
const order = this.handler.order;
const idx = (
order.indexOf(this.get().dt.date() + '') - 1 + order.length // 向上
) % order.length;
if (idx == order.length - 1) {
dt = dt.add(1, "month");
}
let year = dt.year();
let month = dt.month();
dt = this.table[order[idx]].dt
.set("year", year)
.set("month", month);
return new Plan(dt, this.params);
}
_addParam(execTime, period) {
// MM-dd HH:mm:ss
const dt = dayjs.tz(new Date(), CST)
.set("date", +execTime.substring(0, 2))
.set("hour", +execTime.substring(3, 5));
this.table[dt.date()] = { period, dt };
this.params.push(arguments);
}
}
export const makeLogEntry = (message) => {
return {
time: dayjs.tz(new Date(), CST).format("HH:mm:ss"),
message
}
};
export const addLog = (message, push) => chrome.runtime.sendMessage({ type: "addLog", data: makeLogEntry(message), push });
const checkTime = (time) => { const checkTime = (time) => {
if (!time.isValid()) throw new Error("无效时间"); if (!time.isValid()) throw new Error("无效时间");
} }
...@@ -38,7 +112,7 @@ export function isLatestDate(dt) { ...@@ -38,7 +112,7 @@ export function isLatestDate(dt) {
const time = dayjs.tz(dt ?? new Date(), PT); const time = dayjs.tz(dt ?? new Date(), PT);
checkTime(time); checkTime(time);
const now = dayjs.tz(undefined, PT); const now = dayjs.tz(undefined, PT);
return time.isSame(now, "day") return time.isSame(now, "day")
|| time.isSame(now.subtract(1, "day"), "day") || time.isSame(now.subtract(1, "day"), "day")
|| time.isSame(now.add(1, "day"), "day"); || time.isSame(now.add(1, "day"), "day");
} }
......
...@@ -131,70 +131,6 @@ export function downloadFile(fn, blob) { ...@@ -131,70 +131,6 @@ export function downloadFile(fn, blob) {
a.remove(); a.remove();
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
} }
export class Plan {
constructor(dt, params) {
this.dt = dt = dt && new Date(dt) || new Date();
this.handler = {
order: [], // 逆序
get(obj, prop) {
if (prop in obj) return obj[prop];
const idx = this.order.find(x => prop - x >= 0);
return obj[idx];
},
set(obj, prop, value) {
const result = Reflect.set(...arguments);
this.order = Object.keys(obj).sort((a, b) => b - a);
let [x1, x2] = value.period;
let year = dt.getFullYear();
let month = dt.getMonth();
if (dt.getDate() < parseInt(x2) || x2 === 0) {
month = month == 0 ? 11 : month - 1;
year = month == 0 ? year - 1 : year;
}
month++;
const endDate = new Date(year, month, 0).getDate() + '';
x2 = x2 === 0 ? endDate : x2;
month = (month + '').padStart(2, '0');
value.period = [
`${year}-${month}-${x1}`,
`${year}-${month}-${x2}`
];
return result;
}
}
this.table = new Proxy({}, this.handler);
this.params = [];
params?.forEach(args => this._addParam(...args));
}
get(day = null) {
return day ? this.table[day] : this.table[this.dt.getDate()];
}
next() {
let year = this.dt.getFullYear();
let month = this.dt.getMonth() + 1;
const order = this.handler.order;
const idx = (
order.indexOf(this.get().day) - 1 + order.length // 向上
) % order.length;
if (idx == order.length - 1) {
month = month == 12 ? 1 : month + 1;
year = month == 12 ? year + 1 : year;
}
const info = this.table[order[idx]];
return new Plan(new Date(`${year}-${month}-${info.day} ${info.time}`), this.params);
}
_addParam(execTime, period) {
// MM-dd HH:mm:ss
const dt = new Date(`01-${execTime}`);
this.table[dt.getDate()] = {
period,
day: dt.getDate() + '',
time: `${dt.toTimeString().substring(0, 8)}`,
};
this.params.push(arguments);
}
}
export function fmt0(d1, diff = 0) { export function fmt0(d1, diff = 0) {
const dt1 = new Date(d1); const dt1 = new Date(d1);
dt1.setDate(d1.getDate() + diff); dt1.setDate(d1.getDate() + diff);
...@@ -224,10 +160,3 @@ export function ffmt1(d1, d2) { ...@@ -224,10 +160,3 @@ export function ffmt1(d1, d2) {
const dt2 = new Date(d2); const dt2 = new Date(d2);
return `${dt1.getMonth() + 1}${dt1.getDate()}-${dt2.getDate()}`; return `${dt1.getMonth() + 1}${dt1.getDate()}-${dt2.getDate()}`;
} }
export const addLog = (message, push) => {
const logEntry = {
time: new Date().toLocaleTimeString(),
message
};
chrome.runtime.sendMessage({ type: "addLog", data: logEntry, push });
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment