fixed account parsing
parent
ac17e1a8de
commit
fe9b604c04
|
|
@ -109,17 +109,17 @@ void IntegrationPluginTempo::discoverThings(ThingDiscoveryInfo *info)
|
||||||
if (info->thingClassId() == accountThingClassId) {
|
if (info->thingClassId() == accountThingClassId) {
|
||||||
Q_FOREACH(Tempo *tempo, m_tempoConnections) {
|
Q_FOREACH(Tempo *tempo, m_tempoConnections) {
|
||||||
tempo->getAccounts();
|
tempo->getAccounts();
|
||||||
Thing *parentThing = m_tempoConnections.key(tempo);
|
ThingId parentThingId = m_tempoConnections.key(tempo);
|
||||||
if (!parentThing) {
|
if (parentThingId.isNull()) {
|
||||||
qCWarning(dcTempo()) << "Parent not found";
|
qCWarning(dcTempo()) << "Parent not found";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connect(tempo, &Tempo::accountsReceived, info, [info, parentThing, this, tempo] (const QList<Tempo::Account> &accounts) {
|
connect(tempo, &Tempo::accountsReceived, info, [info, parentThingId] (const QList<Tempo::Account> &accounts) {
|
||||||
Q_FOREACH(Tempo::Account account, accounts) {
|
Q_FOREACH(Tempo::Account account, accounts) {
|
||||||
if (account.status == Tempo::Status::Archived)
|
if (account.status == Tempo::Status::Archived)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ThingDescriptor descriptor(accountThingClassId, account.name, account.customer.name, parentThing->id());
|
ThingDescriptor descriptor(accountThingClassId, account.name, account.customer.name, parentThingId);
|
||||||
ParamList params;
|
ParamList params;
|
||||||
params << Param(accountThingKeyParamTypeId, account.key);
|
params << Param(accountThingKeyParamTypeId, account.key);
|
||||||
descriptor.setParams(params);
|
descriptor.setParams(params);
|
||||||
|
|
@ -130,15 +130,15 @@ void IntegrationPluginTempo::discoverThings(ThingDiscoveryInfo *info)
|
||||||
} else if (info->thingClassId() == teamThingClassId) {
|
} else if (info->thingClassId() == teamThingClassId) {
|
||||||
Q_FOREACH(Tempo *tempo, m_tempoConnections) {
|
Q_FOREACH(Tempo *tempo, m_tempoConnections) {
|
||||||
tempo->getTeams();
|
tempo->getTeams();
|
||||||
Thing *parentThing = m_tempoConnections.key(tempo);
|
ThingId parentThingId = m_tempoConnections.key(tempo);
|
||||||
if (!parentThing) {
|
if (parentThingId.isNull()) {
|
||||||
qCWarning(dcTempo()) << "Parent not found";
|
qCWarning(dcTempo()) << "Parent not found";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connect(tempo, &Tempo::teamsReceived, info, [info, parentThing, this, tempo] (const QList<Tempo::Team> &teams) {
|
connect(tempo, &Tempo::teamsReceived, info, [info, parentThingId] (const QList<Tempo::Team> &teams) {
|
||||||
Q_FOREACH(Tempo::Team team, teams) {
|
Q_FOREACH(Tempo::Team team, teams) {
|
||||||
|
|
||||||
ThingDescriptor descriptor(teamThingClassId, team.name, team.summary, parentThing->id());
|
ThingDescriptor descriptor(teamThingClassId, team.name, team.summary, parentThingId);
|
||||||
ParamList params;
|
ParamList params;
|
||||||
params << Param(teamThingIdParamTypeId, team.id);
|
params << Param(teamThingIdParamTypeId, team.id);
|
||||||
descriptor.setParams(params);
|
descriptor.setParams(params);
|
||||||
|
|
@ -160,9 +160,9 @@ void IntegrationPluginTempo::setupThing(ThingSetupInfo *info)
|
||||||
if (thing->thingClassId() == tempoConnectionThingClassId) {
|
if (thing->thingClassId() == tempoConnectionThingClassId) {
|
||||||
|
|
||||||
Tempo *tempo;
|
Tempo *tempo;
|
||||||
if (m_tempoConnections.contains(thing)) {
|
if (m_tempoConnections.contains(thing->id())) {
|
||||||
qCDebug(dcTempo()) << "Setup after reconfiguration, cleaning up";
|
qCDebug(dcTempo()) << "Setup after reconfiguration, cleaning up";
|
||||||
m_tempoConnections.take(thing)->deleteLater();
|
m_tempoConnections.take(thing->id())->deleteLater();
|
||||||
}
|
}
|
||||||
if (m_setupTempoConnections.keys().contains(thing->id())) {
|
if (m_setupTempoConnections.keys().contains(thing->id())) {
|
||||||
// This thing setup is after a pairing process
|
// This thing setup is after a pairing process
|
||||||
|
|
@ -171,7 +171,7 @@ void IntegrationPluginTempo::setupThing(ThingSetupInfo *info)
|
||||||
if (!tempo) {
|
if (!tempo) {
|
||||||
qCWarning(dcTempo()) << "Tempo connection object not found for thing" << thing->name();
|
qCWarning(dcTempo()) << "Tempo connection object not found for thing" << thing->name();
|
||||||
}
|
}
|
||||||
m_tempoConnections.insert(thing, tempo);
|
m_tempoConnections.insert(thing->id(), tempo);
|
||||||
info->finish(Thing::ThingErrorNoError);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
} else {
|
} else {
|
||||||
//device loaded from the device database, needs a new access token;
|
//device loaded from the device database, needs a new access token;
|
||||||
|
|
@ -187,15 +187,18 @@ void IntegrationPluginTempo::setupThing(ThingSetupInfo *info)
|
||||||
connect(info, &ThingSetupInfo::aborted, tempo, &Tempo::deleteLater);
|
connect(info, &ThingSetupInfo::aborted, tempo, &Tempo::deleteLater);
|
||||||
connect(tempo, &Tempo::authenticationStatusChanged, info, [info, tempo, this] (bool authenticated){
|
connect(tempo, &Tempo::authenticationStatusChanged, info, [info, tempo, this] (bool authenticated){
|
||||||
if (authenticated) {
|
if (authenticated) {
|
||||||
m_tempoConnections.insert(info->thing(), tempo);
|
m_tempoConnections.insert(info->thing()->id(), tempo);
|
||||||
|
connect(tempo, &Tempo::connectionChanged, this, &IntegrationPluginTempo::onConnectionChanged);
|
||||||
|
connect(tempo, &Tempo::authenticationStatusChanged, this, &IntegrationPluginTempo::onAuthenticationStatusChanged);
|
||||||
|
connect(tempo, &Tempo::accountsReceived, this, &IntegrationPluginTempo::onAccountsReceived);
|
||||||
|
connect(tempo, &Tempo::teamsReceived, this, &IntegrationPluginTempo::onTeamsReceived);
|
||||||
|
connect(tempo, &Tempo::accountWorklogsReceived, this, &IntegrationPluginTempo::onAccountWorkloadReceived);
|
||||||
|
connect(tempo, &Tempo::teamWorklogsReceived, this, &IntegrationPluginTempo::onTeamWorkloadReceived);
|
||||||
info->finish(Thing::ThingErrorNoError);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
tempo->getAccounts();
|
tempo->getAccounts();
|
||||||
}
|
}
|
||||||
connect(tempo, &Tempo::connectionChanged, this, &IntegrationPluginTempo::onConnectionChanged);
|
|
||||||
connect(tempo, &Tempo::authenticationStatusChanged, this, &IntegrationPluginTempo::onAuthenticationStatusChanged);
|
|
||||||
connect(tempo, &Tempo::accountsReceived, this, &IntegrationPluginTempo::onReceivedAccounts);
|
|
||||||
|
|
||||||
} else if (thing->thingClassId() == accountThingClassId ||
|
} else if (thing->thingClassId() == accountThingClassId ||
|
||||||
thing->thingClassId() == teamThingClassId){
|
thing->thingClassId() == teamThingClassId){
|
||||||
|
|
@ -223,53 +226,68 @@ void IntegrationPluginTempo::postSetupThing(Thing *thing)
|
||||||
connect(m_pluginTimer15min, &PluginTimer::timeout, this, [this]() {
|
connect(m_pluginTimer15min, &PluginTimer::timeout, this, [this]() {
|
||||||
qCDebug(dcTempo()) << "Refresh timer timout, polling all Tempo accounts.";
|
qCDebug(dcTempo()) << "Refresh timer timout, polling all Tempo accounts.";
|
||||||
Q_FOREACH (Thing *thing, myThings().filterByThingClassId(tempoConnectionThingClassId)) {
|
Q_FOREACH (Thing *thing, myThings().filterByThingClassId(tempoConnectionThingClassId)) {
|
||||||
Tempo *tempo = m_tempoConnections.value(thing);
|
Tempo *tempo = m_tempoConnections.value(thing->id());
|
||||||
if (!tempo) {
|
if (!tempo) {
|
||||||
qWarning(dcTempo()) << "No Tempo connection found for" << thing->name();
|
qWarning(dcTempo()) << "No Tempo connection found for" << thing->name();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tempo->getAccounts();
|
tempo->getAccounts();
|
||||||
|
tempo->getTeams();
|
||||||
Q_FOREACH (Thing *childThing, myThings().filterByParentId(thing->id())) {
|
Q_FOREACH (Thing *childThing, myThings().filterByParentId(thing->id())) {
|
||||||
QString key = childThing->paramValue(accountThingKeyParamTypeId).toString();
|
if (childThing->thingClassId() == accountThingClassId) {
|
||||||
QDate from(1970, 1, 1);
|
QString key = childThing->paramValue(accountThingKeyParamTypeId).toString();
|
||||||
tempo->getWorkloadByAccount(key, from, QDate::currentDate());
|
QDate from(1970, 1, 1);
|
||||||
|
tempo->getWorkloadByAccount(key, from, QDate::currentDate());
|
||||||
|
} else if (childThing->thingClassId() == teamThingClassId) {
|
||||||
|
int id = childThing->paramValue(teamThingIdParamTypeId).toInt();
|
||||||
|
QDate from(1970, 1, 1);
|
||||||
|
tempo->getWorkloadByTeam(id, from, QDate::currentDate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thing->thingClassId() == tempoConnectionThingClassId) {
|
if (thing->thingClassId() == tempoConnectionThingClassId) {
|
||||||
Tempo *tempo = m_tempoConnections.value(thing);
|
Tempo *tempo = m_tempoConnections.value(thing->id());
|
||||||
|
if (!tempo) {
|
||||||
|
qCWarning(dcTempo()) << "Tempo connection not found for" << thing->name();
|
||||||
|
return;
|
||||||
|
}
|
||||||
tempo->getAccounts();
|
tempo->getAccounts();
|
||||||
|
|
||||||
} else if (thing->thingClassId() == accountThingClassId) {
|
} else if (thing->thingClassId() == accountThingClassId) {
|
||||||
|
Tempo *tempo = m_tempoConnections.value(thing->parentId());
|
||||||
|
QString key = thing->paramValue(accountThingKeyParamTypeId).toString();
|
||||||
|
QDate from(1970, 1, 1);
|
||||||
|
tempo->getWorkloadByAccount(key, from, QDate::currentDate());
|
||||||
|
tempo->getAccounts();
|
||||||
} else if (thing->thingClassId() == teamThingClassId) {
|
} else if (thing->thingClassId() == teamThingClassId) {
|
||||||
|
Tempo *tempo = m_tempoConnections.value(thing->parentId());
|
||||||
}
|
int id = thing->paramValue(teamThingIdParamTypeId).toInt();
|
||||||
}
|
QDate from(1970, 1, 1);
|
||||||
|
tempo->getWorkloadByTeam(id, from, QDate::currentDate());
|
||||||
void IntegrationPluginTempo::executeAction(ThingActionInfo *info)
|
tempo->getTeams();
|
||||||
{
|
|
||||||
Thing *thing = info->thing();
|
|
||||||
Action action = info->action();
|
|
||||||
|
|
||||||
if (thing->thingClassId() == tempoConnectionThingClassId) {
|
|
||||||
|
|
||||||
} else if (thing->thingClassId() == accountThingClassId) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginTempo::thingRemoved(Thing *thing)
|
void IntegrationPluginTempo::thingRemoved(Thing *thing)
|
||||||
{
|
{
|
||||||
qCDebug(dcTempo()) << "Thing removed" << thing->name();
|
qCDebug(dcTempo()) << "Thing removed" << thing->name();
|
||||||
|
if (thing->thingClassId() == tempoConnectionThingClassId) {
|
||||||
|
m_tempoConnections.take(thing->id())->deleteLater();
|
||||||
|
}
|
||||||
|
if (myThings().isEmpty()) {
|
||||||
|
qCDebug(dcTempo()) << "Stopping plugin timer";
|
||||||
|
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer15min);
|
||||||
|
m_pluginTimer15min = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginTempo::onConnectionChanged(bool connected)
|
void IntegrationPluginTempo::onConnectionChanged(bool connected)
|
||||||
{
|
{
|
||||||
Tempo *tempo = static_cast<Tempo *>(sender());
|
Tempo *tempo = static_cast<Tempo *>(sender());
|
||||||
Thing *thing = m_tempoConnections.key(tempo);
|
Thing *thing = myThings().findById(m_tempoConnections.key(tempo));
|
||||||
if (!thing)
|
if (!thing)
|
||||||
return;
|
return;
|
||||||
thing->setStateValue(tempoConnectionConnectedStateTypeId, connected);
|
thing->setStateValue(tempoConnectionConnectedStateTypeId, connected);
|
||||||
|
|
@ -284,31 +302,107 @@ void IntegrationPluginTempo::onAuthenticationStatusChanged(bool authenticated)
|
||||||
{
|
{
|
||||||
qCDebug(dcTempo()) << "Authentication changed" << authenticated;
|
qCDebug(dcTempo()) << "Authentication changed" << authenticated;
|
||||||
|
|
||||||
Tempo *tempoConnection = static_cast<Tempo *>(sender());
|
Tempo *tempo = static_cast<Tempo *>(sender());
|
||||||
|
Thing *thing = myThings().findById(m_tempoConnections.key(tempo));
|
||||||
Thing *thing = m_tempoConnections.key(tempoConnection);
|
|
||||||
if (!thing)
|
if (!thing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
thing->setStateValue(tempoConnectionLoggedInStateTypeId, authenticated);
|
thing->setStateValue(tempoConnectionLoggedInStateTypeId, authenticated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginTempo::onAccountsReceived(const QList<Tempo::Account> accounts)
|
||||||
void IntegrationPluginTempo::onReceivedAccounts(const QList<Tempo::Account> &accounts)
|
|
||||||
{
|
{
|
||||||
qCDebug(dcTempo()) << "Received" << accounts.count() << "accounts";
|
qCDebug(dcTempo()) << "Accounts received";
|
||||||
|
|
||||||
|
Q_FOREACH(Tempo::Account account, accounts) {
|
||||||
|
qCDebug(dcTempo()) << " - Account" << account.name;
|
||||||
|
qCDebug(dcTempo()) << " - Key" << account.key;
|
||||||
|
qCDebug(dcTempo()) << " - Monthly budget" << account.monthlyBudget;
|
||||||
|
qCDebug(dcTempo()) << " - Lead" << account.lead.displayName;
|
||||||
|
qCDebug(dcTempo()) << " - Is Global" << account.global;
|
||||||
|
qCDebug(dcTempo()) << " - Contact type" << account.contact.type;
|
||||||
|
qCDebug(dcTempo()) << " - Contact account id" << account.contact.accountId;
|
||||||
|
qCDebug(dcTempo()) << " - Contact" << account.contact.displayName;
|
||||||
|
qCDebug(dcTempo()) << " - Category Id" << account.category.id;
|
||||||
|
qCDebug(dcTempo()) << " - Category name" << account.category.name;
|
||||||
|
qCDebug(dcTempo()) << " - Category key" << account.category.key;
|
||||||
|
qCDebug(dcTempo()) << " - Customer id" << account.customer.id;
|
||||||
|
qCDebug(dcTempo()) << " - Customer key" << account.customer.key;
|
||||||
|
qCDebug(dcTempo()) << " - Customer name" << account.customer.name;
|
||||||
|
|
||||||
|
Thing *thing = myThings().findByParams(ParamList() << Param(accountThingKeyParamTypeId, account.key));
|
||||||
|
if (!thing) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
thing->setName(account.name);
|
||||||
|
thing->setStateValue(accountConnectedStateTypeId, (account.status != Tempo::Status::Archived));
|
||||||
|
thing->setStateValue(accountLeadStateTypeId, account.lead.displayName);
|
||||||
|
thing->setStateValue(accountGlobalStateTypeId, account.global);
|
||||||
|
thing->setStateValue(accountCategoryStateTypeId, account.category.name);
|
||||||
|
thing->setStateValue(accountCustomerStateTypeId, account.customer.name);
|
||||||
|
thing->setStateValue(accountContactStateTypeId, account.contact.displayName);
|
||||||
|
thing->setStateValue(accountMonthlyBudgetStateTypeId, account.monthlyBudget);
|
||||||
|
|
||||||
|
if (account.status == Tempo::Status::Open) {
|
||||||
|
thing->setStateValue(accountStatusStateTypeId, "Open");
|
||||||
|
} else if (account.status == Tempo::Status::Closed) {
|
||||||
|
thing->setStateValue(accountStatusStateTypeId, "Closed");
|
||||||
|
} else if (account.status == Tempo::Status::Archived) {
|
||||||
|
thing->setStateValue(accountStatusStateTypeId, "Archived");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginTempo::onTeamsReceived(const QList<Tempo::Team> teams)
|
||||||
|
{
|
||||||
|
qCDebug(dcTempo()) << "Teams received";
|
||||||
|
|
||||||
|
Q_FOREACH(Tempo::Team team, teams) {
|
||||||
|
Thing *thing = myThings().findByParams(ParamList() << Param(teamThingIdParamTypeId, team.id));
|
||||||
|
if (!thing) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
thing->setName(team.name);
|
||||||
|
thing->setStateValue(teamConnectedStateTypeId, true);
|
||||||
|
thing->setStateValue(teamLeadStateTypeId, team.lead.displayName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginTempo::onAccountWorkloadReceived(const QString &accountKey, QList<Tempo::Worklog> workloads)
|
void IntegrationPluginTempo::onAccountWorkloadReceived(const QString &accountKey, QList<Tempo::Worklog> workloads)
|
||||||
{
|
{
|
||||||
|
qCDebug(dcTempo()) << "Account workload received, account key:" << accountKey << "Worklog etries: "<< workloads.count();
|
||||||
Thing *thing = myThings().findByParams(ParamList() << Param(accountThingKeyParamTypeId, accountKey));
|
Thing *thing = myThings().findByParams(ParamList() << Param(accountThingKeyParamTypeId, accountKey));
|
||||||
if (!thing)
|
if (!thing) {
|
||||||
|
qCWarning(dcTempo()) << "Could not find account thing for account key" << accountKey;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint totalTimeSpentSeconds = 0;
|
||||||
|
uint thisMonthTimeSpentSeconds = 0;
|
||||||
|
QDate today = QDate::currentDate();
|
||||||
|
Q_FOREACH(Tempo::Worklog workload, workloads) {
|
||||||
|
if (workload.createdAt.date().month() == today.month()) {
|
||||||
|
thisMonthTimeSpentSeconds += workload.timeSpentSeconds;
|
||||||
|
}
|
||||||
|
totalTimeSpentSeconds += workload.timeSpentSeconds;
|
||||||
|
}
|
||||||
|
thing->setStateValue(accountTotalTimeSpentStateTypeId, totalTimeSpentSeconds/3600.00);
|
||||||
|
thing->setStateValue(accountMonthTimeSpentStateTypeId, thisMonthTimeSpentSeconds/3600.00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginTempo::onTeamWorkloadReceived(int teamId, QList<Tempo::Worklog> workloads)
|
||||||
|
{
|
||||||
|
qCDebug(dcTempo()) << "Team workload received, team ID:" << teamId << "Worklog etries: "<< workloads.count();
|
||||||
|
Thing *thing = myThings().findByParams(ParamList() << Param(teamThingIdParamTypeId, teamId));
|
||||||
|
if (!thing) {
|
||||||
|
qCWarning(dcTempo()) << "Could not find team thing for account key" << teamId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint totalTimeSpentSeconds = 0;
|
uint totalTimeSpentSeconds = 0;
|
||||||
Q_FOREACH(Tempo::Worklog workload, workloads) {
|
Q_FOREACH(Tempo::Worklog workload, workloads) {
|
||||||
totalTimeSpentSeconds += workload.timeSpentSeconds;
|
totalTimeSpentSeconds += workload.timeSpentSeconds;
|
||||||
}
|
}
|
||||||
thing->setStateValue(accountTotalTimeSpentStateTypeId, totalTimeSpentSeconds/60);
|
thing->setStateValue(teamTotalTimeSpentStateTypeId, totalTimeSpentSeconds/3600.00);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,20 +52,22 @@ public:
|
||||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||||
void setupThing(ThingSetupInfo *info) override;
|
void setupThing(ThingSetupInfo *info) override;
|
||||||
void postSetupThing(Thing *thing) override;
|
void postSetupThing(Thing *thing) override;
|
||||||
void executeAction(ThingActionInfo *info) override;
|
|
||||||
void thingRemoved(Thing *thing) override;
|
void thingRemoved(Thing *thing) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PluginTimer *m_pluginTimer15min = nullptr;
|
PluginTimer *m_pluginTimer15min = nullptr;
|
||||||
|
|
||||||
QHash<ThingId, Tempo *> m_setupTempoConnections;
|
QHash<ThingId, Tempo *> m_setupTempoConnections;
|
||||||
QHash<Thing *, Tempo *> m_tempoConnections;
|
QHash<ThingId, Tempo *> m_tempoConnections;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onConnectionChanged(bool connected);
|
void onConnectionChanged(bool connected);
|
||||||
void onAuthenticationStatusChanged(bool authenticated);
|
void onAuthenticationStatusChanged(bool authenticated);
|
||||||
void onReceivedAccounts(const QList<Tempo::Account> &accounts);
|
|
||||||
|
void onAccountsReceived(const QList<Tempo::Account> accounts);
|
||||||
|
void onTeamsReceived(const QList<Tempo::Team> teams);
|
||||||
|
|
||||||
void onAccountWorkloadReceived(const QString &accountKey, QList<Tempo::Worklog> workloads);
|
void onAccountWorkloadReceived(const QString &accountKey, QList<Tempo::Worklog> workloads);
|
||||||
|
void onTeamWorkloadReceived(int teamId, QList<Tempo::Worklog> workloads);
|
||||||
};
|
};
|
||||||
#endif // INTEGRATIONPLUGINTEMPO_H
|
#endif // INTEGRATIONPLUGINTEMPO_H
|
||||||
|
|
|
||||||
|
|
@ -41,22 +41,6 @@
|
||||||
"displayNameEvent": "Logged in changed",
|
"displayNameEvent": "Logged in changed",
|
||||||
"defaultValue": true,
|
"defaultValue": true,
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "f3b9581b-7828-4fbe-be5f-3e8aad78a71e",
|
|
||||||
"name": "userDisplayName",
|
|
||||||
"displayName": "User name",
|
|
||||||
"displayNameEvent": "User name changed",
|
|
||||||
"defaultValue": "",
|
|
||||||
"type": "QString"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "db70444d-bf67-4133-b2de-54aefbdd7149",
|
|
||||||
"name": "autoAddAccounts",
|
|
||||||
"displayName": "Auto add accounts",
|
|
||||||
"displayNameEvent": "Auto add accounts",
|
|
||||||
"defaultValue": true,
|
|
||||||
"type": "bool"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -72,7 +56,8 @@
|
||||||
"name": "key",
|
"name": "key",
|
||||||
"displayName": "Key",
|
"displayName": "Key",
|
||||||
"defaultValue": "",
|
"defaultValue": "",
|
||||||
"type": "QString"
|
"type": "QString",
|
||||||
|
"readOnly": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"stateTypes": [
|
"stateTypes": [
|
||||||
|
|
@ -90,11 +75,11 @@
|
||||||
"name": "status",
|
"name": "status",
|
||||||
"displayName": "Status",
|
"displayName": "Status",
|
||||||
"displayNameEvent": "Status changed",
|
"displayNameEvent": "Status changed",
|
||||||
"defaultValue": "OPEN",
|
"defaultValue": "Open",
|
||||||
"possibleValues": [
|
"possibleValues": [
|
||||||
"OPEN",
|
"Open",
|
||||||
"CLOSED",
|
"Closed",
|
||||||
"ARCHIVED"
|
"Archived"
|
||||||
],
|
],
|
||||||
"type": "QString"
|
"type": "QString"
|
||||||
},
|
},
|
||||||
|
|
@ -152,8 +137,8 @@
|
||||||
"displayName": "Total time spent",
|
"displayName": "Total time spent",
|
||||||
"displayNameEvent": "Total time spent changed",
|
"displayNameEvent": "Total time spent changed",
|
||||||
"defaultValue": 0,
|
"defaultValue": 0,
|
||||||
"type": "uint",
|
"type": "double",
|
||||||
"unit": "Minutes"
|
"unit": "Hours"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "81bec4e8-9fd3-43d1-b339-2a7fdd83e8cb",
|
"id": "81bec4e8-9fd3-43d1-b339-2a7fdd83e8cb",
|
||||||
|
|
@ -161,8 +146,8 @@
|
||||||
"displayName": "This month time spent",
|
"displayName": "This month time spent",
|
||||||
"displayNameEvent": "This month time spent changed",
|
"displayNameEvent": "This month time spent changed",
|
||||||
"defaultValue": 0,
|
"defaultValue": 0,
|
||||||
"type": "uint",
|
"type": "double",
|
||||||
"unit": "Minutes"
|
"unit": "Hours"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -178,7 +163,8 @@
|
||||||
"name": "id",
|
"name": "id",
|
||||||
"displayName": "Id",
|
"displayName": "Id",
|
||||||
"defaultValue": 0,
|
"defaultValue": 0,
|
||||||
"type": "int"
|
"type": "int",
|
||||||
|
"readOnly": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"stateTypes": [
|
"stateTypes": [
|
||||||
|
|
@ -190,6 +176,23 @@
|
||||||
"defaultValue": true,
|
"defaultValue": true,
|
||||||
"cached": false,
|
"cached": false,
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "667a9d8d-4e80-4c7c-938c-d698853fa4b1",
|
||||||
|
"name": "lead",
|
||||||
|
"displayName": "Lead",
|
||||||
|
"displayNameEvent": "Lead changed",
|
||||||
|
"defaultValue": "",
|
||||||
|
"type": "QString"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "a694682e-3c2a-4146-aa56-9e75fd82bcab",
|
||||||
|
"name": "totalTimeSpent",
|
||||||
|
"displayName": "Total time spent",
|
||||||
|
"displayNameEvent": "Total time spent changed",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"type": "double",
|
||||||
|
"unit": "Hours"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,15 +134,24 @@ void Tempo::getAccounts()
|
||||||
account.lead.self = lead["self"].toString();
|
account.lead.self = lead["self"].toString();
|
||||||
account.lead.accountId = lead["accountId"].toString();
|
account.lead.accountId = lead["accountId"].toString();
|
||||||
account.lead.displayName = lead["displayName"].toString();
|
account.lead.displayName = lead["displayName"].toString();
|
||||||
//TODO Customer
|
|
||||||
QVariantMap customer = map["customer"].toMap();
|
QVariantMap customer = map["customer"].toMap();
|
||||||
account.customer.self = lead["self"].toString();
|
account.customer.self = customer["self"].toString();
|
||||||
//TODO Category
|
account.customer.key = customer["key"].toString();
|
||||||
|
account.customer.id = customer["id"].toInt();
|
||||||
|
account.customer.name = customer["name"].toString();
|
||||||
|
|
||||||
QVariantMap category = map["category"].toMap();
|
QVariantMap category = map["category"].toMap();
|
||||||
account.category.self = lead["self"].toString();
|
account.category.self = category["self"].toString();
|
||||||
//TODO Contact
|
account.category.key = category["key"].toString();
|
||||||
|
account.category.name = category["name"].toString();
|
||||||
|
account.category.id = category["id"].toInt();
|
||||||
|
|
||||||
QVariantMap contact = map["contact"].toMap();
|
QVariantMap contact = map["contact"].toMap();
|
||||||
account.contact.self = lead["self"].toString();
|
account.contact.self = contact["self"].toString();
|
||||||
|
account.contact.type = contact["type"].toString();
|
||||||
|
account.contact.accountId = contact["accountId"].toString();
|
||||||
|
account.contact.displayName = contact["displayName"].toString();
|
||||||
|
|
||||||
accounts.append(account);
|
accounts.append(account);
|
||||||
}
|
}
|
||||||
|
|
@ -152,12 +161,14 @@ void Tempo::getAccounts()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tempo::getWorkloadByAccount(const QString &accountKey, QDate from, QDate to)
|
void Tempo::getWorkloadByAccount(const QString &accountKey, QDate from, QDate to, int offset, int limit)
|
||||||
{
|
{
|
||||||
QUrl url = QUrl(m_baseControlUrl+"/worklogs/account/"+accountKey);
|
QUrl url = QUrl(m_baseControlUrl+"/worklogs/account/"+accountKey);
|
||||||
QUrlQuery query;
|
QUrlQuery query;
|
||||||
query.addQueryItem("from", from.toString(Qt::DateFormat::ISODate));
|
query.addQueryItem("from", from.toString(Qt::DateFormat::ISODate));
|
||||||
query.addQueryItem("to", to.toString(Qt::DateFormat::ISODate));
|
query.addQueryItem("to", to.toString(Qt::DateFormat::ISODate));
|
||||||
|
query.addQueryItem("offset", QString::number(offset));
|
||||||
|
query.addQueryItem("limit", QString::number(limit));
|
||||||
url.setQuery(query);
|
url.setQuery(query);
|
||||||
|
|
||||||
qCDebug(dcTempo()) << "Get workload by account. Url" << url.toString();
|
qCDebug(dcTempo()) << "Get workload by account. Url" << url.toString();
|
||||||
|
|
@ -174,30 +185,41 @@ void Tempo::getWorkloadByAccount(const QString &accountKey, QDate from, QDate to
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
||||||
QVariantList worklogList = dataMap.value("results").toList();
|
QList<Worklog> worklogs = parseJsonForWorklog(dataMap);
|
||||||
QList<Worklog> worklogs;
|
|
||||||
Q_FOREACH(QVariant var, worklogList) {
|
|
||||||
QVariantMap map = var.toMap();
|
|
||||||
Worklog worklog;
|
|
||||||
worklog.self = map["self"].toString();
|
|
||||||
worklog.tempoWorklogId = map["tempoWorklogId"].toInt();
|
|
||||||
worklog.jiraWorklogId = map["jiraWorklogId"].toInt();
|
|
||||||
worklog.issue = map["issue"].toMap().value("key").toString();
|
|
||||||
worklog.timeSpentSeconds = map["timeSpentSeconds"].toInt();
|
|
||||||
//TODO startDate: required (date-only)
|
|
||||||
//TODO startTime: required (time-only)
|
|
||||||
worklog.description = map["description"].toString();
|
|
||||||
//TODO createdAt: required (datetime)
|
|
||||||
//TODO updatedAt: required (datetime)
|
|
||||||
worklog.authorAccountId = map["author"].toMap().value("accountId").toString();
|
|
||||||
worklog.authorDisplayName = map["author"].toMap().value("displayName").toString();
|
|
||||||
worklogs.append(worklog);
|
|
||||||
}
|
|
||||||
if (!worklogs.isEmpty())
|
if (!worklogs.isEmpty())
|
||||||
emit accountWorklogsReceived(accountKey, worklogs);
|
emit accountWorklogsReceived(accountKey, worklogs);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tempo::getWorkloadByTeam(int teamId, QDate from, QDate to, int offset, int limit)
|
||||||
|
{
|
||||||
|
QUrl url = QUrl(m_baseControlUrl+"/worklogs/team/"+QString::number(teamId));
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem("from", from.toString(Qt::DateFormat::ISODate));
|
||||||
|
query.addQueryItem("to", to.toString(Qt::DateFormat::ISODate));
|
||||||
|
query.addQueryItem("offset", QString::number(offset));
|
||||||
|
query.addQueryItem("limit", QString::number(limit));
|
||||||
|
url.setQuery(query);
|
||||||
|
|
||||||
|
qCDebug(dcTempo()) << "Get workload by account. Url" << url.toString();
|
||||||
|
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
request.setRawHeader("Authorization", "Bearer "+m_token.toUtf8());
|
||||||
|
|
||||||
|
QNetworkReply *reply = m_networkManager->get(request);
|
||||||
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, teamId, reply]{
|
||||||
|
QByteArray rawData = reply->readAll();
|
||||||
|
if (!checkStatusCode(reply, rawData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap();
|
||||||
|
QList<Worklog> worklogs = parseJsonForWorklog(dataMap);
|
||||||
|
if (!worklogs.isEmpty())
|
||||||
|
emit teamWorklogsReceived(teamId, worklogs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Tempo::setAuthenticated(bool state)
|
void Tempo::setAuthenticated(bool state)
|
||||||
{
|
{
|
||||||
if (state != m_authenticated) {
|
if (state != m_authenticated) {
|
||||||
|
|
@ -214,6 +236,30 @@ void Tempo::setConnected(bool state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<Tempo::Worklog> Tempo::parseJsonForWorklog(const QVariantMap &data)
|
||||||
|
{
|
||||||
|
QVariantList worklogList = data.value("results").toList();
|
||||||
|
QList<Worklog> worklogs;
|
||||||
|
Q_FOREACH(QVariant var, worklogList) {
|
||||||
|
QVariantMap map = var.toMap();
|
||||||
|
Worklog worklog;
|
||||||
|
worklog.self = map["self"].toString();
|
||||||
|
worklog.tempoWorklogId = map["tempoWorklogId"].toInt();
|
||||||
|
worklog.jiraWorklogId = map["jiraWorklogId"].toInt();
|
||||||
|
worklog.issue = map["issue"].toMap().value("key").toString();
|
||||||
|
worklog.timeSpentSeconds = map["timeSpentSeconds"].toInt();
|
||||||
|
//TODO startDate: required (date-only)
|
||||||
|
//TODO startTime: required (time-only)
|
||||||
|
worklog.description = map["description"].toString();
|
||||||
|
worklog.createdAt = QDateTime::fromString(map["createdAt"].toString(), Qt::ISODate);
|
||||||
|
worklog.updatedAt = QDateTime::fromString(map["updatedAt"].toString(), Qt::ISODate);
|
||||||
|
worklog.authorAccountId = map["author"].toMap().value("accountId").toString();
|
||||||
|
worklog.authorDisplayName = map["author"].toMap().value("displayName").toString();
|
||||||
|
worklogs.append(worklog);
|
||||||
|
}
|
||||||
|
return worklogs;
|
||||||
|
}
|
||||||
|
|
||||||
bool Tempo::checkStatusCode(QNetworkReply *reply, const QByteArray &rawData)
|
bool Tempo::checkStatusCode(QNetworkReply *reply, const QByteArray &rawData)
|
||||||
{
|
{
|
||||||
// Check for the internet connection
|
// Check for the internet connection
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,9 @@ public:
|
||||||
|
|
||||||
struct Category {
|
struct Category {
|
||||||
QUrl self;
|
QUrl self;
|
||||||
QString accountId;
|
QString key;
|
||||||
QString displayName;
|
int id;
|
||||||
|
QString name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Customer {
|
struct Customer {
|
||||||
|
|
@ -116,11 +117,11 @@ public:
|
||||||
|
|
||||||
void getTeams();
|
void getTeams();
|
||||||
void getAccounts();
|
void getAccounts();
|
||||||
void getWorkloadByAccount(const QString &accountKey, QDate from, QDate to);
|
void getWorkloadByAccount(const QString &accountKey, QDate from, QDate to, int offset = 0, int limit = 50);
|
||||||
|
void getWorkloadByTeam(int teamId, QDate from, QDate to, int offset = 0, int limit = 50);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QByteArray m_baseTokenUrl = "https://api.tempo.io/oauth/token/";
|
QByteArray m_baseControlUrl = "https://api.tempo.io/core/3";
|
||||||
QByteArray m_baseControlUrl = "https://api.tempo.io/core/3/";
|
|
||||||
QString m_token;
|
QString m_token;
|
||||||
QString m_jiraCloudInstanceName;
|
QString m_jiraCloudInstanceName;
|
||||||
|
|
||||||
|
|
@ -132,6 +133,7 @@ private:
|
||||||
bool m_authenticated = false;
|
bool m_authenticated = false;
|
||||||
bool m_connected = false;
|
bool m_connected = false;
|
||||||
|
|
||||||
|
QList<Worklog> parseJsonForWorklog(const QVariantMap &data);
|
||||||
bool checkStatusCode(QNetworkReply *reply, const QByteArray &rawData);
|
bool checkStatusCode(QNetworkReply *reply, const QByteArray &rawData);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
@ -143,6 +145,7 @@ signals:
|
||||||
void teamsReceived(const QList<Team> teams);
|
void teamsReceived(const QList<Team> teams);
|
||||||
void accountsReceived(const QList<Account> accounts);
|
void accountsReceived(const QList<Account> accounts);
|
||||||
void accountWorklogsReceived(const QString &accountKey, QList<Worklog> worklogs);
|
void accountWorklogsReceived(const QString &accountKey, QList<Worklog> worklogs);
|
||||||
|
void teamWorklogsReceived(int teamId, QList<Worklog> worklogs);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TEMPO_H
|
#endif // TEMPO_H
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue