From 813c59ccccce4c7b9d095d67a6f718355db60af2 Mon Sep 17 00:00:00 2001 From: "d.kislov" Date: Wed, 15 Apr 2020 12:21:21 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B3=D0=B0=D0=BB=D0=BA=D1=83=20=D0=BD=D0=B0=20=D1=83=D0=B4?= =?UTF-8?q?=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=D0=BD=D0=B5=D1=81?= =?UTF-8?q?=D1=91=D0=BD=D0=BD=D1=8B=D1=85=20=D1=80=D1=83=D0=BA=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8=20=D0=B2=D0=BE=D1=80=D0=BA=D0=BB=D0=BE=D0=B3=D0=BE=D0=B2?= =?UTF-8?q?,=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2=D0=BE=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20Estimate=20(=D0=BD=D0=B5?= =?UTF-8?q?=20=D1=84=D0=B0=D0=BA=D1=82=20=D1=87=D1=82=D0=BE=20=D0=B2=D0=B7?= =?UTF-8?q?=D0=BB=D0=B5=D1=82=D0=B8=D1=82).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .semver.txt | 2 +- src/JiraTimeBot/Configuration/Settings.cs | 1 + src/JiraTimeBot/DI/ContainerBuilder.cs | 3 +- src/JiraTimeBot/JiraIntegration/JiraApi.cs | 34 ++++++++-- src/JiraTimeBot/JiraTimeBot.csproj | 2 +- src/JiraTimeBot/Job.cs | 30 +++++++-- src/JiraTimeBot/Properties/AssemblyInfo.cs | 62 +++++++++---------- .../JiraCommitEmulator.cs | 14 ++--- src/JiraTimeBot/UI/frmSettings.Designer.cs | 19 +++++- src/JiraTimeBot/UI/frmSettings.cs | 4 +- 10 files changed, 117 insertions(+), 54 deletions(-) rename src/JiraTimeBot/{JiraIntegration => RepositoryProviders}/JiraCommitEmulator.cs (96%) diff --git a/.semver.txt b/.semver.txt index 224d004..53fe5d6 100644 --- a/.semver.txt +++ b/.semver.txt @@ -1 +1 @@ -1.0.82 +1.0.83 diff --git a/src/JiraTimeBot/Configuration/Settings.cs b/src/JiraTimeBot/Configuration/Settings.cs index cd75d4b..358533d 100644 --- a/src/JiraTimeBot/Configuration/Settings.cs +++ b/src/JiraTimeBot/Configuration/Settings.cs @@ -14,6 +14,7 @@ namespace JiraTimeBot.Configuration public string JiraUrl { get; set; } public bool PullBeforeProcess { get; set; } + public bool RemoveManuallyAddedWorklogs { get; set; } public string RepositoryPath { get; set; } public string MercurialAuthorEmail { get; set; } public string JiraUserName { get; set; } diff --git a/src/JiraTimeBot/DI/ContainerBuilder.cs b/src/JiraTimeBot/DI/ContainerBuilder.cs index e6b201a..5b25a6d 100644 --- a/src/JiraTimeBot/DI/ContainerBuilder.cs +++ b/src/JiraTimeBot/DI/ContainerBuilder.cs @@ -61,7 +61,8 @@ namespace JiraTimeBot.DI _builder.RegisterType().AsSelf().As(); - _builder.Register(c => new Job(c.Resolve(), c.Resolve(), c.Resolve())).AsSelf(); + _builder.Register(c => new Job(c.Resolve(), c.Resolve(), + c.Resolve(), c.Resolve())).AsSelf(); _builder.RegisterType().AsSelf().AsImplementedInterfaces(); _builder.RegisterType().AsSelf().AsImplementedInterfaces(); diff --git a/src/JiraTimeBot/JiraIntegration/JiraApi.cs b/src/JiraTimeBot/JiraIntegration/JiraApi.cs index 65b4fee..355993f 100644 --- a/src/JiraTimeBot/JiraIntegration/JiraApi.cs +++ b/src/JiraTimeBot/JiraIntegration/JiraApi.cs @@ -15,6 +15,7 @@ namespace JiraTimeBot.JiraIntegration string GetTaskName(string branch, Settings settings); List GetWorkloggedIssuesByDate(Settings settings, DateTime? date = null, CancellationToken cancellationToken = default); void SetTodayWorklog(List taskTimeItems, Settings settings, DateTime? date = null, bool dummy = false, bool addCommentsToWorklog = false, CancellationToken cancellationToken = default); + List GetManuallyWorklogged(List taskTimeItems, Settings settings, DateTime? date, CancellationToken cancellationToken = default); } public class JiraApi : IJiraApi @@ -77,6 +78,28 @@ namespace JiraTimeBot.JiraIntegration return GetIssuesByJQL(jql, settings, date, cancellationToken); } + public List GetManuallyWorklogged(List taskTimeItems, Settings settings, DateTime? date, CancellationToken cancellationToken = default) + { + var result = new List(); + var alreadyLoggedToday = GetWorkloggedIssuesByDate(settings, date); + foreach (var issue in alreadyLoggedToday) + { + if (!taskTimeItems.Any(f => f.Branch.Equals(issue.Key.Value, StringComparison.InvariantCulture))) + { + var workLogs = issue.GetWorklogsAsync(cancellationToken).Result; + var userWorklogs = workLogs.Where(w => + w.StartDate.GetValueOrDefault().Date == date && w.Author.Equals(settings.JiraUserName, + StringComparison.InvariantCultureIgnoreCase)).ToList(); + foreach (var userWorklog in userWorklogs) + { + result.Add(userWorklog); + } + } + } + + return result; + } + private void RemoveWorklogsAddedByUser(List taskTimeItems, Settings settings, DateTime? date = null, bool dummy = false, CancellationToken cancellationToken = default) { var alreadyLoggedToday = GetWorkloggedIssuesByDate(settings, date); @@ -106,8 +129,11 @@ namespace JiraTimeBot.JiraIntegration date = date.GetValueOrDefault(DateTime.Now.Date).Date; var jira = Jira.CreateRestClient(settings.JiraUrl, settings.JiraUserName, settings.JiraPassword); - //Удаляем добавленные вручную пользователем данные. - RemoveWorklogsAddedByUser(taskTimeItems, settings, date, dummy, cancellationToken); + if (settings.RemoveManuallyAddedWorklogs) + { + //Удаляем добавленные вручную пользователем данные. + RemoveWorklogsAddedByUser(taskTimeItems, settings, date, dummy, cancellationToken); + } foreach (TaskTimeItem taskTimeItem in taskTimeItems) { @@ -155,7 +181,7 @@ namespace JiraTimeBot.JiraIntegration { try { - issue.DeleteWorklogAsync(workLog, WorklogStrategy.RetainRemainingEstimate, token: cancellationToken); + issue.DeleteWorklogAsync(workLog, WorklogStrategy.AutoAdjustRemainingEstimate, token: cancellationToken); } catch (Exception ex) { @@ -181,7 +207,7 @@ namespace JiraTimeBot.JiraIntegration { try { - workLogToAdd = issue.AddWorklogAsync(workLogToAdd, WorklogStrategy.RetainRemainingEstimate, token: cancellationToken).Result; + workLogToAdd = issue.AddWorklogAsync(workLogToAdd, WorklogStrategy.AutoAdjustRemainingEstimate, token: cancellationToken).Result; } catch (Exception ex) { diff --git a/src/JiraTimeBot/JiraTimeBot.csproj b/src/JiraTimeBot/JiraTimeBot.csproj index d05acc9..e7abfbf 100644 --- a/src/JiraTimeBot/JiraTimeBot.csproj +++ b/src/JiraTimeBot/JiraTimeBot.csproj @@ -121,7 +121,7 @@ - + diff --git a/src/JiraTimeBot/Job.cs b/src/JiraTimeBot/Job.cs index 010aa15..05591dc 100644 --- a/src/JiraTimeBot/Job.cs +++ b/src/JiraTimeBot/Job.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using JiraTimeBot.JiraIntegration; namespace JiraTimeBot { @@ -15,12 +16,14 @@ namespace JiraTimeBot { private readonly IAllRepositoryProviders _mercurialProviders; private readonly ITaskTimeCalculator _taskTimeDiscoverer; + private readonly IJiraApi _jiraApi; private readonly ILog _log; - public Job(IAllRepositoryProviders mercurialProviders, ITaskTimeCalculator taskTimeDiscoverer, ILog log) + public Job(IAllRepositoryProviders mercurialProviders, ITaskTimeCalculator taskTimeDiscoverer, IJiraApi jiraApi, ILog log) { _mercurialProviders = mercurialProviders; _taskTimeDiscoverer = taskTimeDiscoverer; + _jiraApi = jiraApi; _log = log; } @@ -72,22 +75,23 @@ namespace JiraTimeBot private bool SetTaskTimesForDateImpl(DateTime setForDate, DateTime realDate, Settings settings, ITasksProcessor tasksProcessor, bool dummyMode, CancellationToken cancellationToken) { - IRepositoryLog mercurial = _mercurialProviders.MercurialLog; + IRepositoryLog repository = _mercurialProviders.MercurialLog; if (settings.WorkType == WorkType.JiraLogs) { _log.Info("Использую Jira как источник информации."); - mercurial = _mercurialProviders.JiraCommitEmulator; + repository = _mercurialProviders.JiraCommitEmulator; } else if (settings.WorkType == WorkType.GitLogs) { _log.Info("Использую Git как источник информации."); - mercurial = _mercurialProviders.GitLog; + repository = _mercurialProviders.GitLog; } List taskTimes; if (!(tasksProcessor is MeetingProcessor)) { - List commits = mercurial.GetRepositoryLog(settings, realDate, cancellationToken); + List commits = repository.GetRepositoryLog(settings, realDate, cancellationToken); + ModifyWorktimeByManualLogs(setForDate, settings, cancellationToken, commits); taskTimes = _taskTimeDiscoverer.CalculateTaskTime(commits, settings, cancellationToken); } else @@ -111,5 +115,21 @@ namespace JiraTimeBot _log.Info("Готово."); return true; } + + private void ModifyWorktimeByManualLogs(DateTime setForDate, Settings settings, CancellationToken cancellationToken, + List commits) + { + if (settings.RemoveManuallyAddedWorklogs) + { + return; + } + + //если не удаляем добавленное вручную, то посчитаем сколько там надобавляли и отнимем от рабочего дня + var manuallyWorklogged = _jiraApi.GetManuallyWorklogged(commits, settings, setForDate, cancellationToken); + if (manuallyWorklogged.Any() && manuallyWorklogged.Sum(f => f.TimeSpentInSeconds) < settings.MinuterPerWorkDay) + { + settings.MinuterPerWorkDay = (int) (settings.MinuterPerWorkDay - manuallyWorklogged.Sum(f => f.TimeSpentInSeconds)); + } + } } } diff --git a/src/JiraTimeBot/Properties/AssemblyInfo.cs b/src/JiraTimeBot/Properties/AssemblyInfo.cs index 1914cff..6e39233 100644 --- a/src/JiraTimeBot/Properties/AssemblyInfo.cs +++ b/src/JiraTimeBot/Properties/AssemblyInfo.cs @@ -1,31 +1,31 @@ -using System.Reflection; -using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("JiraTimeBot")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("JiraTimeBot")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f3b89316-c38c-4ce6-9d88-0b1373cfba1a")] -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.82")] -[assembly: AssemblyFileVersion("1.0.82")] -[assembly: AssemblyInformationalVersion("1.0.82")] +using System.Reflection; +using System.Runtime.InteropServices; +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("JiraTimeBot")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("JiraTimeBot")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f3b89316-c38c-4ce6-9d88-0b1373cfba1a")] +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.83")] +[assembly: AssemblyFileVersion("1.0.83")] +[assembly: AssemblyInformationalVersion("1.0.83")] diff --git a/src/JiraTimeBot/JiraIntegration/JiraCommitEmulator.cs b/src/JiraTimeBot/RepositoryProviders/JiraCommitEmulator.cs similarity index 96% rename from src/JiraTimeBot/JiraIntegration/JiraCommitEmulator.cs rename to src/JiraTimeBot/RepositoryProviders/JiraCommitEmulator.cs index 213f2ac..34417c6 100644 --- a/src/JiraTimeBot/JiraIntegration/JiraCommitEmulator.cs +++ b/src/JiraTimeBot/RepositoryProviders/JiraCommitEmulator.cs @@ -1,14 +1,14 @@ -using Atlassian.Jira; -using JiraTimeBot.Configuration; -using JiraTimeBot.RepositoryProviders.Interfaces; -using JiraTimeBot.TaskTime.Objects; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; +using Atlassian.Jira; +using JiraTimeBot.Configuration; +using JiraTimeBot.JiraIntegration; +using JiraTimeBot.RepositoryProviders.Interfaces; +using JiraTimeBot.TaskTime.Objects; - -namespace JiraTimeBot.JiraIntegration +namespace JiraTimeBot.RepositoryProviders { public class JiraCommitEmulator : IRepositoryLog { diff --git a/src/JiraTimeBot/UI/frmSettings.Designer.cs b/src/JiraTimeBot/UI/frmSettings.Designer.cs index ec85422..a2afb6a 100644 --- a/src/JiraTimeBot/UI/frmSettings.Designer.cs +++ b/src/JiraTimeBot/UI/frmSettings.Designer.cs @@ -56,6 +56,7 @@ this.label4 = new System.Windows.Forms.Label(); this.lblJiraUrl = new System.Windows.Forms.Label(); this.txtJiraUrl = new System.Windows.Forms.TextBox(); + this.chkRemoveManuallyAddedWorklogs = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // // label5 @@ -154,7 +155,7 @@ // // btnSave // - this.btnSave.Location = new System.Drawing.Point(86, 412); + this.btnSave.Location = new System.Drawing.Point(86, 432); this.btnSave.Name = "btnSave"; this.btnSave.Size = new System.Drawing.Size(75, 23); this.btnSave.TabIndex = 32; @@ -262,7 +263,7 @@ // chkPullBeforeProcess // this.chkPullBeforeProcess.AutoSize = true; - this.chkPullBeforeProcess.Location = new System.Drawing.Point(65, 389); + this.chkPullBeforeProcess.Location = new System.Drawing.Point(65, 409); this.chkPullBeforeProcess.Name = "chkPullBeforeProcess"; this.chkPullBeforeProcess.Size = new System.Drawing.Size(83, 17); this.chkPullBeforeProcess.TabIndex = 45; @@ -303,11 +304,22 @@ this.txtJiraUrl.Size = new System.Drawing.Size(100, 20); this.txtJiraUrl.TabIndex = 46; // + // chkRemoveManuallyAddedWorklogs + // + this.chkRemoveManuallyAddedWorklogs.AutoSize = true; + this.chkRemoveManuallyAddedWorklogs.Location = new System.Drawing.Point(65, 387); + this.chkRemoveManuallyAddedWorklogs.Name = "chkRemoveManuallyAddedWorklogs"; + this.chkRemoveManuallyAddedWorklogs.Size = new System.Drawing.Size(157, 17); + this.chkRemoveManuallyAddedWorklogs.TabIndex = 48; + this.chkRemoveManuallyAddedWorklogs.Text = "Удалять \"ручные записи\""; + this.chkRemoveManuallyAddedWorklogs.UseVisualStyleBackColor = true; + // // frmSettings // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(243, 442); + this.ClientSize = new System.Drawing.Size(243, 467); + this.Controls.Add(this.chkRemoveManuallyAddedWorklogs); this.Controls.Add(this.lblJiraUrl); this.Controls.Add(this.txtJiraUrl); this.Controls.Add(this.chkPullBeforeProcess); @@ -377,5 +389,6 @@ private System.Windows.Forms.Label label4; private System.Windows.Forms.Label lblJiraUrl; private System.Windows.Forms.TextBox txtJiraUrl; + private System.Windows.Forms.CheckBox chkRemoveManuallyAddedWorklogs; } } \ No newline at end of file diff --git a/src/JiraTimeBot/UI/frmSettings.cs b/src/JiraTimeBot/UI/frmSettings.cs index 74f72d7..524c340 100644 --- a/src/JiraTimeBot/UI/frmSettings.cs +++ b/src/JiraTimeBot/UI/frmSettings.cs @@ -42,6 +42,7 @@ namespace JiraTimeBot.UI txtWorkDayDuration.Text = settings.MinuterPerWorkDay.ToString(); txtRandomMinutes.Text = settings.RandomWorkMinutes.ToString(); chkPullBeforeProcess.Checked = settings.PullBeforeProcess; + chkRemoveManuallyAddedWorklogs.Checked = settings.RemoveManuallyAddedWorklogs; cboWorkType_SelectedIndexChanged(null, null); } @@ -76,7 +77,8 @@ namespace JiraTimeBot.UI TimeControlTask = txtTimeControlTask.Text, MinuterPerWorkDay = minuterPerWorkDay, RandomWorkMinutes = randomWorkMinutes, - PullBeforeProcess = chkPullBeforeProcess.Checked + PullBeforeProcess = chkPullBeforeProcess.Checked, + RemoveManuallyAddedWorklogs = chkRemoveManuallyAddedWorklogs.Checked }; //LockUnlock(false);