diff --git a/cypress/e2e/02_repositories.cy.ts b/cypress/e2e/02_repositories.cy.ts new file mode 100644 index 000000000..dba204270 --- /dev/null +++ b/cypress/e2e/02_repositories.cy.ts @@ -0,0 +1,40 @@ +import { User, HostName, Workspaces, Repositories } from '../support/objects/objects'; + + +describe('Create Repositories for Workspace', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + for(let i = 0; i <= 1; i++) { + cy.request({ + method: 'POST', + url: `${HostName}/workspaces/repositories`, + headers: { 'x-jwt': `${value}` }, + body: Repositories[i] + }).its('body').then(body => { + expect(body).to.have.property('name').and.equal(Repositories[i].name.trim()); + expect(body).to.have.property('url').and.equal(Repositories[i].url.trim()); + }); + } + }) + }) +}) + + +describe('Check Repositories Values', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + cy.request({ + method: 'GET', + url: `${HostName}/workspaces/repositories/` + Repositories[0].workspace_uuid, + headers: { 'x-jwt': `${ value }` }, + body: {} + }).then((resp) => { + expect(resp.status).to.eq(200) + expect(resp.body[0]).to.have.property('name', Repositories[0].name.trim()) + expect(resp.body[0]).to.have.property('url', Repositories[0].url.trim()) + expect(resp.body[1]).to.have.property('name', Repositories[1].name.trim()) + expect(resp.body[1]).to.have.property('url', Repositories[1].url.trim()) + }) + }) + }) +}) diff --git a/cypress/e2e/03_features.cy.ts b/cypress/e2e/03_features.cy.ts index f5f135560..0e268c6a2 100644 --- a/cypress/e2e/03_features.cy.ts +++ b/cypress/e2e/03_features.cy.ts @@ -1,20 +1,22 @@ -import { User, HostName, Workspaces, Repositories, Features } from '../support/objects/objects'; +import { User, HostName, Features } from '../support/objects/objects'; describe('Create Features for Workspace', () => { it('passes', () => { cy.upsertlogin(User).then(value => { - for(let i = 0; i <= 2; i++) { + for (let i = 0; i <= 2; i++) { cy.request({ method: 'POST', url: `${HostName}/features`, headers: { 'x-jwt': `${value}` }, body: Features[i] - }).its('body').should('have.property', 'name', Features[i].name.trim()) - .its('body').should('have.property', 'brief', Features[i].brief.trim()) - .its('body').should('have.property', 'requirements', Features[i].requirements.trim()) - .its('body').should('have.property', 'architecture', Features[i].architecture.trim()) + }).its('body').then(body => { + expect(body).to.have.property('name').and.equal(Features[i].name.trim()); + expect(body).to.have.property('brief').and.equal(Features[i].brief.trim()); + expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim()); + expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim()); + }); } }) }) @@ -23,7 +25,7 @@ describe('Create Features for Workspace', () => { describe('Modify name for Feature', () => { it('passes', () => { cy.upsertlogin(User).then(value => { - for(let i = 0; i <= 2; i++) { + for (let i = 0; i <= 2; i++) { cy.request({ method: 'POST', url: `${HostName}/features`, @@ -32,10 +34,12 @@ describe('Modify name for Feature', () => { uuid: Features[i].uuid, name: Features[i].name + "_addtext" } - }).its('body').should('have.property', 'name', Features[i].name.trim() + "_addtext") - .its('body').should('have.property', 'brief', Features[i].brief.trim()) - .its('body').should('have.property', 'requirements', Features[i].requirements.trim()) - .its('body').should('have.property', 'architecture', Features[i].architecture.trim()) + }).its('body').then(body => { + expect(body).to.have.property('name').and.equal(Features[i].name.trim() + " _addtext"); + expect(body).to.have.property('brief').and.equal(Features[i].brief.trim()); + expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim()); + expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim()); + }); } }) }) @@ -44,7 +48,7 @@ describe('Modify name for Feature', () => { describe('Modify brief for Feature', () => { it('passes', () => { cy.upsertlogin(User).then(value => { - for(let i = 0; i <= 2; i++) { + for (let i = 0; i <= 2; i++) { cy.request({ method: 'POST', url: `${HostName}/features`, @@ -53,10 +57,12 @@ describe('Modify brief for Feature', () => { uuid: Features[i].uuid, brief: Features[i].brief + "_addtext" } - }).its('body').should('have.property', 'name', Features[i].name.trim() + "_addtext") - .its('body').should('have.property', 'brief', Features[i].brief.trim() + "_addtext") - .its('body').should('have.property', 'requirements', Features[i].requirements.trim()) - .its('body').should('have.property', 'architecture', Features[i].architecture.trim()) + }).its('body').then(body => { + expect(body).to.have.property('name').and.equal(Features[i].name.trim() + " _addtext"); + expect(body).to.have.property('brief').and.equal(Features[i].brief.trim() + " _addtext"); + expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim()); + expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim()); + }); } }) }) @@ -65,7 +71,7 @@ describe('Modify brief for Feature', () => { describe('Modify requirements for Feature', () => { it('passes', () => { cy.upsertlogin(User).then(value => { - for(let i = 0; i <= 2; i++) { + for (let i = 0; i <= 2; i++) { cy.request({ method: 'POST', url: `${HostName}/features`, @@ -74,10 +80,12 @@ describe('Modify requirements for Feature', () => { uuid: Features[i].uuid, requirements: Features[i].requirements + "_addtext" } - }).its('body').should('have.property', 'name', Features[i].name.trim() + "_addtext") - .its('body').should('have.property', 'brief', Features[i].brief.trim() + "_addtext") - .its('body').should('have.property', 'requirements', Features[i].requirements.trim() + "_addtext") - .its('body').should('have.property', 'architecture', Features[i].architecture.trim()) + }).its('body').then(body => { + expect(body).to.have.property('name').and.equal(Features[i].name.trim() + " _addtext"); + expect(body).to.have.property('brief').and.equal(Features[i].brief.trim() + " _addtext"); + expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim() + " _addtext"); + expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim()); + }); } }) }) @@ -86,7 +94,7 @@ describe('Modify requirements for Feature', () => { describe('Modify architecture for Feature', () => { it('passes', () => { cy.upsertlogin(User).then(value => { - for(let i = 0; i <= 2; i++) { + for (let i = 0; i <= 2; i++) { cy.request({ method: 'POST', url: `${HostName}/features`, @@ -95,10 +103,12 @@ describe('Modify architecture for Feature', () => { uuid: Features[i].uuid, architecture: Features[i].architecture + "_addtext" } - }).its('body').should('have.property', 'name', Features[i].name.trim() + "_addtext") - .its('body').should('have.property', 'brief', Features[i].brief.trim() + "_addtext") - .its('body').should('have.property', 'requirements', Features[i].requirements.trim() + "_addtext") - .its('body').should('have.property', 'architecture', Features[i].architecture.trim() + "_addtext") + }).its('body').then(body => { + expect(body).to.have.property('name').and.equal(Features[i].name.trim() + " _addtext"); + expect(body).to.have.property('brief').and.equal(Features[i].brief.trim() + " _addtext"); + expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim() + " _addtext"); + expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim() + " _addtext"); + }); } }) }) @@ -110,37 +120,62 @@ describe('Get Features for Workspace', () => { cy.upsertlogin(User).then(value => { cy.request({ method: 'GET', - url: `${HostName}/workspaces/${Features[0].workspace_uuid}/features`, //changed from url: `${HostName}/features/forworkspace/` + Features[0].workspace_uuid, please update the routes file and any other change needed. + url: `${HostName}/workspaces/${Features[0].workspace_uuid}/features`, headers: { 'x-jwt': `${ value }` }, - body: {} + body: {} }).then((resp) => { expect(resp.status).to.eq(200) - for(let i = 0; i <= 2; i++) { - expect(resp.body[i]).to.have.property('name', Features[i].name.trim() + "_addtext") - expect(resp.body[i]).to.have.property('brief', Features[i].brief.trim() + "_addtext") - expect(resp.body[i]).to.have.property('requirements', Features[i].requirements.trim() + "_addtext") - expect(resp.body[i]).to.have.property('architecture', Features[i].architecture.trim() + "_addtext") - } + resp.body.forEach((feature) => { + const expectedFeature = Features.find(f => f.uuid === feature.uuid); + expect(feature).to.have.property('name', expectedFeature.name.trim() + " _addtext"); + expect(feature).to.have.property('brief', expectedFeature.brief.trim() + " _addtext"); + expect(feature).to.have.property('requirements', expectedFeature.requirements.trim() + " _addtext"); + expect(feature).to.have.property('architecture', expectedFeature.architecture.trim() + " _addtext"); + }); }) }) }) }) +describe('Old Get Features for Workspace', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + cy.request({ + method: 'GET', + url: `${HostName}/features/forworkspace/` + Features[0].workspace_uuid, + headers: { 'x-jwt': `${value}` }, + body: {} + }).then((resp) => { + expect(resp.status).to.eq(200); + if (resp.status === 200) { + resp.body.forEach((feature) => { + const expectedFeature = Features.find(f => f.uuid === feature.uuid); + expect(feature).to.have.property('name', expectedFeature.name.trim() + " _addtext"); + expect(feature).to.have.property('brief', expectedFeature.brief.trim() + " _addtext"); + expect(feature).to.have.property('requirements', expectedFeature.requirements.trim() + " _addtext"); + expect(feature).to.have.property('architecture', expectedFeature.architecture.trim() + " _addtext"); + }); + } + }); + }) + }) +}) + describe('Get Feature by uuid', () => { it('passes', () => { cy.upsertlogin(User).then(value => { - for(let i = 0; i <= 2; i++) { + for (let i = 0; i <= 2; i++) { cy.request({ method: 'GET', url: `${HostName}/features/`+ Features[i].uuid, headers: { 'x-jwt': `${ value }` }, - body: {} + body: {} }).then((resp) => { expect(resp.status).to.eq(200) - expect(resp.body).to.have.property('name', Features[i].name.trim() + "_addtext") - expect(resp.body).to.have.property('brief', Features[i].brief.trim() + "_addtext") - expect(resp.body).to.have.property('requirements', Features[i].requirements.trim() + "_addtext") - expect(resp.body).to.have.property('architecture', Features[i].architecture.trim() + "_addtext") + expect(resp.body).to.have.property('name', Features[i].name.trim() + " _addtext") + expect(resp.body).to.have.property('brief', Features[i].brief.trim() + " _addtext") + expect(resp.body).to.have.property('requirements', Features[i].requirements.trim() + " _addtext") + expect(resp.body).to.have.property('architecture', Features[i].architecture.trim() + " _addtext") }) } }) @@ -154,7 +189,7 @@ describe('Delete Feature by uuid', () => { method: 'DELETE', url: `${HostName}/features/${Features[0].uuid}`, headers: { 'x-jwt': `${ value }` }, - body: {} + body: {} }).then((resp) => { expect(resp.status).to.eq(200) }) @@ -166,10 +201,11 @@ describe('Check delete by uuid', () => { it('passes', () => { cy.upsertlogin(User).then(value => { cy.request({ - method: 'GET', + method: 'DELETE', url: `${HostName}/features/${Features[0].uuid}`, headers: { 'x-jwt': `${ value }` }, - body: {} + body: {}, + failOnStatusCode: false }).then((resp) => { expect(resp.status).to.eq(404); }) diff --git a/cypress/e2e/04_user_stories.cy.ts b/cypress/e2e/04_user_stories.cy.ts new file mode 100644 index 000000000..3bca14d24 --- /dev/null +++ b/cypress/e2e/04_user_stories.cy.ts @@ -0,0 +1,117 @@ +import { User, HostName, UserStories } from '../support/objects/objects'; + +describe('Create user stories for Feature', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + for (let i = 0; i <= 5; i++) { + cy.request({ + method: 'POST', + url: `${HostName}/features/story`, + headers: { 'x-jwt': `${value}` }, + body: UserStories[i] + }).its('body').then(body => { + expect(body).to.have.property('uuid').and.equal(UserStories[i].uuid.trim()); + expect(body).to.have.property('feature_uuid').and.equal(UserStories[i].feature_uuid.trim()); + expect(body).to.have.property('description').and.equal(UserStories[i].description.trim()); + expect(body).to.have.property('priority').and.equal(UserStories[i].priority); + }); + } + }) + }) +}) + +describe('Modify user story description', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + for (let i = 0; i <= 5; i++) { + cy.request({ + method: 'POST', + url: `${HostName}/features/story`, + headers: { 'x-jwt': `${value}` }, + body: { + uuid: UserStories[i].uuid, + description: UserStories[i].description + "_addtext" + } + }).its('body').then(body => { + expect(body).to.have.property('uuid').and.equal(UserStories[i].uuid.trim()); + expect(body).to.have.property('feature_uuid').and.equal(UserStories[i].feature_uuid.trim()); + expect(body).to.have.property('description').and.equal(UserStories[i].description.trim() + " _addtext"); + expect(body).to.have.property('priority').and.equal(UserStories[i].priority); + }); + } + }) + }) +}) + +describe('Get user stories for feature', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + cy.request({ + method: 'GET', + url: `${HostName}/features/${UserStories[0].feature_uuid}/story`, + headers: { 'x-jwt': `${value}` }, + body: {} + }).then((resp) => { + expect(resp.status).to.eq(200) + for (let i = 0; i <= 5; i++) { + expect(resp.body[i]).to.have.property('uuid').and.equal(UserStories[i].uuid.trim()); + expect(resp.body[i]).to.have.property('feature_uuid').and.equal(UserStories[i].feature_uuid.trim()); + expect(resp.body[i]).to.have.property('description').and.equal(UserStories[i].description.trim() + " _addtext"); + expect(resp.body[i]).to.have.property('priority').and.equal(UserStories[i].priority); + } + }) + }) + }) +}) + +describe('Get story by uuid', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + for (let i = 0; i <= 5; i++) { + cy.request({ + method: 'GET', + url: `${HostName}/features/${UserStories[0].feature_uuid}/story/${UserStories[i].uuid}`, + headers: { 'x-jwt': `${value}` }, + body: {} + }).then((resp) => { + expect(resp.status).to.eq(200); + expect(resp.body).to.have.property('uuid').and.equal(UserStories[i].uuid.trim()); + expect(resp.body).to.have.property('feature_uuid').and.equal(UserStories[i].feature_uuid.trim()); + expect(resp.body).to.have.property('description').and.equal(UserStories[i].description.trim() + " _addtext"); + expect(resp.body).to.have.property('priority').and.equal(UserStories[i].priority); + }); + } + }); + }); +}); + +describe('Delete story by uuid', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + cy.request({ + method: 'DELETE', + url: `${HostName}/features/${UserStories[0].feature_uuid}/story/${UserStories[0].uuid}`, + headers: { 'x-jwt': `${value}` }, + body: {} + }).then((resp) => { + expect(resp.status).to.eq(200) + }) + }) + }) +}) + +describe('Check delete by uuid', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + cy.request({ + method: 'DELETE', + url: `${HostName}/features/${UserStories[0].feature_uuid}/story/${UserStories[0].uuid}`, + headers: { 'x-jwt': `${value}` }, + body: {}, + failOnStatusCode: false + }).then((resp) => { + expect(resp.status).to.eq(404); + }) + }) + }) +}) diff --git a/cypress/e2e/05_phases.cy.ts b/cypress/e2e/05_phases.cy.ts new file mode 100644 index 000000000..bcc7dbd32 --- /dev/null +++ b/cypress/e2e/05_phases.cy.ts @@ -0,0 +1,120 @@ +import { User, HostName, UserStories, Phases } from '../support/objects/objects'; + +describe('Create Phases for Feature', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + for(let i = 0; i <= 2; i++) { + cy.request({ + method: 'POST', + url: `${HostName}/features/phase`, + headers: { 'x-jwt': `${value}` }, + body: Phases[i] + }).its('body').then(body => { + expect(body).to.have.property('uuid').and.equal(Phases[i].uuid.trim()); + expect(body).to.have.property('feature_uuid').and.equal(Phases[i].feature_uuid.trim()); + expect(body).to.have.property('name').and.equal(Phases[i].name.trim()); + expect(body).to.have.property('priority').and.equal(Phases[i].priority); + }); + } + }) + }) +}) + +describe('Modify phases name', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + for(let i = 0; i <= 2; i++) { + cy.request({ + method: 'POST', + url: `${HostName}/features/phase`, + headers: { 'x-jwt': `${value}` }, + body: { + uuid: Phases[i].uuid, + name: Phases[i].name + "_addtext" + } + }).its('body').then(body => { + expect(body).to.have.property('uuid').and.equal(Phases[i].uuid.trim()); + expect(body).to.have.property('feature_uuid').and.equal(Phases[i].feature_uuid.trim()); + expect(body).to.have.property('name').and.equal(Phases[i].name.trim() + " _addtext"); + expect(body).to.have.property('priority').and.equal(Phases[i].priority); + }); + } + }) + }) +}) + +describe('Get phases for feature', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + cy.request({ + method: 'GET', + url: `${HostName}/features/${Phases[0].feature_uuid}/phase`, + headers: { 'x-jwt': `${ value }` }, + body: {} + }).then((resp) => { + expect(resp.status).to.eq(200) + + resp.body.forEach((phase, index) => { + // Directly use index to compare with the expected phase in the same order + const expectedPhase = Phases[index]; + expect(phase.uuid).to.equal(expectedPhase.uuid.trim()); + expect(phase.feature_uuid).to.equal(expectedPhase.feature_uuid.trim()); + expect(phase.name).to.equal(expectedPhase.name.trim() + " _addtext"); + expect(phase.priority).to.equal(expectedPhase.priority); + }); + }) + }) + }) +}) + +describe('Get phase by uuid', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + for(let i = 0; i <= 2; i++) { + cy.request({ + method: 'GET', + url: `${HostName}/features/${Phases[0].feature_uuid}/phase/${Phases[i].uuid}`, + headers: { 'x-jwt': `${ value }` }, + body: {} + }).then((resp) => { + expect(resp.status).to.eq(200) + expect(resp.body).to.have.property('uuid').and.equal(Phases[i].uuid.trim()); + expect(resp.body).to.have.property('feature_uuid').and.equal(Phases[i].feature_uuid.trim()); + expect(resp.body).to.have.property('name').and.equal(Phases[i].name.trim() + " _addtext"); + expect(resp.body).to.have.property('priority').and.equal(Phases[i].priority); + }) + } + }) + }) +}) + +describe('Delete phase by uuid', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + cy.request({ + method: 'DELETE', + url: `${HostName}/features/${Phases[0].feature_uuid}/phase/${Phases[0].uuid}`, + headers: { 'x-jwt': `${ value }` }, + body: {} + }).then((resp) => { + expect(resp.status).to.eq(200) + }) + }) + }) +}) + +describe('Check delete by uuid', () => { + it('passes', () => { + cy.upsertlogin(User).then(value => { + cy.request({ + method: 'GET', + url: `${HostName}/features/${Phases[0].feature_uuid}/phase/${Phases[0].uuid}`, + headers: { 'x-jwt': `${ value }` }, + body: {}, + failOnStatusCode: false + }).then((resp) => { + expect(resp.status).to.eq(404); + }) + }) + }) +}) diff --git a/cypress/support/objects/objects.ts b/cypress/support/objects/objects.ts index c1cfa4af0..973ab70fe 100644 --- a/cypress/support/objects/objects.ts +++ b/cypress/support/objects/objects.ts @@ -63,7 +63,7 @@ export const Repositories = [ url: ' https://github.com/stakwork/sphinx-tribes-frontend ' }, { - uuid: 'com1t3gn1e4a4qu3tnlg', + uuid: 'com1t3gn1e4a4qu3thss', workspace_uuid: 'cohob00n1e4808utqel0', name: ' backend ', url: ' https://github.com/stakwork/sphinx-tribes ' @@ -100,7 +100,7 @@ export const Features = [ ' the base from which every technical decition relays on.
' + 'We are going to leverage AI to help the PM write better definitions.
' + 'The fields that would benefit form AI assistance are: mission, tactics, ' + - 'feature brief and feature user stories', + 'feature brief and feature user stories ', requirements: ' Create a new page for a conversation format between the PM and the LLM
' + 'Rely as much as possible on stakwork workflows
' + 'Have history of previous definitions ', @@ -110,7 +110,7 @@ export const Features = [ 'Front

', }, { - uuid: 'com1l5on1e49tucv350g', + uuid: 'com1l5on1e49tucv350h', workspace_uuid: 'cohob00n1e4808utqel0', name: ' AI Assited relation between text fields ', priority: 2, @@ -118,9 +118,9 @@ export const Features = [ 'feature brief, user stories, requirements and architecture should have some ' + 'relation between each other.
' + 'One way to do that is to leverage an LLM ' + 'to discern the parts of the defintion that have a connection to other definitions.
' + - 'The UI will need to show the user how each definition is related to other defintions.', + 'The UI will need to show the user how each definition is related to other defintions. ', requirements: 'Create a new process after a Feature text has changed. It should use the LLM to ' + - 'determine de relationship between parts of the text.', + 'determine de relationship between parts of the text. ', architecture: 'Describe the architecture of the feature with the following sections:' + '

Wireframes

Visual Schematics

Object Definition

' + 'DB Schema Changes

UX

CI/CD

Changes

Endpoints

' + @@ -129,16 +129,16 @@ export const Features = [ ]; export const UserStories = [ - { uuid: 'com1lh0n1e49ug76noig', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {make providers \"hive ready\"}, so I can {leverage the hive process ' }, - { uuid: 'com1lk8n1e49uqfe3l40', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {CRUD Features}, so I can {use the system to manage my features} ' }, - { uuid: 'com1ln8n1e49v4159gug', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {follow best practices}, so I can {make more valuable features} ' }, - { uuid: 'com1lqgn1e49vevhs9k0', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {save the architecture of the feature}, so I can {share it with people} ' }, - { uuid: 'com1lt8n1e49voquoq90', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {create phases}, so I can {divide the work in several deliverable stages} ' }, - { uuid: 'com1m08n1e4a02r6j0pg', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {assign bounties to features}, so I can {group bounties together} ' }, + { uuid: 'com1lh0n1e49ug76noig', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {make providers \"hive ready\"}, so I can {leverage the hive process ', priority: 0 }, + { uuid: 'com1lk8n1e49uqfe3l40', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {CRUD Features}, so I can {use the system to manage my features} ', priority: 1 }, + { uuid: 'com1ln8n1e49v4159gug', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {follow best practices}, so I can {make more valuable features} ', priority: 2 }, + { uuid: 'com1lqgn1e49vevhs9k0', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {save the architecture of the feature}, so I can {share it with people} ', priority: 3 }, + { uuid: 'com1lt8n1e49voquoq90', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {create phases}, so I can {divide the work in several deliverable stages} ', priority: 4 }, + { uuid: 'com1m08n1e4a02r6j0pg', feature_uuid: 'com1kson1e49th88dbg0', description: ' As a {PM} I want to {assign bounties to features}, so I can {group bounties together} ', priority: 5 }, ]; export const Phases = [ - { uuid: 'com1msgn1e4a0ts5kls0', feature_uuid: 'com1kson1e49th88dbg0', name: ' MVP ' }, - { uuid: 'com1mvgn1e4a1879uiv0', feature_uuid: 'com1kson1e49th88dbg0', name: ' Phase 2 ' }, - { uuid: 'com1n2gn1e4a1i8p60p0', feature_uuid: 'com1kson1e49th88dbg0', name: ' Phase 3 ' }, + { uuid: 'com1msgn1e4a0ts5kls0', feature_uuid: 'com1kson1e49th88dbg0', name: ' MVP ', priority: 0 }, + { uuid: 'com1mvgn1e4a1879uiv0', feature_uuid: 'com1kson1e49th88dbg0', name: ' Phase 2 ', priority: 1 }, + { uuid: 'com1n2gn1e4a1i8p60p0', feature_uuid: 'com1kson1e49th88dbg0', name: ' Phase 3 ', priority: 2 }, ]; \ No newline at end of file diff --git a/db/config.go b/db/config.go index 4b50a4502..d54c162ca 100644 --- a/db/config.go +++ b/db/config.go @@ -67,6 +67,10 @@ func InitDB() { db.AutoMigrate(&ConnectionCodes{}) db.AutoMigrate(&BountyRoles{}) db.AutoMigrate(&UserInvoiceData{}) + db.AutoMigrate(&WorkspaceRepositories{}) + db.AutoMigrate(&WorkspaceFeatures{}) + db.AutoMigrate(&FeaturePhase{}) + db.AutoMigrate(&FeatureStory{}) DB.MigrateTablesWithOrgUuid() DB.MigrateOrganizationToWorkspace() @@ -177,6 +181,8 @@ func (db database) MigrateTablesWithOrgUuid() { if !db.db.Migrator().HasTable("bounty") { if !db.db.Migrator().HasColumn(Bounty{}, "workspace_uuid") { db.db.AutoMigrate(&Bounty{}) + } else { + db.db.AutoMigrate(&NewBounty{}) } } if !db.db.Migrator().HasTable("budget_histories") { @@ -187,16 +193,22 @@ func (db database) MigrateTablesWithOrgUuid() { if !db.db.Migrator().HasTable("payment_histories") { if !db.db.Migrator().HasColumn(PaymentHistory{}, "workspace_uuid") { db.db.AutoMigrate(&PaymentHistory{}) + } else { + db.db.AutoMigrate(&NewPaymentHistory{}) } } if !db.db.Migrator().HasTable("invoice_list") { if !db.db.Migrator().HasColumn(InvoiceList{}, "workspace_uuid") { db.db.AutoMigrate(&InvoiceList{}) + } else { + db.db.AutoMigrate(&NewInvoiceList{}) } } if !db.db.Migrator().HasTable("bounty_budgets") { if !db.db.Migrator().HasColumn(BountyBudget{}, "workspace_uuid") { db.db.AutoMigrate(&BountyBudget{}) + } else { + db.db.AutoMigrate(&NewBountyBudget{}) } } if !db.db.Migrator().HasTable("workspace_user_roles") { diff --git a/db/db.go b/db/db.go index d2af69fb5..ed1fd7e18 100644 --- a/db/db.go +++ b/db/db.go @@ -1142,7 +1142,7 @@ func (db database) GetAllBounties(r *http.Request) []NewBounty { languageArray := strings.Split(languages, ",") languageLength := len(languageArray) - if workspaceUuid != "" && orgUuid != "" { + if workspaceUuid == "" && orgUuid != "" { workspaceUuid = orgUuid } diff --git a/db/features.go b/db/features.go new file mode 100644 index 000000000..038d645c8 --- /dev/null +++ b/db/features.go @@ -0,0 +1,184 @@ +package db + +import ( + "errors" + "fmt" + "net/http" + "strings" + "time" + + "github.com/stakwork/sphinx-tribes/utils" +) + +func (db database) GetFeaturesByWorkspaceUuid(uuid string, r *http.Request) []WorkspaceFeatures { + offset, limit, sortBy, direction, _ := utils.GetPaginationParams(r) + + orderQuery := "" + limitQuery := "" + + ms := []WorkspaceFeatures{} + + if sortBy != "" && direction != "" { + orderQuery = "ORDER BY " + sortBy + " " + direction + } else { + orderQuery = "ORDER BY created DESC" + } + + if limit > 1 { + limitQuery = fmt.Sprintf("LIMIT %d OFFSET %d", limit, offset) + } + + query := `SELECT * FROM public.workspace_features WHERE workspace_uuid = '` + uuid + `'` + + allQuery := query + " " + orderQuery + " " + limitQuery + + theQuery := db.db.Raw(allQuery) + + theQuery.Scan(&ms) + + return ms +} + +func (db database) GetWorkspaceFeaturesCount(uuid string) int64 { + var count int64 + db.db.Model(&WorkspaceFeatures{}).Where("workspace_uuid = ?", uuid).Count(&count) + return count +} + +func (db database) GetFeatureByUuid(uuid string) WorkspaceFeatures { + ms := WorkspaceFeatures{} + + db.db.Model(&WorkspaceFeatures{}).Where("uuid = ?", uuid).Find(&ms) + + return ms +} + +func (db database) CreateOrEditFeature(m WorkspaceFeatures) (WorkspaceFeatures, error) { + m.Name = strings.TrimSpace(m.Name) + m.Brief = strings.TrimSpace(m.Brief) + m.Requirements = strings.TrimSpace(m.Requirements) + m.Architecture = strings.TrimSpace(m.Architecture) + now := time.Now() + m.Updated = &now + + var existing WorkspaceFeatures + result := db.db.Model(&WorkspaceFeatures{}).Where("uuid = ?", m.Uuid).First(&existing) + if result.RowsAffected == 0 { + + m.Created = &now + db.db.Create(&m) + } else { + + db.db.Model(&WorkspaceFeatures{}).Where("uuid = ?", m.Uuid).Updates(m) + } + + db.db.Model(&WorkspaceFeatures{}).Where("uuid = ?", m.Uuid).First(&m) + return m, nil +} + +func (db database) DeleteFeatureByUuid(uuid string) error { + result := db.db.Where("uuid = ?", uuid).Delete(&WorkspaceFeatures{}) + + if result.RowsAffected == 0 { + return errors.New("no feature found to delete") + } + return nil + +} + +func (db database) CreateOrEditFeaturePhase(phase FeaturePhase) (FeaturePhase, error) { + phase.Name = strings.TrimSpace(phase.Name) + + now := time.Now() + phase.Updated = &now + + existingPhase := FeaturePhase{} + result := db.db.Model(&FeaturePhase{}).Where("uuid = ?", phase.Uuid).First(&existingPhase) + + if result.RowsAffected == 0 { + + phase.Created = &now + db.db.Create(&phase) + } else { + + db.db.Model(&FeaturePhase{}).Where("uuid = ?", phase.Uuid).Updates(phase) + } + + db.db.Model(&FeaturePhase{}).Where("uuid = ?", phase.Uuid).Find(&phase) + + return phase, nil +} + +func (db database) GetPhasesByFeatureUuid(featureUuid string) []FeaturePhase { + phases := []FeaturePhase{} + db.db.Model(&FeaturePhase{}).Where("feature_uuid = ?", featureUuid).Order("Created ASC").Find(&phases) + return phases +} + +func (db database) GetFeaturePhaseByUuid(featureUuid, phaseUuid string) (FeaturePhase, error) { + phase := FeaturePhase{} + result := db.db.Model(&FeaturePhase{}).Where("feature_uuid = ? AND uuid = ?", featureUuid, phaseUuid).First(&phase) + if result.RowsAffected == 0 { + return phase, errors.New("no phase found") + } + return phase, nil +} + +func (db database) DeleteFeaturePhase(featureUuid, phaseUuid string) error { + result := db.db.Where("feature_uuid = ? AND uuid = ?", featureUuid, phaseUuid).Delete(&FeaturePhase{}) + if result.RowsAffected == 0 { + return errors.New("no phase found to delete") + } + return nil +} + +func (db database) CreateOrEditFeatureStory(story FeatureStory) (FeatureStory, error) { + story.Description = strings.TrimSpace(story.Description) + + now := time.Now() + story.Updated = &now + + existingStory := FeatureStory{} + result := db.db.Model(&FeatureStory{}).Where("uuid = ?", story.Uuid).First(&existingStory) + + if result.RowsAffected == 0 { + story.Created = &now + db.db.Create(&story) + } else { + db.db.Model(&FeatureStory{}).Where("uuid = ?", story.Uuid).Updates(story) + } + + db.db.Model(&FeatureStory{}).Where("uuid = ?", story.Uuid).Find(&story) + + return story, nil +} + +func (db database) GetFeatureStoriesByFeatureUuid(featureUuid string) ([]FeatureStory, error) { + var stories []FeatureStory + result := db.db.Where("feature_uuid = ?", featureUuid).Find(&stories) + if result.Error != nil { + return nil, result.Error + } + + for i := range stories { + stories[i].Description = strings.TrimSpace(stories[i].Description) + } + return stories, nil +} + +func (db database) GetFeatureStoryByUuid(featureUuid, storyUuid string) (FeatureStory, error) { + story := FeatureStory{} + result := db.db.Model(&FeatureStory{}).Where("feature_uuid = ? AND uuid = ?", featureUuid, storyUuid).First(&story) + if result.RowsAffected == 0 { + return story, errors.New("no story found") + } + return story, nil +} + +func (db database) DeleteFeatureStoryByUuid(featureUuid, storyUuid string) error { + result := db.db.Where("feature_uuid = ? AND uuid = ?", featureUuid, storyUuid).Delete(&FeatureStory{}) + if result.RowsAffected == 0 { + return errors.New("no story found to delete") + } + return nil +} diff --git a/db/interface.go b/db/interface.go index e3cc95163..8c0aa4ced 100644 --- a/db/interface.go +++ b/db/interface.go @@ -122,21 +122,37 @@ type Database interface { DeleteAllUsersFromWorkspace(uuid string) error GetFilterStatusCount() FilterStattuCount UserHasManageBountyRoles(pubKeyFromAuth string, uuid string) bool - BountiesPaidPercentage(r PaymentDateRange) uint - TotalSatsPosted(r PaymentDateRange) uint - TotalSatsPaid(r PaymentDateRange) uint - SatsPaidPercentage(r PaymentDateRange) uint - AveragePaidTime(r PaymentDateRange) uint - AverageCompletedTime(r PaymentDateRange) uint - TotalBountiesPosted(r PaymentDateRange) int64 - TotalPaidBounties(r PaymentDateRange) int64 - NewHuntersPaid(r PaymentDateRange) int64 - TotalHuntersPaid(r PaymentDateRange) int64 + BountiesPaidPercentage(r PaymentDateRange, workspace string) uint + TotalSatsPosted(r PaymentDateRange, workspace string) uint + TotalSatsPaid(r PaymentDateRange, workspace string) uint + SatsPaidPercentage(r PaymentDateRange, workspace string) uint + AveragePaidTime(r PaymentDateRange, workspace string) uint + AverageCompletedTime(r PaymentDateRange, workspace string) uint + TotalBountiesPosted(r PaymentDateRange, workspace string) int64 + TotalPaidBounties(r PaymentDateRange, workspace string) int64 + TotalAssignedBounties(r PaymentDateRange, workspace string) int64 + NewHuntersPaid(r PaymentDateRange, workspace string) int64 + TotalHuntersPaid(r PaymentDateRange, workspace string) int64 GetPersonByPubkey(pubkey string) Person - GetBountiesByDateRange(r PaymentDateRange, re *http.Request) []Bounty + GetBountiesByDateRange(r PaymentDateRange, re *http.Request) []NewBounty GetBountiesByDateRangeCount(r PaymentDateRange, re *http.Request) int64 GetBountiesProviders(r PaymentDateRange, re *http.Request) []Person PersonUniqueNameFromName(name string) (string, error) ProcessAlerts(p Person) UserHasAccess(pubKeyFromAuth string, uuid string, role string) bool + CreateWorkspaceRepository(m WorkspaceRepositories) (WorkspaceRepositories, error) + GetWorkspaceRepositorByWorkspaceUuid(uuid string) []WorkspaceRepositories + CreateOrEditFeature(m WorkspaceFeatures) (WorkspaceFeatures, error) + GetFeaturesByWorkspaceUuid(uuid string, r *http.Request) []WorkspaceFeatures + GetWorkspaceFeaturesCount(uuid string) int64 + GetFeatureByUuid(uuid string) WorkspaceFeatures + CreateOrEditFeaturePhase(phase FeaturePhase) (FeaturePhase, error) + GetPhasesByFeatureUuid(featureUuid string) []FeaturePhase + GetFeaturePhaseByUuid(featureUuid, phaseUuid string) (FeaturePhase, error) + DeleteFeaturePhase(featureUuid, phaseUuid string) error + CreateOrEditFeatureStory(story FeatureStory) (FeatureStory, error) + GetFeatureStoriesByFeatureUuid(featureUuid string) ([]FeatureStory, error) + GetFeatureStoryByUuid(featureUuid, storyUuid string) (FeatureStory, error) + DeleteFeatureStoryByUuid(featureUuid, storyUuid string) error + DeleteFeatureByUuid(uuid string) error } diff --git a/db/metrics.go b/db/metrics.go index 1a1f0e870..0fd676c2b 100644 --- a/db/metrics.go +++ b/db/metrics.go @@ -23,27 +23,45 @@ func (db database) TotalWorkspacesByDateRange(r PaymentDateRange) int64 { return count } -func (db database) TotalPaymentsByDateRange(r PaymentDateRange) uint { +func (db database) TotalPaymentsByDateRange(r PaymentDateRange, workspace string) uint { var sum uint - db.db.Model(&PaymentHistory{}).Where("payment_type = ?", r.PaymentType).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate).Select("SUM(amount)").Row().Scan(&sum) + query := db.db.Model(&NewPaymentHistory{}).Where("payment_type = ?", r.PaymentType).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate) + + if workspace != "" { + query.Where("workspace_uuid", workspace) + } + + query.Select("SUM(amount)").Row().Scan(&sum) return sum } -func (db database) TotalSatsPosted(r PaymentDateRange) uint { +func (db database) TotalSatsPosted(r PaymentDateRange, workspace string) uint { var sum uint - db.db.Model(&Bounty{}).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate).Select("SUM(price)").Row().Scan(&sum) + query := db.db.Model(&NewBounty{}).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate) + + if workspace != "" { + query.Where("workspace_uuid", workspace) + } + + query.Select("SUM(price)").Row().Scan(&sum) return sum } -func (db database) TotalSatsPaid(r PaymentDateRange) uint { +func (db database) TotalSatsPaid(r PaymentDateRange, workspace string) uint { var sum uint - db.db.Model(&Bounty{}).Where("paid = ?", true).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate).Select("SUM(price)").Row().Scan(&sum) + query := db.db.Model(&NewBounty{}).Where("paid = ?", true).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate) + + if workspace != "" { + query.Where("workspace_uuid", workspace) + } + + query.Select("SUM(price)").Row().Scan(&sum) return sum } -func (db database) SatsPaidPercentage(r PaymentDateRange) uint { - satsPosted := DB.TotalSatsPosted(r) - satsPaid := DB.TotalSatsPaid(r) +func (db database) SatsPaidPercentage(r PaymentDateRange, workspace string) uint { + satsPosted := DB.TotalSatsPosted(r, workspace) + satsPaid := DB.TotalSatsPaid(r, workspace) if satsPaid != 0 && satsPosted != 0 { value := (satsPaid * 100) / satsPosted paidPercentage := math.Round(float64(value)) @@ -52,43 +70,81 @@ func (db database) SatsPaidPercentage(r PaymentDateRange) uint { return 0 } -func (db database) TotalPaidBounties(r PaymentDateRange) int64 { +func (db database) TotalPaidBounties(r PaymentDateRange, workspace string) int64 { + var count int64 + query := db.db.Model(&NewBounty{}).Where("paid = ?", true).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate) + + if workspace != "" { + query.Where("workspace_uuid", workspace) + } + + query.Count(&count) + return count +} + +func (db database) TotalAssignedBounties(r PaymentDateRange, workspace string) int64 { var count int64 - db.db.Model(&Bounty{}).Where("paid = ?", true).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate).Count(&count) + query := db.db.Model(&NewBounty{}).Where("assignee != ''").Where("paid = ?", false).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate) + + if workspace != "" { + query.Where("workspace_uuid", workspace) + } + + query.Count(&count) return count } -func (db database) TotalHuntersPaid(r PaymentDateRange) int64 { +func (db database) TotalHuntersPaid(r PaymentDateRange, workspace string) int64 { var count int64 query := fmt.Sprintf(`SELECT COUNT(DISTINCT assignee) FROM bounty WHERE assignee !='' AND paid=true AND created >= %s AND created <= %s`, r.StartDate, r.EndDate) - db.db.Raw(query).Count(&count) + var workspaceQuery string + if workspace != "" { + workspaceQuery = fmt.Sprintf("AND workspace_uuid = '%s'", workspace) + } + + allQuery := query + " " + workspaceQuery + db.db.Raw(allQuery).Count(&count) return count } -func (db database) NewHuntersPaid(r PaymentDateRange) int64 { +func (db database) NewHuntersPaid(r PaymentDateRange, workspace string) int64 { var count int64 - db.db.Model(&Bounty{}). + + query := db.db.Model(&NewBounty{}). Select("DISTINCT assignee"). Where("paid = true"). - Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate). - Not("assignee IN (?)", db.db.Model(&Bounty{}). - Select("assignee"). - Where("paid = true"). - Where("created < ?", r.StartDate), - ).Count(&count) + Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate) + + if workspace != "" { + query.Where("workspace_uuid", workspace) + } + + query.Not("assignee IN (?)", db.db.Model(&NewBounty{}). + Select("assignee"). + Where("paid = true"). + Where("created < ?", r.StartDate), + ) + + query.Count(&count) return count } -func (db database) TotalBountiesPosted(r PaymentDateRange) int64 { +func (db database) TotalBountiesPosted(r PaymentDateRange, workspace string) int64 { var count int64 - db.db.Model(&Bounty{}).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate).Count(&count) + query := db.db.Model(&Bounty{}).Where("created >= ?", r.StartDate).Where("created <= ?", r.EndDate) + + if workspace != "" { + query.Where("workspace_uuid", workspace) + } + + query.Count(&count) return count } -func (db database) BountiesPaidPercentage(r PaymentDateRange) uint { - bountiesPosted := DB.TotalBountiesPosted(r) - bountiesPaid := DB.TotalPaidBounties(r) +func (db database) BountiesPaidPercentage(r PaymentDateRange, workspace string) uint { + bountiesPosted := DB.TotalBountiesPosted(r, workspace) + bountiesPaid := DB.TotalPaidBounties(r, workspace) if bountiesPaid != 0 && bountiesPosted != 0 { value := bountiesPaid * 100 / bountiesPosted paidPercentage := math.Round(float64(value)) @@ -97,23 +153,31 @@ func (db database) BountiesPaidPercentage(r PaymentDateRange) uint { return 0 } -func (db database) PaidDifference(r PaymentDateRange) []DateDifference { +func (db database) PaidDifference(r PaymentDateRange, workspace string) []DateDifference { ms := []DateDifference{} - db.db.Raw(`SELECT EXTRACT(EPOCH FROM (paid_date - TO_TIMESTAMP(created))) as diff FROM public.bounty WHERE paid_date IS NOT NULL AND created >= '` + r.StartDate + `' AND created <= '` + r.EndDate + `' `).Find(&ms) + query := fmt.Sprintf("SELECT EXTRACT(EPOCH FROM (paid_date - TO_TIMESTAMP(created))) as diff FROM public.bounty WHERE paid_date IS NOT NULL AND created >= %s AND created <= %s", r.StartDate, r.EndDate) + + var workspaceQuery string + if workspace != "" { + workspaceQuery = fmt.Sprintf("AND workspace_uuid = '%s'", workspace) + } + + allQuery := query + " " + workspaceQuery + db.db.Raw(allQuery).Find(&ms) return ms } -func (db database) PaidDifferenceCount(r PaymentDateRange) int64 { +func (db database) PaidDifferenceCount(r PaymentDateRange, workspace string) int64 { var count int64 - list := db.PaidDifference(r) + list := db.PaidDifference(r, workspace) count = int64(len(list)) return count } -func (db database) AveragePaidTime(r PaymentDateRange) uint { - paidList := DB.PaidDifference(r) - paidCount := DB.PaidDifferenceCount(r) +func (db database) AveragePaidTime(r PaymentDateRange, workspace string) uint { + paidList := DB.PaidDifference(r, workspace) + paidCount := DB.PaidDifferenceCount(r, workspace) var paidSum uint for _, diff := range paidList { paidSum = uint(math.Round(diff.Diff)) @@ -121,23 +185,31 @@ func (db database) AveragePaidTime(r PaymentDateRange) uint { return CalculateAverageDays(paidCount, paidSum) } -func (db database) CompletedDifference(r PaymentDateRange) []DateDifference { +func (db database) CompletedDifference(r PaymentDateRange, workspace string) []DateDifference { ms := []DateDifference{} - db.db.Raw(`SELECT EXTRACT(EPOCH FROM (completion_date - TO_TIMESTAMP(created))) as diff FROM public.bounty WHERE completion_date IS NOT NULL AND created >= '` + r.StartDate + `' AND created <= '` + r.EndDate + `' `).Find(&ms) + query := fmt.Sprintf("SELECT EXTRACT(EPOCH FROM (completion_date - TO_TIMESTAMP(created))) as diff FROM public.bounty WHERE completion_date IS NOT NULL AND created >= %s AND created <= %s", r.StartDate, r.EndDate) + + var workspaceQuery string + if workspace != "" { + workspaceQuery = fmt.Sprintf("AND workspace_uuid = '%s'", workspace) + } + + allQuery := query + " " + workspaceQuery + db.db.Raw(allQuery).Find(&ms) return ms } -func (db database) CompletedDifferenceCount(r PaymentDateRange) int64 { +func (db database) CompletedDifferenceCount(r PaymentDateRange, workspace string) int64 { var count int64 - list := db.CompletedDifference(r) + list := db.CompletedDifference(r, workspace) count = int64(len(list)) return count } -func (db database) AverageCompletedTime(r PaymentDateRange) uint { - paidList := DB.CompletedDifference(r) - paidCount := DB.CompletedDifferenceCount(r) +func (db database) AverageCompletedTime(r PaymentDateRange, workspace string) uint { + paidList := DB.CompletedDifference(r, workspace) + paidCount := DB.CompletedDifferenceCount(r, workspace) var paidSum uint for _, diff := range paidList { paidSum = uint(math.Round(diff.Diff)) @@ -155,16 +227,18 @@ func CalculateAverageDays(paidCount int64, paidSum uint) uint { return 0 } -func (db database) GetBountiesByDateRange(r PaymentDateRange, re *http.Request) []Bounty { +func (db database) GetBountiesByDateRange(r PaymentDateRange, re *http.Request) []NewBounty { offset, limit, sortBy, direction, _ := utils.GetPaginationParams(re) keys := re.URL.Query() open := keys.Get("Open") assingned := keys.Get("Assigned") paid := keys.Get("Paid") providers := keys.Get("provider") + workspace := keys.Get("workspace") orderQuery := "" limitQuery := "" + workspaceQuery := "" var statusConditions []string @@ -190,9 +264,12 @@ func (db database) GetBountiesByDateRange(r PaymentDateRange, re *http.Request) } else { orderQuery = " ORDER BY " + sortBy + "" + "DESC" } - if limit > 0 { + if limit > 1 { limitQuery = fmt.Sprintf("LIMIT %d OFFSET %d", limit, offset) } + if workspace != "" { + workspaceQuery = fmt.Sprintf("AND workspace_uuid = '%s'", workspace) + } providerCondition := "" if len(providers) > 0 { @@ -201,10 +278,11 @@ func (db database) GetBountiesByDateRange(r PaymentDateRange, re *http.Request) } query := `SELECT * FROM public.bounty WHERE created >= '` + r.StartDate + `' AND created <= '` + r.EndDate + `'` + providerCondition - allQuery := query + " " + statusQuery + " " + orderQuery + " " + limitQuery + allQuery := query + " " + workspaceQuery + " " + statusQuery + " " + orderQuery + " " + limitQuery - b := []Bounty{} + b := []NewBounty{} db.db.Raw(allQuery).Find(&b) + return b } @@ -214,6 +292,7 @@ func (db database) GetBountiesByDateRangeCount(r PaymentDateRange, re *http.Requ assingned := keys.Get("Assigned") paid := keys.Get("Paid") providers := keys.Get("provider") + workspace := keys.Get("workspace") var statusConditions []string @@ -239,11 +318,15 @@ func (db database) GetBountiesByDateRangeCount(r PaymentDateRange, re *http.Requ providerSlice := strings.Split(providers, ",") providerCondition = " AND owner_id IN ('" + strings.Join(providerSlice, "','") + "')" } + var workspaceQuery string + if workspace != "" { + workspaceQuery = fmt.Sprintf("AND workspace_uuid = '%s'", workspace) + } var count int64 query := `SELECT COUNT(*) FROM public.bounty WHERE created >= '` + r.StartDate + `' AND created <= '` + r.EndDate + `'` + providerCondition - allQuery := query + " " + statusQuery + allQuery := query + " " + workspaceQuery + " " + statusQuery db.db.Raw(allQuery).Scan(&count) return count } diff --git a/db/structs.go b/db/structs.go index e6a25a7de..6988a5511 100644 --- a/db/structs.go +++ b/db/structs.go @@ -429,38 +429,42 @@ type BountyOwners struct { } type BountyData struct { - Bounty + NewBounty BountyId uint `json:"bounty_id"` BountyCreated int64 `json:"bounty_created"` BountyUpdated *time.Time `json:"bounty_updated"` BountyDescription string `json:"bounty_description"` Person - AssigneeAlias string `json:"assignee_alias"` - AssigneeId uint `json:"assignee_id"` - AssigneeImg string `json:"assignee_img"` - AssigneeCreated *time.Time `json:"assignee_created"` - AssigneeUpdated *time.Time `json:"assignee_updated"` - AssigneeDescription string `json:"assignee_description"` - AssigneeRouteHint string `json:"assignee_route_hint"` - BountyOwnerId uint `json:"bounty_owner_id"` - OwnerUuid string `json:"owner_uuid"` - OwnerKey string `json:"owner_key"` - OwnerAlias string `json:"owner_alias"` - OwnerUniqueName string `json:"owner_unique_name"` - OwnerDescription string `json:"owner_description"` - OwnerTags pq.StringArray `gorm:"type:text[]" json:"owner_tags" null` - OwnerImg string `json:"owner_img"` - OwnerCreated *time.Time `json:"owner_created"` - OwnerUpdated *time.Time `json:"owner_updated"` - OwnerLastLogin int64 `json:"owner_last_login"` - OwnerRouteHint string `json:"owner_route_hint"` - OwnerContactKey string `json:"owner_contact_key"` - OwnerPriceToMeet int64 `json:"owner_price_to_meet"` - OwnerTwitterConfirmed bool `json:"owner_twitter_confirmed"` - OrganizationName string `json:"organization_name"` - OrganizationImg string `json:"organization_img"` - WorkspaceUuid string `json:"organization_uuid"` - WorkspaceDescription string `json:"description"` + AssigneeAlias string `json:"assignee_alias"` + AssigneeId uint `json:"assignee_id"` + AssigneeImg string `json:"assignee_img"` + AssigneeCreated *time.Time `json:"assignee_created"` + AssigneeUpdated *time.Time `json:"assignee_updated"` + AssigneeDescription string `json:"assignee_description"` + AssigneeRouteHint string `json:"assignee_route_hint"` + BountyOwnerId uint `json:"bounty_owner_id"` + OwnerUuid string `json:"owner_uuid"` + OwnerKey string `json:"owner_key"` + OwnerAlias string `json:"owner_alias"` + OwnerUniqueName string `json:"owner_unique_name"` + OwnerDescription string `json:"owner_description"` + OwnerTags pq.StringArray `gorm:"type:text[]" json:"owner_tags" null` + OwnerImg string `json:"owner_img"` + OwnerCreated *time.Time `json:"owner_created"` + OwnerUpdated *time.Time `json:"owner_updated"` + OwnerLastLogin int64 `json:"owner_last_login"` + OwnerRouteHint string `json:"owner_route_hint"` + OwnerContactKey string `json:"owner_contact_key"` + OwnerPriceToMeet int64 `json:"owner_price_to_meet"` + OwnerTwitterConfirmed bool `json:"owner_twitter_confirmed"` + OrganizationName string `json:"organization_name"` + OrganizationImg string `json:"organization_img"` + OrganizationUuid string `json:"organization_uuid"` + OrganizationDescription string `json:"description"` + WorkspaceName string `json:"workspace_name"` + WorkspaceImg string `json:"workspace_img"` + WorkspaceUuid string `json:"workspace_uuid"` + WorkspaceDescription string `json:"workspace_description"` } type BountyResponse struct { @@ -547,6 +551,43 @@ type WorkspaceUsersData struct { Person } +type WorkspaceRepositories struct { + ID uint `json:"id"` + Uuid string `gorm:"not null" json:"uuid"` + WorkspaceUuid string `gorm:"not null" json:"workspace_uuid"` + Name string `gorm:"not null" json:"name"` + Url string `json:"url"` + Created *time.Time `json:"created"` + Updated *time.Time `json:"updated"` + CreatedBy string `json:"created_by"` + UpdatedBy string `json:"updated_by"` +} + +type WorkspaceFeatures struct { + ID uint `json:"id"` + Uuid string `gorm:"not null" json:"uuid"` + WorkspaceUuid string `gorm:"not null" json:"workspace_uuid"` + Name string `gorm:"not null" json:"name"` + Brief string `json:"brief"` + Requirements string `json:"requirements"` + Architecture string `json:"architecture"` + Created *time.Time `json:"created"` + Updated *time.Time `json:"updated"` + CreatedBy string `json:"created_by"` + UpdatedBy string `json:"updated_by"` +} + +type FeaturePhase struct { + Uuid string `json:"uuid" gorm:"primary_key"` + FeatureUuid string `json:"feature_uuid"` + Name string `json:"name"` + Priority int `json:"priority"` + Created *time.Time `json:"created"` + Updated *time.Time `json:"updated"` + CreatedBy string `json:"created_by"` + UpdatedBy string `json:"updated_by"` +} + type BountyRoles struct { Name string `json:"name"` } @@ -587,15 +628,18 @@ type NewBountyBudget struct { } type StatusBudget struct { - OrgUuid string `json:"org_uuid"` - WorkspaceUuid string `json:"workspace_uuid"` - CurrentBudget uint `json:"current_budget"` - OpenBudget uint `json:"open_budget"` - OpenCount int64 `json:"open_count"` - AssignedBudget uint `json:"assigned_budget"` - AssignedCount int64 `json:"assigned_count"` - CompletedBudget uint `json:"completed_budget"` - CompletedCount int64 `json:"completed_count"` + OrgUuid string `json:"org_uuid"` + WorkspaceUuid string `json:"workspace_uuid"` + CurrentBudget uint `json:"current_budget"` + OpenBudget uint `json:"open_budget"` + OpenCount int64 `json:"open_count"` + OpenDifference int `json:"open_difference"` + AssignedBudget uint `json:"assigned_budget"` + AssignedCount int64 `json:"assigned_count"` + AssignedDifference int `json:"assigned_difference"` + CompletedBudget uint `json:"completed_budget"` + CompletedCount int64 `json:"completed_count"` + CompletedDifference int `json:"completed_difference"` } type BudgetInvoiceRequest struct { @@ -635,6 +679,18 @@ type BudgetHistory struct { PaymentType PaymentType `json:"payment_type"` } +type FeatureStory struct { + ID uint `json:"id"` + Uuid string `json:"uuid"` + FeatureUuid string `json:"feature_uuid"` + Description string `json:"description"` + Priority int `json:"priority"` + Created *time.Time `json:"created"` + Updated *time.Time `json:"updated"` + CreatedBy string `json:"created_by"` + UpdatedBy string `json:"updated_by"` +} + type BudgetHistoryData struct { BudgetHistory SenderName string `json:"sender_name"` @@ -668,11 +724,11 @@ type NewPaymentHistory struct { } type PaymentHistoryData struct { - PaymentHistory NewPaymentHistory - SenderName string `json:"sender_name"` - ReceiverName string `json:"receiver_name"` - SenderImg string `json:"sender_img"` - ReceiverImg string `json:"receiver_img"` + NewPaymentHistory + SenderName string `json:"sender_name"` + ReceiverName string `json:"receiver_name"` + SenderImg string `json:"sender_img"` + ReceiverImg string `json:"receiver_img"` } type PaymentData struct { @@ -799,6 +855,7 @@ type DateDifference struct { type BountyMetrics struct { BountiesPosted int64 `json:"bounties_posted"` BountiesPaid int64 `json:"bounties_paid"` + BountiesAssigned int64 `json:"bounties_assigned"` BountiesPaidPercentage uint `json:"bounties_paid_average"` SatsPosted uint `json:"sats_posted"` SatsPaid uint `json:"sats_paid"` diff --git a/db/workspaces.go b/db/workspaces.go index d1e77b596..f11c298c8 100644 --- a/db/workspaces.go +++ b/db/workspaces.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "net/http" + "strings" "time" "github.com/stakwork/sphinx-tribes/utils" @@ -13,8 +14,13 @@ func (db database) GetWorkspaces(r *http.Request) []Workspace { ms := []Workspace{} offset, limit, sortBy, direction, search := utils.GetPaginationParams(r) - // return if like owner_alias, unique_name, or equals pubkey - db.db.Offset(offset).Limit(limit).Order(sortBy+" "+direction+" ").Where("LOWER(name) LIKE ?", "%"+search+"%").Where("deleted != ?", false).Find(&ms) + query := db.db.Model(&ms).Where("LOWER(name) LIKE ?", "%"+search+"%").Where("deleted != ?", true) + + if limit > 1 { + query.Offset(offset).Limit(limit).Order(sortBy + " " + direction + " ") + } + + query.Find(&ms) return ms } @@ -52,6 +58,29 @@ func (db database) CreateOrEditWorkspace(m Workspace) (Workspace, error) { return m, nil } +func (db database) CreateWorkspaceRepository(m WorkspaceRepositories) (WorkspaceRepositories, error) { + m.Name = strings.TrimSpace(m.Name) + m.Url = strings.TrimSpace(m.Url) + + now := time.Now() + m.Updated = &now + + if db.db.Model(&m).Where("uuid = ?", m.Uuid).Updates(&m).RowsAffected == 0 { + m.Created = &now + db.db.Create(&m) + } + + return m, nil +} + +func (db database) GetWorkspaceRepositorByWorkspaceUuid(uuid string) []WorkspaceRepositories { + ms := []WorkspaceRepositories{} + + db.db.Model(&WorkspaceRepositories{}).Where("workspace_uuid = ?", uuid).Order("Created").Find(&ms) + + return ms +} + func (db database) GetWorkspaceUsers(uuid string) ([]WorkspaceUsersData, error) { ms := []WorkspaceUsersData{} @@ -133,7 +162,7 @@ func (db database) CreateWorkspaceBudget(budget NewBountyBudget) NewBountyBudget } func (db database) UpdateWorkspaceBudget(budget NewBountyBudget) NewBountyBudget { - db.db.Model(&NewBountyBudget{}).Where("workspace_uuid = ?", budget.OrgUuid).Updates(map[string]interface{}{ + db.db.Model(&NewBountyBudget{}).Where("workspace_uuid = ?", budget.WorkspaceUuid).Updates(map[string]interface{}{ "total_budget": budget.TotalBudget, }) return budget @@ -141,49 +170,57 @@ func (db database) UpdateWorkspaceBudget(budget NewBountyBudget) NewBountyBudget func (db database) GetPaymentHistoryByCreated(created *time.Time, workspace_uuid string) NewPaymentHistory { ms := NewPaymentHistory{} - db.db.Where("created = ?", created).Where("workspace_uuid = ? ", workspace_uuid).Find(&ms) + db.db.Model(&NewPaymentHistory{}).Where("created = ?", created).Where("workspace_uuid = ? ", workspace_uuid).Find(&ms) return ms } func (db database) GetWorkspaceBudget(workspace_uuid string) NewBountyBudget { ms := NewBountyBudget{} - db.db.Where("workspace_uuid = ?", workspace_uuid).Find(&ms) + db.db.Model(&NewBountyBudget{}).Where("workspace_uuid = ?", workspace_uuid).Find(&ms) return ms } func (db database) GetWorkspaceStatusBudget(workspace_uuid string) StatusBudget { - orgBudget := db.GetWorkspaceBudget(workspace_uuid) var openBudget uint - db.db.Model(&Bounty{}).Where("assignee = '' ").Where("paid != true").Select("SUM(price)").Row().Scan(&openBudget) + db.db.Model(&NewBounty{}).Where("assignee = '' ").Where("paid != true").Select("SUM(price)").Row().Scan(&openBudget) var openCount int64 - db.db.Model(&Bounty{}).Where("assignee = '' ").Where("paid != true").Count(&openCount) + db.db.Model(&NewBounty{}).Where("assignee = '' ").Where("paid != true").Count(&openCount) + + var openDifference int = int(orgBudget.TotalBudget - openBudget) var assignedBudget uint - db.db.Model(&Bounty{}).Where("assignee != '' ").Where("paid != true").Select("SUM(price)").Row().Scan(&assignedBudget) + db.db.Model(&NewBounty{}).Where("assignee != '' ").Where("paid != true").Select("SUM(price)").Row().Scan(&assignedBudget) var assignedCount int64 - db.db.Model(&Bounty{}).Where("assignee != '' ").Where("paid != true").Count(&assignedCount) + db.db.Model(&NewBounty{}).Where("assignee != '' ").Where("paid != true").Count(&assignedCount) + + var assignedDifference int = int(orgBudget.TotalBudget - assignedBudget) var completedBudget uint - db.db.Model(&Bounty{}).Where("completed = true ").Where("paid != true").Select("SUM(price)").Row().Scan(&completedBudget) + db.db.Model(&NewBounty{}).Where("completed = true ").Where("paid != true").Select("SUM(price)").Row().Scan(&completedBudget) var completedCount int64 - db.db.Model(&Bounty{}).Where("completed = true ").Where("paid != true").Count(&completedCount) + db.db.Model(&NewBounty{}).Where("completed = true ").Where("paid != true").Count(&completedCount) + + var completedDifference int = int(orgBudget.TotalBudget - completedBudget) statusBudget := StatusBudget{ - OrgUuid: workspace_uuid, - WorkspaceUuid: workspace_uuid, - CurrentBudget: orgBudget.TotalBudget, - OpenBudget: openBudget, - OpenCount: openCount, - AssignedBudget: assignedBudget, - AssignedCount: assignedCount, - CompletedBudget: completedBudget, - CompletedCount: completedCount, + OrgUuid: workspace_uuid, + WorkspaceUuid: workspace_uuid, + CurrentBudget: orgBudget.TotalBudget, + OpenBudget: openBudget, + OpenCount: openCount, + OpenDifference: openDifference, + AssignedBudget: assignedBudget, + AssignedCount: assignedCount, + AssignedDifference: assignedDifference, + CompletedBudget: completedBudget, + CompletedCount: completedCount, + CompletedDifference: completedDifference, } return statusBudget @@ -209,15 +246,15 @@ func (db database) AddAndUpdateBudget(invoice NewInvoiceList) NewPaymentHistory // get Workspace budget and add payment to total budget WorkspaceBudget := db.GetWorkspaceBudget(workspace_uuid) - if WorkspaceBudget.OrgUuid == "" { + if WorkspaceBudget.WorkspaceUuid == "" { now := time.Now() - orgBudget := NewBountyBudget{ + workBudget := NewBountyBudget{ WorkspaceUuid: workspace_uuid, TotalBudget: paymentHistory.Amount, Created: &now, Updated: &now, } - db.CreateWorkspaceBudget(orgBudget) + db.CreateWorkspaceBudget(workBudget) } else { totalBudget := WorkspaceBudget.TotalBudget WorkspaceBudget.TotalBudget = totalBudget + paymentHistory.Amount @@ -258,7 +295,7 @@ func (db database) AddPaymentHistory(payment NewPaymentHistory) NewPaymentHistor db.db.Create(&payment) // get Workspace budget and subtract payment from total budget - WorkspaceBudget := db.GetWorkspaceBudget(payment.OrgUuid) + WorkspaceBudget := db.GetWorkspaceBudget(payment.WorkspaceUuid) totalBudget := WorkspaceBudget.TotalBudget // deduct amount if it's a bounty payment diff --git a/handlers/features.go b/handlers/features.go new file mode 100644 index 000000000..1e77f2483 --- /dev/null +++ b/handlers/features.go @@ -0,0 +1,316 @@ +package handlers + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/go-chi/chi" + "github.com/rs/xid" + "github.com/stakwork/sphinx-tribes/auth" + "github.com/stakwork/sphinx-tribes/db" +) + +type featureHandler struct { + db db.Database +} + +func NewFeatureHandler(database db.Database) *featureHandler { + return &featureHandler{ + db: database, + } +} + +func (oh *featureHandler) CreateOrEditFeatures(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + features := db.WorkspaceFeatures{} + body, _ := io.ReadAll(r.Body) + r.Body.Close() + err := json.Unmarshal(body, &features) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusNotAcceptable) + return + } + + features.CreatedBy = pubKeyFromAuth + + if features.Uuid == "" { + features.Uuid = xid.New().String() + } else { + features.UpdatedBy = pubKeyFromAuth + } + + // Validate struct data + err = db.Validate.Struct(features) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + msg := fmt.Sprintf("Error: did not pass validation test : %s", err) + json.NewEncoder(w).Encode(msg) + return + } + + // Check if workspace exists + workpace := oh.db.GetWorkspaceByUuid(features.WorkspaceUuid) + if workpace.Uuid != features.WorkspaceUuid { + w.WriteHeader(http.StatusUnauthorized) + json.NewEncoder(w).Encode("Workspace does not exists") + return + } + + p, err := oh.db.CreateOrEditFeature(features) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(p) +} + +func (oh *featureHandler) DeleteFeature(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + uuid := chi.URLParam(r, "uuid") + err := oh.db.DeleteFeatureByUuid(uuid) + if err != nil { + w.WriteHeader(http.StatusNotFound) + json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + return + } + + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, "Feature deleted successfully") +} + +// Old Method for getting features for workspace uuid + +func (oh *featureHandler) GetFeaturesByWorkspaceUuid(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + uuid := chi.URLParam(r, "workspace_uuid") + workspaceFeatures := oh.db.GetFeaturesByWorkspaceUuid(uuid, r) + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(workspaceFeatures) +} + +func (oh *featureHandler) GetWorkspaceFeaturesCount(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + uuid := chi.URLParam(r, "uuid") + workspaceFeatures := oh.db.GetWorkspaceFeaturesCount(uuid) + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(workspaceFeatures) +} + +func (oh *featureHandler) GetFeatureByUuid(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + uuid := chi.URLParam(r, "uuid") + workspaceFeature := oh.db.GetFeatureByUuid(uuid) + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(workspaceFeature) +} + +func (oh *featureHandler) CreateOrEditFeaturePhase(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + newPhase := db.FeaturePhase{} + decoder := json.NewDecoder(r.Body) + err := decoder.Decode(&newPhase) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Error decoding request body: %v", err) + return + } + + if newPhase.Uuid == "" { + newPhase.Uuid = xid.New().String() + } + + existingPhase, _ := oh.db.GetFeaturePhaseByUuid(newPhase.FeatureUuid, newPhase.Uuid) + + if existingPhase.CreatedBy == "" { + newPhase.CreatedBy = pubKeyFromAuth + } + + newPhase.UpdatedBy = pubKeyFromAuth + + // Check if feature exists + feature := oh.db.GetFeatureByUuid(newPhase.FeatureUuid) + if feature.Uuid != newPhase.FeatureUuid { + w.WriteHeader(http.StatusUnauthorized) + json.NewEncoder(w).Encode("Feature does not exists") + return + } + + phase, err := oh.db.CreateOrEditFeaturePhase(newPhase) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Error creating feature phase: %v", err) + return + } + + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(phase) +} + +func (oh *featureHandler) GetFeaturePhases(w http.ResponseWriter, r *http.Request) { + featureUuid := chi.URLParam(r, "feature_uuid") + phases := oh.db.GetPhasesByFeatureUuid(featureUuid) + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(phases) +} + +func (oh *featureHandler) GetFeaturePhaseByUUID(w http.ResponseWriter, r *http.Request) { + featureUuid := chi.URLParam(r, "feature_uuid") + phaseUuid := chi.URLParam(r, "phase_uuid") + + phase, err := oh.db.GetFeaturePhaseByUuid(featureUuid, phaseUuid) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(phase) +} + +func (oh *featureHandler) DeleteFeaturePhase(w http.ResponseWriter, r *http.Request) { + featureUuid := chi.URLParam(r, "feature_uuid") + phaseUuid := chi.URLParam(r, "phase_uuid") + + err := oh.db.DeleteFeaturePhase(featureUuid, phaseUuid) + if err != nil { + w.WriteHeader(http.StatusNotFound) + json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]string{"message": "Phase deleted successfully"}) +} + +func (oh *featureHandler) CreateOrEditStory(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + newStory := db.FeatureStory{} + decoder := json.NewDecoder(r.Body) + err := decoder.Decode(&newStory) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Error decoding request body: %v", err) + return + } + + if newStory.Uuid == "" { + newStory.Uuid = xid.New().String() + } + + existingStory, _ := oh.db.GetFeatureStoryByUuid(newStory.FeatureUuid, newStory.Uuid) + + if existingStory.CreatedBy == "" { + newStory.CreatedBy = pubKeyFromAuth + } + + newStory.UpdatedBy = pubKeyFromAuth + + story, err := oh.db.CreateOrEditFeatureStory(newStory) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Error creating feature story: %v", err) + return + } + + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(story) +} + +func (oh *featureHandler) GetStoriesByFeatureUuid(w http.ResponseWriter, r *http.Request) { + featureUuid := chi.URLParam(r, "feature_uuid") + stories, err := oh.db.GetFeatureStoriesByFeatureUuid(featureUuid) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(stories) +} + +func (oh *featureHandler) GetStoryByUuid(w http.ResponseWriter, r *http.Request) { + featureUuid := chi.URLParam(r, "feature_uuid") + storyUuid := chi.URLParam(r, "story_uuid") + + story, err := oh.db.GetFeatureStoryByUuid(featureUuid, storyUuid) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(story) +} +func (oh *featureHandler) DeleteStory(w http.ResponseWriter, r *http.Request) { + featureUuid := chi.URLParam(r, "feature_uuid") + storyUuid := chi.URLParam(r, "story_uuid") + + err := oh.db.DeleteFeatureStoryByUuid(featureUuid, storyUuid) + if err != nil { + w.WriteHeader(http.StatusNotFound) + json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]string{"message": "Story deleted successfully"}) +} diff --git a/handlers/metrics.go b/handlers/metrics.go index 2a0140cb5..27f1378b7 100644 --- a/handlers/metrics.go +++ b/handlers/metrics.go @@ -33,6 +33,8 @@ func NewMetricHandler(db db.Database) *metricHandler { func PaymentMetrics(w http.ResponseWriter, r *http.Request) { ctx := r.Context() pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + keys := r.URL.Query() + workspace := keys.Get("workspace") if pubKeyFromAuth == "" { fmt.Println("no pubkey from auth") @@ -51,7 +53,7 @@ func PaymentMetrics(w http.ResponseWriter, r *http.Request) { return } - sumAmount := db.DB.TotalPaymentsByDateRange(request) + sumAmount := db.DB.TotalPaymentsByDateRange(request, workspace) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(sumAmount) @@ -114,6 +116,8 @@ func PeopleMetrics(w http.ResponseWriter, r *http.Request) { func (mh *metricHandler) BountyMetrics(w http.ResponseWriter, r *http.Request) { ctx := r.Context() pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + keys := r.URL.Query() + workspace := keys.Get("workspace") if pubKeyFromAuth == "" { fmt.Println("no pubkey from auth") @@ -146,20 +150,22 @@ func (mh *metricHandler) BountyMetrics(w http.ResponseWriter, r *http.Request) { } } - totalBountiesPosted := mh.db.TotalBountiesPosted(request) - totalBountiesPaid := mh.db.TotalPaidBounties(request) - bountiesPaidPercentage := mh.db.BountiesPaidPercentage(request) - totalSatsPosted := mh.db.TotalSatsPosted(request) - totalSatsPaid := mh.db.TotalSatsPaid(request) - satsPaidPercentage := mh.db.SatsPaidPercentage(request) - avgPaidDays := mh.db.AveragePaidTime(request) - avgCompletedDays := mh.db.AverageCompletedTime(request) - uniqueHuntersPaid := mh.db.TotalHuntersPaid(request) - newHuntersPaid := mh.db.NewHuntersPaid(request) + totalBountiesPosted := mh.db.TotalBountiesPosted(request, workspace) + totalBountiesPaid := mh.db.TotalPaidBounties(request, workspace) + totalBountiesAssigned := mh.db.TotalAssignedBounties(request, workspace) + bountiesPaidPercentage := mh.db.BountiesPaidPercentage(request, workspace) + totalSatsPosted := mh.db.TotalSatsPosted(request, workspace) + totalSatsPaid := mh.db.TotalSatsPaid(request, workspace) + satsPaidPercentage := mh.db.SatsPaidPercentage(request, workspace) + avgPaidDays := mh.db.AveragePaidTime(request, workspace) + avgCompletedDays := mh.db.AverageCompletedTime(request, workspace) + uniqueHuntersPaid := mh.db.TotalHuntersPaid(request, workspace) + newHuntersPaid := mh.db.NewHuntersPaid(request, workspace) bountyMetrics := db.BountyMetrics{ BountiesPosted: totalBountiesPosted, BountiesPaid: totalBountiesPaid, + BountiesAssigned: totalBountiesAssigned, BountiesPaidPercentage: bountiesPaidPercentage, SatsPosted: totalSatsPosted, SatsPaid: totalSatsPaid, @@ -300,46 +306,65 @@ func MetricsCsv(w http.ResponseWriter, r *http.Request) { } } -func (mh *metricHandler) GetMetricsBountiesData(metricBounties []db.Bounty) []db.BountyData { +func GetAdminWorkspaces(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + workspaces := db.DB.GetWorkspaces(r) + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(workspaces) +} + +func (mh *metricHandler) GetMetricsBountiesData(metricBounties []db.NewBounty) []db.BountyData { var metricBountiesData []db.BountyData for _, bounty := range metricBounties { bountyOwner := mh.db.GetPersonByPubkey(bounty.OwnerID) bountyAssignee := mh.db.GetPersonByPubkey(bounty.Assignee) - organization := mh.db.GetWorkspaceByUuid(bounty.OrgUuid) + workspace := mh.db.GetWorkspaceByUuid(bounty.WorkspaceUuid) bountyData := db.BountyData{ - Bounty: bounty, - BountyId: bounty.ID, - Person: bountyOwner, - BountyCreated: bounty.Created, - BountyDescription: bounty.Description, - BountyUpdated: bounty.Updated, - AssigneeId: bountyAssignee.ID, - AssigneeImg: bountyAssignee.Img, - AssigneeAlias: bountyAssignee.OwnerAlias, - AssigneeDescription: bountyAssignee.Description, - AssigneeRouteHint: bountyAssignee.OwnerRouteHint, - BountyOwnerId: bountyOwner.ID, - OwnerUuid: bountyOwner.Uuid, - OwnerDescription: bountyOwner.Description, - OwnerUniqueName: bountyOwner.UniqueName, - OwnerImg: bountyOwner.Img, - OrganizationName: organization.Name, - OrganizationImg: organization.Img, - WorkspaceUuid: organization.Uuid, - WorkspaceDescription: organization.Description, + NewBounty: bounty, + BountyId: bounty.ID, + Person: bountyOwner, + BountyCreated: bounty.Created, + BountyDescription: bounty.Description, + BountyUpdated: bounty.Updated, + AssigneeId: bountyAssignee.ID, + AssigneeImg: bountyAssignee.Img, + AssigneeAlias: bountyAssignee.OwnerAlias, + AssigneeDescription: bountyAssignee.Description, + AssigneeRouteHint: bountyAssignee.OwnerRouteHint, + BountyOwnerId: bountyOwner.ID, + OwnerUuid: bountyOwner.Uuid, + OwnerDescription: bountyOwner.Description, + OwnerUniqueName: bountyOwner.UniqueName, + OwnerImg: bountyOwner.Img, + OrganizationName: workspace.Name, + OrganizationImg: workspace.Img, + OrganizationUuid: workspace.Uuid, + OrganizationDescription: workspace.Description, + WorkspaceName: workspace.Name, + WorkspaceImg: workspace.Img, + WorkspaceUuid: workspace.Uuid, + WorkspaceDescription: workspace.Description, } metricBountiesData = append(metricBountiesData, bountyData) } return metricBountiesData } -func getMetricsBountyCsv(metricBounties []db.Bounty) []db.MetricsBountyCsv { +func getMetricsBountyCsv(metricBounties []db.NewBounty) []db.MetricsBountyCsv { var metricBountiesCsv []db.MetricsBountyCsv for _, bounty := range metricBounties { bountyOwner := db.DB.GetPersonByPubkey(bounty.OwnerID) bountyAssignee := db.DB.GetPersonByPubkey(bounty.Assignee) - organization := db.DB.GetWorkspaceByUuid(bounty.OrgUuid) + workspace := db.DB.GetWorkspaceByUuid(bounty.WorkspaceUuid) bountyLink := fmt.Sprintf("https://community.sphinx.chat/bounty/%d", bounty.ID) bountyStatus := "Open" @@ -353,7 +378,7 @@ func getMetricsBountyCsv(metricBounties []db.Bounty) []db.MetricsBountyCsv { tm := time.Unix(bounty.Created, 0) bountyCsv := db.MetricsBountyCsv{ DatePosted: &tm, - Organization: organization.Name, + Organization: workspace.Name, BountyAmount: bounty.Price, Provider: bountyOwner.OwnerAlias, Hunter: bountyAssignee.OwnerAlias, diff --git a/handlers/metrics_test.go b/handlers/metrics_test.go index 38695f8ac..d278831a4 100644 --- a/handlers/metrics_test.go +++ b/handlers/metrics_test.go @@ -58,30 +58,34 @@ func TestBountyMetrics(t *testing.T) { db.RedisError = errors.New("redis not initialized") rr := httptest.NewRecorder() handler := http.HandlerFunc(mh.BountyMetrics) + workspace := "test-workspace" + dateRange := db.PaymentDateRange{ StartDate: "1111", EndDate: "2222", } body, _ := json.Marshal(dateRange) - req, err := http.NewRequestWithContext(ctx, http.MethodPost, "/bounty_stats", bytes.NewReader(body)) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, "/bounty_stats?workspace="+workspace, bytes.NewReader(body)) if err != nil { t.Fatal(err) } - mockDb.On("TotalBountiesPosted", dateRange).Return(int64(1)).Once() - mockDb.On("TotalPaidBounties", dateRange).Return(int64(1)).Once() - mockDb.On("BountiesPaidPercentage", dateRange).Return(uint(1)).Once() - mockDb.On("TotalSatsPosted", dateRange).Return(uint(1)).Once() - mockDb.On("TotalSatsPaid", dateRange).Return(uint(1)).Once() - mockDb.On("SatsPaidPercentage", dateRange).Return(uint(1)).Once() - mockDb.On("AveragePaidTime", dateRange).Return(uint(1)).Once() - mockDb.On("AverageCompletedTime", dateRange).Return(uint(1)).Once() - mockDb.On("TotalHuntersPaid", dateRange).Return(int64(1)).Once() - mockDb.On("NewHuntersPaid", dateRange).Return(int64(1)).Once() + mockDb.On("TotalBountiesPosted", dateRange, workspace).Return(int64(1)).Once() + mockDb.On("TotalPaidBounties", dateRange, workspace).Return(int64(1)).Once() + mockDb.On("TotalAssignedBounties", dateRange, workspace).Return(int64(2)).Once() + mockDb.On("BountiesPaidPercentage", dateRange, workspace).Return(uint(1)).Once() + mockDb.On("TotalSatsPosted", dateRange, workspace).Return(uint(1)).Once() + mockDb.On("TotalSatsPaid", dateRange, workspace).Return(uint(1)).Once() + mockDb.On("SatsPaidPercentage", dateRange, workspace).Return(uint(1)).Once() + mockDb.On("AveragePaidTime", dateRange, workspace).Return(uint(1)).Once() + mockDb.On("AverageCompletedTime", dateRange, workspace).Return(uint(1)).Once() + mockDb.On("TotalHuntersPaid", dateRange, workspace).Return(int64(1)).Once() + mockDb.On("NewHuntersPaid", dateRange, workspace).Return(int64(1)).Once() handler.ServeHTTP(rr, req) expectedMetricRes := db.BountyMetrics{ BountiesPosted: 1, BountiesPaid: 1, + BountiesAssigned: 2, BountiesPaidPercentage: 1, SatsPosted: 1, SatsPaid: 1, @@ -148,7 +152,7 @@ func TestMetricsBounties(t *testing.T) { t.Fatal(err) } - bounties := []db.Bounty{ + bounties := []db.NewBounty{ { ID: 1, OwnerID: "owner-1", @@ -194,7 +198,7 @@ func TestMetricsBounties(t *testing.T) { req.URL.RawQuery = "provider=provider1,provider2" // Mock bounties data for multiple providers - bounties := []db.Bounty{ + bounties := []db.NewBounty{ { ID: 1, OwnerID: "provider1", diff --git a/handlers/workspaces.go b/handlers/workspaces.go index 0b152c96d..9e31737e9 100644 --- a/handlers/workspaces.go +++ b/handlers/workspaces.go @@ -126,19 +126,6 @@ func (oh *workspaceHandler) CreateOrEditWorkspace(w http.ResponseWriter, r *http } workspace.Name = name } - } else { - // if workspace.ID == 0 { - // // can't create that already exists - // fmt.Println("can't create existing organization") - // w.WriteHeader(http.StatusUnauthorized) - // return - // } - - // if workspace.ID != existing.ID { // can't edit someone else's - // fmt.Println("cant edit another organization") - // w.WriteHeader(http.StatusUnauthorized) - // return - // } } p, err := oh.db.CreateOrEditWorkspace(workspace) @@ -640,11 +627,11 @@ func GetPaymentHistory(w http.ResponseWriter, r *http.Request) { sender := db.DB.GetPersonByPubkey(payment.SenderPubKey) receiver := db.DB.GetPersonByPubkey(payment.ReceiverPubKey) paymentData := db.PaymentHistoryData{ - PaymentHistory: payment, - SenderName: sender.UniqueName, - SenderImg: sender.Img, - ReceiverName: receiver.UniqueName, - ReceiverImg: receiver.Img, + NewPaymentHistory: payment, + SenderName: sender.UniqueName, + SenderImg: sender.Img, + ReceiverName: receiver.UniqueName, + ReceiverImg: receiver.Img, } paymentHistoryData = append(paymentHistoryData, paymentData) } @@ -795,3 +782,92 @@ func (oh *workspaceHandler) UpdateWorkspace(w http.ResponseWriter, r *http.Reque w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(p) } + +func (oh *workspaceHandler) CreateWorkspaceRepository(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + workspaceRepo := db.WorkspaceRepositories{} + body, _ := io.ReadAll(r.Body) + r.Body.Close() + err := json.Unmarshal(body, &workspaceRepo) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusNotAcceptable) + return + } + + workspaceRepo.CreatedBy = pubKeyFromAuth + + if workspaceRepo.Uuid == "" { + workspaceRepo.Uuid = xid.New().String() + } else { + workspaceRepo.UpdatedBy = pubKeyFromAuth + } + + // Validate struct data + err = db.Validate.Struct(workspaceRepo) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + msg := fmt.Sprintf("Error: did not pass validation test : %s", err) + json.NewEncoder(w).Encode(msg) + return + } + + // Check if workspace exists + workpace := oh.db.GetWorkspaceByUuid(workspaceRepo.WorkspaceUuid) + if workpace.Uuid != workspaceRepo.WorkspaceUuid { + w.WriteHeader(http.StatusUnauthorized) + json.NewEncoder(w).Encode("Workspace does not exists") + return + } + + p, err := oh.db.CreateWorkspaceRepository(workspaceRepo) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(p) +} + +func (oh *workspaceHandler) GetWorkspaceRepositorByWorkspaceUuid(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + uuid := chi.URLParam(r, "uuid") + workspaceFeatures := oh.db.GetWorkspaceRepositorByWorkspaceUuid(uuid) + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(workspaceFeatures) +} + +// New method for getting features by workspace uuid + +func (oh *workspaceHandler) GetFeaturesByWorkspaceUuid(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) + if pubKeyFromAuth == "" { + fmt.Println("no pubkey from auth") + w.WriteHeader(http.StatusUnauthorized) + return + } + + uuid := chi.URLParam(r, "workspace_uuid") + workspaceFeatures := oh.db.GetFeaturesByWorkspaceUuid(uuid, r) + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(workspaceFeatures) +} diff --git a/mocks/Database.go b/mocks/Database.go index 784a2492a..f9adc0bea 100644 --- a/mocks/Database.go +++ b/mocks/Database.go @@ -311,17 +311,17 @@ func (_c *Database_AddUserInvoiceData_Call) RunAndReturn(run func(db.UserInvoice return _c } -// AverageCompletedTime provides a mock function with given fields: r -func (_m *Database) AverageCompletedTime(r db.PaymentDateRange) uint { - ret := _m.Called(r) +// AverageCompletedTime provides a mock function with given fields: r, workspace +func (_m *Database) AverageCompletedTime(r db.PaymentDateRange, workspace string) uint { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for AverageCompletedTime") } var r0 uint - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) uint); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) uint); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(uint) } @@ -336,13 +336,14 @@ type Database_AverageCompletedTime_Call struct { // AverageCompletedTime is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) AverageCompletedTime(r interface{}) *Database_AverageCompletedTime_Call { - return &Database_AverageCompletedTime_Call{Call: _e.mock.On("AverageCompletedTime", r)} +// - workspace string +func (_e *Database_Expecter) AverageCompletedTime(r interface{}, workspace interface{}) *Database_AverageCompletedTime_Call { + return &Database_AverageCompletedTime_Call{Call: _e.mock.On("AverageCompletedTime", r, workspace)} } -func (_c *Database_AverageCompletedTime_Call) Run(run func(r db.PaymentDateRange)) *Database_AverageCompletedTime_Call { +func (_c *Database_AverageCompletedTime_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_AverageCompletedTime_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -352,22 +353,22 @@ func (_c *Database_AverageCompletedTime_Call) Return(_a0 uint) *Database_Average return _c } -func (_c *Database_AverageCompletedTime_Call) RunAndReturn(run func(db.PaymentDateRange) uint) *Database_AverageCompletedTime_Call { +func (_c *Database_AverageCompletedTime_Call) RunAndReturn(run func(db.PaymentDateRange, string) uint) *Database_AverageCompletedTime_Call { _c.Call.Return(run) return _c } -// AveragePaidTime provides a mock function with given fields: r -func (_m *Database) AveragePaidTime(r db.PaymentDateRange) uint { - ret := _m.Called(r) +// AveragePaidTime provides a mock function with given fields: r, workspace +func (_m *Database) AveragePaidTime(r db.PaymentDateRange, workspace string) uint { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for AveragePaidTime") } var r0 uint - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) uint); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) uint); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(uint) } @@ -382,13 +383,14 @@ type Database_AveragePaidTime_Call struct { // AveragePaidTime is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) AveragePaidTime(r interface{}) *Database_AveragePaidTime_Call { - return &Database_AveragePaidTime_Call{Call: _e.mock.On("AveragePaidTime", r)} +// - workspace string +func (_e *Database_Expecter) AveragePaidTime(r interface{}, workspace interface{}) *Database_AveragePaidTime_Call { + return &Database_AveragePaidTime_Call{Call: _e.mock.On("AveragePaidTime", r, workspace)} } -func (_c *Database_AveragePaidTime_Call) Run(run func(r db.PaymentDateRange)) *Database_AveragePaidTime_Call { +func (_c *Database_AveragePaidTime_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_AveragePaidTime_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -398,22 +400,22 @@ func (_c *Database_AveragePaidTime_Call) Return(_a0 uint) *Database_AveragePaidT return _c } -func (_c *Database_AveragePaidTime_Call) RunAndReturn(run func(db.PaymentDateRange) uint) *Database_AveragePaidTime_Call { +func (_c *Database_AveragePaidTime_Call) RunAndReturn(run func(db.PaymentDateRange, string) uint) *Database_AveragePaidTime_Call { _c.Call.Return(run) return _c } -// BountiesPaidPercentage provides a mock function with given fields: r -func (_m *Database) BountiesPaidPercentage(r db.PaymentDateRange) uint { - ret := _m.Called(r) +// BountiesPaidPercentage provides a mock function with given fields: r, workspace +func (_m *Database) BountiesPaidPercentage(r db.PaymentDateRange, workspace string) uint { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for BountiesPaidPercentage") } var r0 uint - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) uint); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) uint); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(uint) } @@ -428,13 +430,14 @@ type Database_BountiesPaidPercentage_Call struct { // BountiesPaidPercentage is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) BountiesPaidPercentage(r interface{}) *Database_BountiesPaidPercentage_Call { - return &Database_BountiesPaidPercentage_Call{Call: _e.mock.On("BountiesPaidPercentage", r)} +// - workspace string +func (_e *Database_Expecter) BountiesPaidPercentage(r interface{}, workspace interface{}) *Database_BountiesPaidPercentage_Call { + return &Database_BountiesPaidPercentage_Call{Call: _e.mock.On("BountiesPaidPercentage", r, workspace)} } -func (_c *Database_BountiesPaidPercentage_Call) Run(run func(r db.PaymentDateRange)) *Database_BountiesPaidPercentage_Call { +func (_c *Database_BountiesPaidPercentage_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_BountiesPaidPercentage_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -444,7 +447,44 @@ func (_c *Database_BountiesPaidPercentage_Call) Return(_a0 uint) *Database_Bount return _c } -func (_c *Database_BountiesPaidPercentage_Call) RunAndReturn(run func(db.PaymentDateRange) uint) *Database_BountiesPaidPercentage_Call { +func (_c *Database_BountiesPaidPercentage_Call) RunAndReturn(run func(db.PaymentDateRange, string) uint) *Database_BountiesPaidPercentage_Call { + _c.Call.Return(run) + return _c +} + +// DeleteFeatureByUuid provides a mock function with given fields: uuid +func (_m *Database) DeleteFeatureByUuid(uuid string) error { + ret := _m.Called(uuid) + if len(ret) == 0 { + panic("no return value specified for DeleteFeatureByUuid") + } + return ret.Error(0) +} + +// Database_DeleteFeatureByUuid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteFeatureByUuid' +type Database_DeleteFeatureByUuid_Call struct { + *mock.Call +} + +// DeleteFeatureByUuid is a helper method to define mock.On call +// - uuid string +func (_e *Database_Expecter) DeleteFeatureByUuid(uuid interface{}) *Database_DeleteFeatureByUuid_Call { + return &Database_DeleteFeatureByUuid_Call{Call: _e.mock.On("DeleteFeatureByUuid", uuid)} +} + +func (_c *Database_DeleteFeatureByUuid_Call) Run(run func(uuid string)) *Database_DeleteFeatureByUuid_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Database_DeleteFeatureByUuid_Call) Return(_a0 error) *Database_DeleteFeatureByUuid_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_DeleteFeatureByUuid_Call) RunAndReturn(run func(string) error) *Database_DeleteFeatureByUuid_Call { _c.Call.Return(run) return _c } @@ -927,6 +967,174 @@ func (_c *Database_CreateOrEditBounty_Call) RunAndReturn(run func(db.NewBounty) return _c } +// CreateOrEditFeature provides a mock function with given fields: m +func (_m *Database) CreateOrEditFeature(m db.WorkspaceFeatures) (db.WorkspaceFeatures, error) { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for CreateOrEditFeature") + } + + var r0 db.WorkspaceFeatures + var r1 error + if rf, ok := ret.Get(0).(func(db.WorkspaceFeatures) (db.WorkspaceFeatures, error)); ok { + return rf(m) + } + if rf, ok := ret.Get(0).(func(db.WorkspaceFeatures) db.WorkspaceFeatures); ok { + r0 = rf(m) + } else { + r0 = ret.Get(0).(db.WorkspaceFeatures) + } + + if rf, ok := ret.Get(1).(func(db.WorkspaceFeatures) error); ok { + r1 = rf(m) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Database_CreateOrEditFeature_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateOrEditFeature' +type Database_CreateOrEditFeature_Call struct { + *mock.Call +} + +// CreateOrEditFeature is a helper method to define mock.On call +// - m db.WorkspaceFeatures +func (_e *Database_Expecter) CreateOrEditFeature(m interface{}) *Database_CreateOrEditFeature_Call { + return &Database_CreateOrEditFeature_Call{Call: _e.mock.On("CreateOrEditFeature", m)} +} + +func (_c *Database_CreateOrEditFeature_Call) Run(run func(m db.WorkspaceFeatures)) *Database_CreateOrEditFeature_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(db.WorkspaceFeatures)) + }) + return _c +} + +func (_c *Database_CreateOrEditFeature_Call) Return(_a0 db.WorkspaceFeatures, _a1 error) *Database_CreateOrEditFeature_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Database_CreateOrEditFeature_Call) RunAndReturn(run func(db.WorkspaceFeatures) (db.WorkspaceFeatures, error)) *Database_CreateOrEditFeature_Call { + _c.Call.Return(run) + return _c +} + +// CreateOrEditFeaturePhase provides a mock function with given fields: phase +func (_m *Database) CreateOrEditFeaturePhase(phase db.FeaturePhase) (db.FeaturePhase, error) { + ret := _m.Called(phase) + + if len(ret) == 0 { + panic("no return value specified for CreateOrEditFeaturePhase") + } + + var r0 db.FeaturePhase + var r1 error + if rf, ok := ret.Get(0).(func(db.FeaturePhase) (db.FeaturePhase, error)); ok { + return rf(phase) + } + if rf, ok := ret.Get(0).(func(db.FeaturePhase) db.FeaturePhase); ok { + r0 = rf(phase) + } else { + r0 = ret.Get(0).(db.FeaturePhase) + } + + if rf, ok := ret.Get(1).(func(db.FeaturePhase) error); ok { + r1 = rf(phase) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Database_CreateOrEditFeaturePhase_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateOrEditFeaturePhase' +type Database_CreateOrEditFeaturePhase_Call struct { + *mock.Call +} + +// CreateOrEditFeaturePhase is a helper method to define mock.On call +// - phase db.FeaturePhase +func (_e *Database_Expecter) CreateOrEditFeaturePhase(phase interface{}) *Database_CreateOrEditFeaturePhase_Call { + return &Database_CreateOrEditFeaturePhase_Call{Call: _e.mock.On("CreateOrEditFeaturePhase", phase)} +} + +func (_c *Database_CreateOrEditFeaturePhase_Call) Run(run func(phase db.FeaturePhase)) *Database_CreateOrEditFeaturePhase_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(db.FeaturePhase)) + }) + return _c +} + +func (_c *Database_CreateOrEditFeaturePhase_Call) Return(_a0 db.FeaturePhase, _a1 error) *Database_CreateOrEditFeaturePhase_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Database_CreateOrEditFeaturePhase_Call) RunAndReturn(run func(db.FeaturePhase) (db.FeaturePhase, error)) *Database_CreateOrEditFeaturePhase_Call { + _c.Call.Return(run) + return _c +} + +// CreateOrEditFeatureStory provides a mock function with given fields: story +func (_m *Database) CreateOrEditFeatureStory(story db.FeatureStory) (db.FeatureStory, error) { + ret := _m.Called(story) + + if len(ret) == 0 { + panic("no return value specified for CreateOrEditFeatureStory") + } + + var r0 db.FeatureStory + var r1 error + if rf, ok := ret.Get(0).(func(db.FeatureStory) (db.FeatureStory, error)); ok { + return rf(story) + } + if rf, ok := ret.Get(0).(func(db.FeatureStory) db.FeatureStory); ok { + r0 = rf(story) + } else { + r0 = ret.Get(0).(db.FeatureStory) + } + + if rf, ok := ret.Get(1).(func(db.FeatureStory) error); ok { + r1 = rf(story) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Database_CreateOrEditFeatureStory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateOrEditFeatureStory' +type Database_CreateOrEditFeatureStory_Call struct { + *mock.Call +} + +// CreateOrEditFeatureStory is a helper method to define mock.On call +// - story db.FeatureStory +func (_e *Database_Expecter) CreateOrEditFeatureStory(story interface{}) *Database_CreateOrEditFeatureStory_Call { + return &Database_CreateOrEditFeatureStory_Call{Call: _e.mock.On("CreateOrEditFeatureStory", story)} +} + +func (_c *Database_CreateOrEditFeatureStory_Call) Run(run func(story db.FeatureStory)) *Database_CreateOrEditFeatureStory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(db.FeatureStory)) + }) + return _c +} + +func (_c *Database_CreateOrEditFeatureStory_Call) Return(_a0 db.FeatureStory, _a1 error) *Database_CreateOrEditFeatureStory_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Database_CreateOrEditFeatureStory_Call) RunAndReturn(run func(db.FeatureStory) (db.FeatureStory, error)) *Database_CreateOrEditFeatureStory_Call { + _c.Call.Return(run) + return _c +} + // CreateOrEditPerson provides a mock function with given fields: m func (_m *Database) CreateOrEditPerson(m db.Person) (db.Person, error) { ret := _m.Called(m) @@ -1191,6 +1399,62 @@ func (_c *Database_CreateWorkspaceBudget_Call) RunAndReturn(run func(db.NewBount return _c } +// CreateWorkspaceRepository provides a mock function with given fields: m +func (_m *Database) CreateWorkspaceRepository(m db.WorkspaceRepositories) (db.WorkspaceRepositories, error) { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for CreateWorkspaceRepository") + } + + var r0 db.WorkspaceRepositories + var r1 error + if rf, ok := ret.Get(0).(func(db.WorkspaceRepositories) (db.WorkspaceRepositories, error)); ok { + return rf(m) + } + if rf, ok := ret.Get(0).(func(db.WorkspaceRepositories) db.WorkspaceRepositories); ok { + r0 = rf(m) + } else { + r0 = ret.Get(0).(db.WorkspaceRepositories) + } + + if rf, ok := ret.Get(1).(func(db.WorkspaceRepositories) error); ok { + r1 = rf(m) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Database_CreateWorkspaceRepository_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateWorkspaceRepository' +type Database_CreateWorkspaceRepository_Call struct { + *mock.Call +} + +// CreateWorkspaceRepository is a helper method to define mock.On call +// - m db.WorkspaceRepositories +func (_e *Database_Expecter) CreateWorkspaceRepository(m interface{}) *Database_CreateWorkspaceRepository_Call { + return &Database_CreateWorkspaceRepository_Call{Call: _e.mock.On("CreateWorkspaceRepository", m)} +} + +func (_c *Database_CreateWorkspaceRepository_Call) Run(run func(m db.WorkspaceRepositories)) *Database_CreateWorkspaceRepository_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(db.WorkspaceRepositories)) + }) + return _c +} + +func (_c *Database_CreateWorkspaceRepository_Call) Return(_a0 db.WorkspaceRepositories, _a1 error) *Database_CreateWorkspaceRepository_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Database_CreateWorkspaceRepository_Call) RunAndReturn(run func(db.WorkspaceRepositories) (db.WorkspaceRepositories, error)) *Database_CreateWorkspaceRepository_Call { + _c.Call.Return(run) + return _c +} + // CreateWorkspaceUser provides a mock function with given fields: orgUser func (_m *Database) CreateWorkspaceUser(orgUser db.WorkspaceUsers) db.WorkspaceUsers { ret := _m.Called(orgUser) @@ -1340,6 +1604,100 @@ func (_c *Database_DeleteBounty_Call) RunAndReturn(run func(string, string) (db. return _c } +// DeleteFeaturePhase provides a mock function with given fields: featureUuid, phaseUuid +func (_m *Database) DeleteFeaturePhase(featureUuid string, phaseUuid string) error { + ret := _m.Called(featureUuid, phaseUuid) + + if len(ret) == 0 { + panic("no return value specified for DeleteFeaturePhase") + } + + var r0 error + if rf, ok := ret.Get(0).(func(string, string) error); ok { + r0 = rf(featureUuid, phaseUuid) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Database_DeleteFeaturePhase_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteFeaturePhase' +type Database_DeleteFeaturePhase_Call struct { + *mock.Call +} + +// DeleteFeaturePhase is a helper method to define mock.On call +// - featureUuid string +// - phaseUuid string +func (_e *Database_Expecter) DeleteFeaturePhase(featureUuid interface{}, phaseUuid interface{}) *Database_DeleteFeaturePhase_Call { + return &Database_DeleteFeaturePhase_Call{Call: _e.mock.On("DeleteFeaturePhase", featureUuid, phaseUuid)} +} + +func (_c *Database_DeleteFeaturePhase_Call) Run(run func(featureUuid string, phaseUuid string)) *Database_DeleteFeaturePhase_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *Database_DeleteFeaturePhase_Call) Return(_a0 error) *Database_DeleteFeaturePhase_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_DeleteFeaturePhase_Call) RunAndReturn(run func(string, string) error) *Database_DeleteFeaturePhase_Call { + _c.Call.Return(run) + return _c +} + +// DeleteFeatureStoryByUuid provides a mock function with given fields: featureUuid, storyUuid +func (_m *Database) DeleteFeatureStoryByUuid(featureUuid string, storyUuid string) error { + ret := _m.Called(featureUuid, storyUuid) + + if len(ret) == 0 { + panic("no return value specified for DeleteFeatureStoryByUuid") + } + + var r0 error + if rf, ok := ret.Get(0).(func(string, string) error); ok { + r0 = rf(featureUuid, storyUuid) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Database_DeleteFeatureStoryByUuid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteFeatureStoryByUuid' +type Database_DeleteFeatureStoryByUuid_Call struct { + *mock.Call +} + +// DeleteFeatureStoryByUuid is a helper method to define mock.On call +// - featureUuid string +// - storyUuid string +func (_e *Database_Expecter) DeleteFeatureStoryByUuid(featureUuid interface{}, storyUuid interface{}) *Database_DeleteFeatureStoryByUuid_Call { + return &Database_DeleteFeatureStoryByUuid_Call{Call: _e.mock.On("DeleteFeatureStoryByUuid", featureUuid, storyUuid)} +} + +func (_c *Database_DeleteFeatureStoryByUuid_Call) Run(run func(featureUuid string, storyUuid string)) *Database_DeleteFeatureStoryByUuid_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *Database_DeleteFeatureStoryByUuid_Call) Return(_a0 error) *Database_DeleteFeatureStoryByUuid_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_DeleteFeatureStoryByUuid_Call) RunAndReturn(run func(string, string) error) *Database_DeleteFeatureStoryByUuid_Call { + _c.Call.Return(run) + return _c +} + // DeleteUserInvoiceData provides a mock function with given fields: payment_request func (_m *Database) DeleteUserInvoiceData(payment_request string) db.UserInvoiceData { ret := _m.Called(payment_request) @@ -1775,19 +2133,19 @@ func (_c *Database_GetBotsByOwner_Call) RunAndReturn(run func(string) []db.Bot) } // GetBountiesByDateRange provides a mock function with given fields: r, re -func (_m *Database) GetBountiesByDateRange(r db.PaymentDateRange, re *http.Request) []db.Bounty { +func (_m *Database) GetBountiesByDateRange(r db.PaymentDateRange, re *http.Request) []db.NewBounty { ret := _m.Called(r, re) if len(ret) == 0 { panic("no return value specified for GetBountiesByDateRange") } - var r0 []db.Bounty - if rf, ok := ret.Get(0).(func(db.PaymentDateRange, *http.Request) []db.Bounty); ok { + var r0 []db.NewBounty + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, *http.Request) []db.NewBounty); ok { r0 = rf(r, re) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]db.Bounty) + r0 = ret.Get(0).([]db.NewBounty) } } @@ -1813,12 +2171,12 @@ func (_c *Database_GetBountiesByDateRange_Call) Run(run func(r db.PaymentDateRan return _c } -func (_c *Database_GetBountiesByDateRange_Call) Return(_a0 []db.Bounty) *Database_GetBountiesByDateRange_Call { +func (_c *Database_GetBountiesByDateRange_Call) Return(_a0 []db.NewBounty) *Database_GetBountiesByDateRange_Call { _c.Call.Return(_a0) return _c } -func (_c *Database_GetBountiesByDateRange_Call) RunAndReturn(run func(db.PaymentDateRange, *http.Request) []db.Bounty) *Database_GetBountiesByDateRange_Call { +func (_c *Database_GetBountiesByDateRange_Call) RunAndReturn(run func(db.PaymentDateRange, *http.Request) []db.NewBounty) *Database_GetBountiesByDateRange_Call { _c.Call.Return(run) return _c } @@ -2331,191 +2689,458 @@ func (_m *Database) GetChannel(id uint) db.Channel { panic("no return value specified for GetChannel") } - var r0 db.Channel - if rf, ok := ret.Get(0).(func(uint) db.Channel); ok { - r0 = rf(id) + var r0 db.Channel + if rf, ok := ret.Get(0).(func(uint) db.Channel); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(db.Channel) + } + + return r0 +} + +// Database_GetChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetChannel' +type Database_GetChannel_Call struct { + *mock.Call +} + +// GetChannel is a helper method to define mock.On call +// - id uint +func (_e *Database_Expecter) GetChannel(id interface{}) *Database_GetChannel_Call { + return &Database_GetChannel_Call{Call: _e.mock.On("GetChannel", id)} +} + +func (_c *Database_GetChannel_Call) Run(run func(id uint)) *Database_GetChannel_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint)) + }) + return _c +} + +func (_c *Database_GetChannel_Call) Return(_a0 db.Channel) *Database_GetChannel_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_GetChannel_Call) RunAndReturn(run func(uint) db.Channel) *Database_GetChannel_Call { + _c.Call.Return(run) + return _c +} + +// GetChannelsByTribe provides a mock function with given fields: tribe_uuid +func (_m *Database) GetChannelsByTribe(tribe_uuid string) []db.Channel { + ret := _m.Called(tribe_uuid) + + if len(ret) == 0 { + panic("no return value specified for GetChannelsByTribe") + } + + var r0 []db.Channel + if rf, ok := ret.Get(0).(func(string) []db.Channel); ok { + r0 = rf(tribe_uuid) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]db.Channel) + } + } + + return r0 +} + +// Database_GetChannelsByTribe_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetChannelsByTribe' +type Database_GetChannelsByTribe_Call struct { + *mock.Call +} + +// GetChannelsByTribe is a helper method to define mock.On call +// - tribe_uuid string +func (_e *Database_Expecter) GetChannelsByTribe(tribe_uuid interface{}) *Database_GetChannelsByTribe_Call { + return &Database_GetChannelsByTribe_Call{Call: _e.mock.On("GetChannelsByTribe", tribe_uuid)} +} + +func (_c *Database_GetChannelsByTribe_Call) Run(run func(tribe_uuid string)) *Database_GetChannelsByTribe_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Database_GetChannelsByTribe_Call) Return(_a0 []db.Channel) *Database_GetChannelsByTribe_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_GetChannelsByTribe_Call) RunAndReturn(run func(string) []db.Channel) *Database_GetChannelsByTribe_Call { + _c.Call.Return(run) + return _c +} + +// GetConnectionCode provides a mock function with given fields: +func (_m *Database) GetConnectionCode() db.ConnectionCodesShort { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetConnectionCode") + } + + var r0 db.ConnectionCodesShort + if rf, ok := ret.Get(0).(func() db.ConnectionCodesShort); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(db.ConnectionCodesShort) + } + + return r0 +} + +// Database_GetConnectionCode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetConnectionCode' +type Database_GetConnectionCode_Call struct { + *mock.Call +} + +// GetConnectionCode is a helper method to define mock.On call +func (_e *Database_Expecter) GetConnectionCode() *Database_GetConnectionCode_Call { + return &Database_GetConnectionCode_Call{Call: _e.mock.On("GetConnectionCode")} +} + +func (_c *Database_GetConnectionCode_Call) Run(run func()) *Database_GetConnectionCode_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Database_GetConnectionCode_Call) Return(_a0 db.ConnectionCodesShort) *Database_GetConnectionCode_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_GetConnectionCode_Call) RunAndReturn(run func() db.ConnectionCodesShort) *Database_GetConnectionCode_Call { + _c.Call.Return(run) + return _c +} + +// GetCreatedBounties provides a mock function with given fields: r +func (_m *Database) GetCreatedBounties(r *http.Request) ([]db.NewBounty, error) { + ret := _m.Called(r) + + if len(ret) == 0 { + panic("no return value specified for GetCreatedBounties") + } + + var r0 []db.NewBounty + var r1 error + if rf, ok := ret.Get(0).(func(*http.Request) ([]db.NewBounty, error)); ok { + return rf(r) + } + if rf, ok := ret.Get(0).(func(*http.Request) []db.NewBounty); ok { + r0 = rf(r) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]db.NewBounty) + } + } + + if rf, ok := ret.Get(1).(func(*http.Request) error); ok { + r1 = rf(r) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Database_GetCreatedBounties_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCreatedBounties' +type Database_GetCreatedBounties_Call struct { + *mock.Call +} + +// GetCreatedBounties is a helper method to define mock.On call +// - r *http.Request +func (_e *Database_Expecter) GetCreatedBounties(r interface{}) *Database_GetCreatedBounties_Call { + return &Database_GetCreatedBounties_Call{Call: _e.mock.On("GetCreatedBounties", r)} +} + +func (_c *Database_GetCreatedBounties_Call) Run(run func(r *http.Request)) *Database_GetCreatedBounties_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*http.Request)) + }) + return _c +} + +func (_c *Database_GetCreatedBounties_Call) Return(_a0 []db.NewBounty, _a1 error) *Database_GetCreatedBounties_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Database_GetCreatedBounties_Call) RunAndReturn(run func(*http.Request) ([]db.NewBounty, error)) *Database_GetCreatedBounties_Call { + _c.Call.Return(run) + return _c +} + +// GetFeatureByUuid provides a mock function with given fields: uuid +func (_m *Database) GetFeatureByUuid(uuid string) db.WorkspaceFeatures { + ret := _m.Called(uuid) + + if len(ret) == 0 { + panic("no return value specified for GetFeatureByUuid") + } + + var r0 db.WorkspaceFeatures + if rf, ok := ret.Get(0).(func(string) db.WorkspaceFeatures); ok { + r0 = rf(uuid) + } else { + r0 = ret.Get(0).(db.WorkspaceFeatures) + } + + return r0 +} + +// Database_GetFeatureByUuid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeatureByUuid' +type Database_GetFeatureByUuid_Call struct { + *mock.Call +} + +// GetFeatureByUuid is a helper method to define mock.On call +// - uuid string +func (_e *Database_Expecter) GetFeatureByUuid(uuid interface{}) *Database_GetFeatureByUuid_Call { + return &Database_GetFeatureByUuid_Call{Call: _e.mock.On("GetFeatureByUuid", uuid)} +} + +func (_c *Database_GetFeatureByUuid_Call) Run(run func(uuid string)) *Database_GetFeatureByUuid_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Database_GetFeatureByUuid_Call) Return(_a0 db.WorkspaceFeatures) *Database_GetFeatureByUuid_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_GetFeatureByUuid_Call) RunAndReturn(run func(string) db.WorkspaceFeatures) *Database_GetFeatureByUuid_Call { + _c.Call.Return(run) + return _c +} + +// GetFeaturePhaseByUuid provides a mock function with given fields: featureUuid, phaseUuid +func (_m *Database) GetFeaturePhaseByUuid(featureUuid string, phaseUuid string) (db.FeaturePhase, error) { + ret := _m.Called(featureUuid, phaseUuid) + + if len(ret) == 0 { + panic("no return value specified for GetFeaturePhaseByUuid") + } + + var r0 db.FeaturePhase + var r1 error + if rf, ok := ret.Get(0).(func(string, string) (db.FeaturePhase, error)); ok { + return rf(featureUuid, phaseUuid) + } + if rf, ok := ret.Get(0).(func(string, string) db.FeaturePhase); ok { + r0 = rf(featureUuid, phaseUuid) + } else { + r0 = ret.Get(0).(db.FeaturePhase) + } + + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(featureUuid, phaseUuid) } else { - r0 = ret.Get(0).(db.Channel) + r1 = ret.Error(1) } - return r0 + return r0, r1 } -// Database_GetChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetChannel' -type Database_GetChannel_Call struct { +// Database_GetFeaturePhaseByUuid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeaturePhaseByUuid' +type Database_GetFeaturePhaseByUuid_Call struct { *mock.Call } -// GetChannel is a helper method to define mock.On call -// - id uint -func (_e *Database_Expecter) GetChannel(id interface{}) *Database_GetChannel_Call { - return &Database_GetChannel_Call{Call: _e.mock.On("GetChannel", id)} +// GetFeaturePhaseByUuid is a helper method to define mock.On call +// - featureUuid string +// - phaseUuid string +func (_e *Database_Expecter) GetFeaturePhaseByUuid(featureUuid interface{}, phaseUuid interface{}) *Database_GetFeaturePhaseByUuid_Call { + return &Database_GetFeaturePhaseByUuid_Call{Call: _e.mock.On("GetFeaturePhaseByUuid", featureUuid, phaseUuid)} } -func (_c *Database_GetChannel_Call) Run(run func(id uint)) *Database_GetChannel_Call { +func (_c *Database_GetFeaturePhaseByUuid_Call) Run(run func(featureUuid string, phaseUuid string)) *Database_GetFeaturePhaseByUuid_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(uint)) + run(args[0].(string), args[1].(string)) }) return _c } -func (_c *Database_GetChannel_Call) Return(_a0 db.Channel) *Database_GetChannel_Call { - _c.Call.Return(_a0) +func (_c *Database_GetFeaturePhaseByUuid_Call) Return(_a0 db.FeaturePhase, _a1 error) *Database_GetFeaturePhaseByUuid_Call { + _c.Call.Return(_a0, _a1) return _c } -func (_c *Database_GetChannel_Call) RunAndReturn(run func(uint) db.Channel) *Database_GetChannel_Call { +func (_c *Database_GetFeaturePhaseByUuid_Call) RunAndReturn(run func(string, string) (db.FeaturePhase, error)) *Database_GetFeaturePhaseByUuid_Call { _c.Call.Return(run) return _c } -// GetChannelsByTribe provides a mock function with given fields: tribe_uuid -func (_m *Database) GetChannelsByTribe(tribe_uuid string) []db.Channel { - ret := _m.Called(tribe_uuid) +// GetFeatureStoriesByFeatureUuid provides a mock function with given fields: featureUuid +func (_m *Database) GetFeatureStoriesByFeatureUuid(featureUuid string) ([]db.FeatureStory, error) { + ret := _m.Called(featureUuid) if len(ret) == 0 { - panic("no return value specified for GetChannelsByTribe") + panic("no return value specified for GetFeatureStoriesByFeatureUuid") } - var r0 []db.Channel - if rf, ok := ret.Get(0).(func(string) []db.Channel); ok { - r0 = rf(tribe_uuid) + var r0 []db.FeatureStory + var r1 error + if rf, ok := ret.Get(0).(func(string) ([]db.FeatureStory, error)); ok { + return rf(featureUuid) + } + if rf, ok := ret.Get(0).(func(string) []db.FeatureStory); ok { + r0 = rf(featureUuid) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]db.Channel) + r0 = ret.Get(0).([]db.FeatureStory) } } - return r0 + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(featureUuid) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } -// Database_GetChannelsByTribe_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetChannelsByTribe' -type Database_GetChannelsByTribe_Call struct { +// Database_GetFeatureStoriesByFeatureUuid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeatureStoriesByFeatureUuid' +type Database_GetFeatureStoriesByFeatureUuid_Call struct { *mock.Call } -// GetChannelsByTribe is a helper method to define mock.On call -// - tribe_uuid string -func (_e *Database_Expecter) GetChannelsByTribe(tribe_uuid interface{}) *Database_GetChannelsByTribe_Call { - return &Database_GetChannelsByTribe_Call{Call: _e.mock.On("GetChannelsByTribe", tribe_uuid)} +// GetFeatureStoriesByFeatureUuid is a helper method to define mock.On call +// - featureUuid string +func (_e *Database_Expecter) GetFeatureStoriesByFeatureUuid(featureUuid interface{}) *Database_GetFeatureStoriesByFeatureUuid_Call { + return &Database_GetFeatureStoriesByFeatureUuid_Call{Call: _e.mock.On("GetFeatureStoriesByFeatureUuid", featureUuid)} } -func (_c *Database_GetChannelsByTribe_Call) Run(run func(tribe_uuid string)) *Database_GetChannelsByTribe_Call { +func (_c *Database_GetFeatureStoriesByFeatureUuid_Call) Run(run func(featureUuid string)) *Database_GetFeatureStoriesByFeatureUuid_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(string)) }) return _c } -func (_c *Database_GetChannelsByTribe_Call) Return(_a0 []db.Channel) *Database_GetChannelsByTribe_Call { - _c.Call.Return(_a0) +func (_c *Database_GetFeatureStoriesByFeatureUuid_Call) Return(_a0 []db.FeatureStory, _a1 error) *Database_GetFeatureStoriesByFeatureUuid_Call { + _c.Call.Return(_a0, _a1) return _c } -func (_c *Database_GetChannelsByTribe_Call) RunAndReturn(run func(string) []db.Channel) *Database_GetChannelsByTribe_Call { +func (_c *Database_GetFeatureStoriesByFeatureUuid_Call) RunAndReturn(run func(string) ([]db.FeatureStory, error)) *Database_GetFeatureStoriesByFeatureUuid_Call { _c.Call.Return(run) return _c } -// GetConnectionCode provides a mock function with given fields: -func (_m *Database) GetConnectionCode() db.ConnectionCodesShort { - ret := _m.Called() +// GetFeatureStoryByUuid provides a mock function with given fields: featureUuid, storyUuid +func (_m *Database) GetFeatureStoryByUuid(featureUuid string, storyUuid string) (db.FeatureStory, error) { + ret := _m.Called(featureUuid, storyUuid) if len(ret) == 0 { - panic("no return value specified for GetConnectionCode") + panic("no return value specified for GetFeatureStoryByUuid") } - var r0 db.ConnectionCodesShort - if rf, ok := ret.Get(0).(func() db.ConnectionCodesShort); ok { - r0 = rf() + var r0 db.FeatureStory + var r1 error + if rf, ok := ret.Get(0).(func(string, string) (db.FeatureStory, error)); ok { + return rf(featureUuid, storyUuid) + } + if rf, ok := ret.Get(0).(func(string, string) db.FeatureStory); ok { + r0 = rf(featureUuid, storyUuid) } else { - r0 = ret.Get(0).(db.ConnectionCodesShort) + r0 = ret.Get(0).(db.FeatureStory) } - return r0 + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(featureUuid, storyUuid) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } -// Database_GetConnectionCode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetConnectionCode' -type Database_GetConnectionCode_Call struct { +// Database_GetFeatureStoryByUuid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeatureStoryByUuid' +type Database_GetFeatureStoryByUuid_Call struct { *mock.Call } -// GetConnectionCode is a helper method to define mock.On call -func (_e *Database_Expecter) GetConnectionCode() *Database_GetConnectionCode_Call { - return &Database_GetConnectionCode_Call{Call: _e.mock.On("GetConnectionCode")} +// GetFeatureStoryByUuid is a helper method to define mock.On call +// - featureUuid string +// - storyUuid string +func (_e *Database_Expecter) GetFeatureStoryByUuid(featureUuid interface{}, storyUuid interface{}) *Database_GetFeatureStoryByUuid_Call { + return &Database_GetFeatureStoryByUuid_Call{Call: _e.mock.On("GetFeatureStoryByUuid", featureUuid, storyUuid)} } -func (_c *Database_GetConnectionCode_Call) Run(run func()) *Database_GetConnectionCode_Call { +func (_c *Database_GetFeatureStoryByUuid_Call) Run(run func(featureUuid string, storyUuid string)) *Database_GetFeatureStoryByUuid_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(string), args[1].(string)) }) return _c } -func (_c *Database_GetConnectionCode_Call) Return(_a0 db.ConnectionCodesShort) *Database_GetConnectionCode_Call { - _c.Call.Return(_a0) +func (_c *Database_GetFeatureStoryByUuid_Call) Return(_a0 db.FeatureStory, _a1 error) *Database_GetFeatureStoryByUuid_Call { + _c.Call.Return(_a0, _a1) return _c } -func (_c *Database_GetConnectionCode_Call) RunAndReturn(run func() db.ConnectionCodesShort) *Database_GetConnectionCode_Call { +func (_c *Database_GetFeatureStoryByUuid_Call) RunAndReturn(run func(string, string) (db.FeatureStory, error)) *Database_GetFeatureStoryByUuid_Call { _c.Call.Return(run) return _c } -// GetCreatedBounties provides a mock function with given fields: r -func (_m *Database) GetCreatedBounties(r *http.Request) ([]db.NewBounty, error) { - ret := _m.Called(r) +// GetFeaturesByWorkspaceUuid provides a mock function with given fields: uuid, r +func (_m *Database) GetFeaturesByWorkspaceUuid(uuid string, r *http.Request) []db.WorkspaceFeatures { + ret := _m.Called(uuid, r) if len(ret) == 0 { - panic("no return value specified for GetCreatedBounties") + panic("no return value specified for GetFeaturesByWorkspaceUuid") } - var r0 []db.NewBounty - var r1 error - if rf, ok := ret.Get(0).(func(*http.Request) ([]db.NewBounty, error)); ok { - return rf(r) - } - if rf, ok := ret.Get(0).(func(*http.Request) []db.NewBounty); ok { - r0 = rf(r) + var r0 []db.WorkspaceFeatures + if rf, ok := ret.Get(0).(func(string, *http.Request) []db.WorkspaceFeatures); ok { + r0 = rf(uuid, r) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]db.NewBounty) + r0 = ret.Get(0).([]db.WorkspaceFeatures) } } - if rf, ok := ret.Get(1).(func(*http.Request) error); ok { - r1 = rf(r) - } else { - r1 = ret.Error(1) - } - - return r0, r1 + return r0 } -// Database_GetCreatedBounties_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCreatedBounties' -type Database_GetCreatedBounties_Call struct { +// Database_GetFeaturesByWorkspaceUuid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeaturesByWorkspaceUuid' +type Database_GetFeaturesByWorkspaceUuid_Call struct { *mock.Call } -// GetCreatedBounties is a helper method to define mock.On call +// GetFeaturesByWorkspaceUuid is a helper method to define mock.On call +// - uuid string // - r *http.Request -func (_e *Database_Expecter) GetCreatedBounties(r interface{}) *Database_GetCreatedBounties_Call { - return &Database_GetCreatedBounties_Call{Call: _e.mock.On("GetCreatedBounties", r)} +func (_e *Database_Expecter) GetFeaturesByWorkspaceUuid(uuid interface{}, r interface{}) *Database_GetFeaturesByWorkspaceUuid_Call { + return &Database_GetFeaturesByWorkspaceUuid_Call{Call: _e.mock.On("GetFeaturesByWorkspaceUuid", uuid, r)} } -func (_c *Database_GetCreatedBounties_Call) Run(run func(r *http.Request)) *Database_GetCreatedBounties_Call { +func (_c *Database_GetFeaturesByWorkspaceUuid_Call) Run(run func(uuid string, r *http.Request)) *Database_GetFeaturesByWorkspaceUuid_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*http.Request)) + run(args[0].(string), args[1].(*http.Request)) }) return _c } -func (_c *Database_GetCreatedBounties_Call) Return(_a0 []db.NewBounty, _a1 error) *Database_GetCreatedBounties_Call { - _c.Call.Return(_a0, _a1) +func (_c *Database_GetFeaturesByWorkspaceUuid_Call) Return(_a0 []db.WorkspaceFeatures) *Database_GetFeaturesByWorkspaceUuid_Call { + _c.Call.Return(_a0) return _c } -func (_c *Database_GetCreatedBounties_Call) RunAndReturn(run func(*http.Request) ([]db.NewBounty, error)) *Database_GetCreatedBounties_Call { +func (_c *Database_GetFeaturesByWorkspaceUuid_Call) RunAndReturn(run func(string, *http.Request) []db.WorkspaceFeatures) *Database_GetFeaturesByWorkspaceUuid_Call { _c.Call.Return(run) return _c } @@ -3648,6 +4273,54 @@ func (_c *Database_GetPersonByUuid_Call) RunAndReturn(run func(string) db.Person return _c } +// GetPhasesByFeatureUuid provides a mock function with given fields: featureUuid +func (_m *Database) GetPhasesByFeatureUuid(featureUuid string) []db.FeaturePhase { + ret := _m.Called(featureUuid) + + if len(ret) == 0 { + panic("no return value specified for GetPhasesByFeatureUuid") + } + + var r0 []db.FeaturePhase + if rf, ok := ret.Get(0).(func(string) []db.FeaturePhase); ok { + r0 = rf(featureUuid) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]db.FeaturePhase) + } + } + + return r0 +} + +// Database_GetPhasesByFeatureUuid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPhasesByFeatureUuid' +type Database_GetPhasesByFeatureUuid_Call struct { + *mock.Call +} + +// GetPhasesByFeatureUuid is a helper method to define mock.On call +// - featureUuid string +func (_e *Database_Expecter) GetPhasesByFeatureUuid(featureUuid interface{}) *Database_GetPhasesByFeatureUuid_Call { + return &Database_GetPhasesByFeatureUuid_Call{Call: _e.mock.On("GetPhasesByFeatureUuid", featureUuid)} +} + +func (_c *Database_GetPhasesByFeatureUuid_Call) Run(run func(featureUuid string)) *Database_GetPhasesByFeatureUuid_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Database_GetPhasesByFeatureUuid_Call) Return(_a0 []db.FeaturePhase) *Database_GetPhasesByFeatureUuid_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_GetPhasesByFeatureUuid_Call) RunAndReturn(run func(string) []db.FeaturePhase) *Database_GetPhasesByFeatureUuid_Call { + _c.Call.Return(run) + return _c +} + // GetPreviousBountyByCreated provides a mock function with given fields: r func (_m *Database) GetPreviousBountyByCreated(r *http.Request) (uint, error) { ret := _m.Called(r) @@ -4651,6 +5324,52 @@ func (_c *Database_GetWorkspaceByUuid_Call) RunAndReturn(run func(string) db.Wor return _c } +// GetWorkspaceFeaturesCount provides a mock function with given fields: uuid +func (_m *Database) GetWorkspaceFeaturesCount(uuid string) int64 { + ret := _m.Called(uuid) + + if len(ret) == 0 { + panic("no return value specified for GetWorkspaceFeaturesCount") + } + + var r0 int64 + if rf, ok := ret.Get(0).(func(string) int64); ok { + r0 = rf(uuid) + } else { + r0 = ret.Get(0).(int64) + } + + return r0 +} + +// Database_GetWorkspaceFeaturesCount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetWorkspaceFeaturesCount' +type Database_GetWorkspaceFeaturesCount_Call struct { + *mock.Call +} + +// GetWorkspaceFeaturesCount is a helper method to define mock.On call +// - uuid string +func (_e *Database_Expecter) GetWorkspaceFeaturesCount(uuid interface{}) *Database_GetWorkspaceFeaturesCount_Call { + return &Database_GetWorkspaceFeaturesCount_Call{Call: _e.mock.On("GetWorkspaceFeaturesCount", uuid)} +} + +func (_c *Database_GetWorkspaceFeaturesCount_Call) Run(run func(uuid string)) *Database_GetWorkspaceFeaturesCount_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Database_GetWorkspaceFeaturesCount_Call) Return(_a0 int64) *Database_GetWorkspaceFeaturesCount_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_GetWorkspaceFeaturesCount_Call) RunAndReturn(run func(string) int64) *Database_GetWorkspaceFeaturesCount_Call { + _c.Call.Return(run) + return _c +} + // GetWorkspaceInvoices provides a mock function with given fields: workspace_uuid func (_m *Database) GetWorkspaceInvoices(workspace_uuid string) []db.NewInvoiceList { ret := _m.Called(workspace_uuid) @@ -4745,6 +5464,54 @@ func (_c *Database_GetWorkspaceInvoicesCount_Call) RunAndReturn(run func(string) return _c } +// GetWorkspaceRepositorByWorkspaceUuid provides a mock function with given fields: uuid +func (_m *Database) GetWorkspaceRepositorByWorkspaceUuid(uuid string) []db.WorkspaceRepositories { + ret := _m.Called(uuid) + + if len(ret) == 0 { + panic("no return value specified for GetWorkspaceRepositorByWorkspaceUuid") + } + + var r0 []db.WorkspaceRepositories + if rf, ok := ret.Get(0).(func(string) []db.WorkspaceRepositories); ok { + r0 = rf(uuid) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]db.WorkspaceRepositories) + } + } + + return r0 +} + +// Database_GetWorkspaceRepositorByWorkspaceUuid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetWorkspaceRepositorByWorkspaceUuid' +type Database_GetWorkspaceRepositorByWorkspaceUuid_Call struct { + *mock.Call +} + +// GetWorkspaceRepositorByWorkspaceUuid is a helper method to define mock.On call +// - uuid string +func (_e *Database_Expecter) GetWorkspaceRepositorByWorkspaceUuid(uuid interface{}) *Database_GetWorkspaceRepositorByWorkspaceUuid_Call { + return &Database_GetWorkspaceRepositorByWorkspaceUuid_Call{Call: _e.mock.On("GetWorkspaceRepositorByWorkspaceUuid", uuid)} +} + +func (_c *Database_GetWorkspaceRepositorByWorkspaceUuid_Call) Run(run func(uuid string)) *Database_GetWorkspaceRepositorByWorkspaceUuid_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Database_GetWorkspaceRepositorByWorkspaceUuid_Call) Return(_a0 []db.WorkspaceRepositories) *Database_GetWorkspaceRepositorByWorkspaceUuid_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_GetWorkspaceRepositorByWorkspaceUuid_Call) RunAndReturn(run func(string) []db.WorkspaceRepositories) *Database_GetWorkspaceRepositorByWorkspaceUuid_Call { + _c.Call.Return(run) + return _c +} + // GetWorkspaceStatusBudget provides a mock function with given fields: workspace_uuid func (_m *Database) GetWorkspaceStatusBudget(workspace_uuid string) db.StatusBudget { ret := _m.Called(workspace_uuid) @@ -5035,17 +5802,17 @@ func (_c *Database_GetWorkspacesCount_Call) RunAndReturn(run func() int64) *Data return _c } -// NewHuntersPaid provides a mock function with given fields: r -func (_m *Database) NewHuntersPaid(r db.PaymentDateRange) int64 { - ret := _m.Called(r) +// NewHuntersPaid provides a mock function with given fields: r, workspace +func (_m *Database) NewHuntersPaid(r db.PaymentDateRange, workspace string) int64 { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for NewHuntersPaid") } var r0 int64 - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) int64); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) int64); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(int64) } @@ -5060,13 +5827,14 @@ type Database_NewHuntersPaid_Call struct { // NewHuntersPaid is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) NewHuntersPaid(r interface{}) *Database_NewHuntersPaid_Call { - return &Database_NewHuntersPaid_Call{Call: _e.mock.On("NewHuntersPaid", r)} +// - workspace string +func (_e *Database_Expecter) NewHuntersPaid(r interface{}, workspace interface{}) *Database_NewHuntersPaid_Call { + return &Database_NewHuntersPaid_Call{Call: _e.mock.On("NewHuntersPaid", r, workspace)} } -func (_c *Database_NewHuntersPaid_Call) Run(run func(r db.PaymentDateRange)) *Database_NewHuntersPaid_Call { +func (_c *Database_NewHuntersPaid_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_NewHuntersPaid_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -5076,7 +5844,7 @@ func (_c *Database_NewHuntersPaid_Call) Return(_a0 int64) *Database_NewHuntersPa return _c } -func (_c *Database_NewHuntersPaid_Call) RunAndReturn(run func(db.PaymentDateRange) int64) *Database_NewHuntersPaid_Call { +func (_c *Database_NewHuntersPaid_Call) RunAndReturn(run func(db.PaymentDateRange, string) int64) *Database_NewHuntersPaid_Call { _c.Call.Return(run) return _c } @@ -5170,17 +5938,17 @@ func (_c *Database_ProcessAlerts_Call) RunAndReturn(run func(db.Person)) *Databa return _c } -// SatsPaidPercentage provides a mock function with given fields: r -func (_m *Database) SatsPaidPercentage(r db.PaymentDateRange) uint { - ret := _m.Called(r) +// SatsPaidPercentage provides a mock function with given fields: r, workspace +func (_m *Database) SatsPaidPercentage(r db.PaymentDateRange, workspace string) uint { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for SatsPaidPercentage") } var r0 uint - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) uint); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) uint); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(uint) } @@ -5195,13 +5963,14 @@ type Database_SatsPaidPercentage_Call struct { // SatsPaidPercentage is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) SatsPaidPercentage(r interface{}) *Database_SatsPaidPercentage_Call { - return &Database_SatsPaidPercentage_Call{Call: _e.mock.On("SatsPaidPercentage", r)} +// - workspace string +func (_e *Database_Expecter) SatsPaidPercentage(r interface{}, workspace interface{}) *Database_SatsPaidPercentage_Call { + return &Database_SatsPaidPercentage_Call{Call: _e.mock.On("SatsPaidPercentage", r, workspace)} } -func (_c *Database_SatsPaidPercentage_Call) Run(run func(r db.PaymentDateRange)) *Database_SatsPaidPercentage_Call { +func (_c *Database_SatsPaidPercentage_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_SatsPaidPercentage_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -5211,7 +5980,7 @@ func (_c *Database_SatsPaidPercentage_Call) Return(_a0 uint) *Database_SatsPaidP return _c } -func (_c *Database_SatsPaidPercentage_Call) RunAndReturn(run func(db.PaymentDateRange) uint) *Database_SatsPaidPercentage_Call { +func (_c *Database_SatsPaidPercentage_Call) RunAndReturn(run func(db.PaymentDateRange, string) uint) *Database_SatsPaidPercentage_Call { _c.Call.Return(run) return _c } @@ -5364,17 +6133,64 @@ func (_c *Database_SearchTribes_Call) RunAndReturn(run func(string) []db.Tribe) return _c } -// TotalBountiesPosted provides a mock function with given fields: r -func (_m *Database) TotalBountiesPosted(r db.PaymentDateRange) int64 { - ret := _m.Called(r) +// TotalAssignedBounties provides a mock function with given fields: r, workspace +func (_m *Database) TotalAssignedBounties(r db.PaymentDateRange, workspace string) int64 { + ret := _m.Called(r, workspace) + + if len(ret) == 0 { + panic("no return value specified for TotalAssignedBounties") + } + + var r0 int64 + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) int64); ok { + r0 = rf(r, workspace) + } else { + r0 = ret.Get(0).(int64) + } + + return r0 +} + +// Database_TotalAssignedBounties_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TotalAssignedBounties' +type Database_TotalAssignedBounties_Call struct { + *mock.Call +} + +// TotalAssignedBounties is a helper method to define mock.On call +// - r db.PaymentDateRange +// - workspace string +func (_e *Database_Expecter) TotalAssignedBounties(r interface{}, workspace interface{}) *Database_TotalAssignedBounties_Call { + return &Database_TotalAssignedBounties_Call{Call: _e.mock.On("TotalAssignedBounties", r, workspace)} +} + +func (_c *Database_TotalAssignedBounties_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_TotalAssignedBounties_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(db.PaymentDateRange), args[1].(string)) + }) + return _c +} + +func (_c *Database_TotalAssignedBounties_Call) Return(_a0 int64) *Database_TotalAssignedBounties_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Database_TotalAssignedBounties_Call) RunAndReturn(run func(db.PaymentDateRange, string) int64) *Database_TotalAssignedBounties_Call { + _c.Call.Return(run) + return _c +} + +// TotalBountiesPosted provides a mock function with given fields: r, workspace +func (_m *Database) TotalBountiesPosted(r db.PaymentDateRange, workspace string) int64 { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for TotalBountiesPosted") } var r0 int64 - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) int64); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) int64); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(int64) } @@ -5389,13 +6205,14 @@ type Database_TotalBountiesPosted_Call struct { // TotalBountiesPosted is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) TotalBountiesPosted(r interface{}) *Database_TotalBountiesPosted_Call { - return &Database_TotalBountiesPosted_Call{Call: _e.mock.On("TotalBountiesPosted", r)} +// - workspace string +func (_e *Database_Expecter) TotalBountiesPosted(r interface{}, workspace interface{}) *Database_TotalBountiesPosted_Call { + return &Database_TotalBountiesPosted_Call{Call: _e.mock.On("TotalBountiesPosted", r, workspace)} } -func (_c *Database_TotalBountiesPosted_Call) Run(run func(r db.PaymentDateRange)) *Database_TotalBountiesPosted_Call { +func (_c *Database_TotalBountiesPosted_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_TotalBountiesPosted_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -5405,22 +6222,22 @@ func (_c *Database_TotalBountiesPosted_Call) Return(_a0 int64) *Database_TotalBo return _c } -func (_c *Database_TotalBountiesPosted_Call) RunAndReturn(run func(db.PaymentDateRange) int64) *Database_TotalBountiesPosted_Call { +func (_c *Database_TotalBountiesPosted_Call) RunAndReturn(run func(db.PaymentDateRange, string) int64) *Database_TotalBountiesPosted_Call { _c.Call.Return(run) return _c } -// TotalHuntersPaid provides a mock function with given fields: r -func (_m *Database) TotalHuntersPaid(r db.PaymentDateRange) int64 { - ret := _m.Called(r) +// TotalHuntersPaid provides a mock function with given fields: r, workspace +func (_m *Database) TotalHuntersPaid(r db.PaymentDateRange, workspace string) int64 { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for TotalHuntersPaid") } var r0 int64 - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) int64); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) int64); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(int64) } @@ -5435,13 +6252,14 @@ type Database_TotalHuntersPaid_Call struct { // TotalHuntersPaid is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) TotalHuntersPaid(r interface{}) *Database_TotalHuntersPaid_Call { - return &Database_TotalHuntersPaid_Call{Call: _e.mock.On("TotalHuntersPaid", r)} +// - workspace string +func (_e *Database_Expecter) TotalHuntersPaid(r interface{}, workspace interface{}) *Database_TotalHuntersPaid_Call { + return &Database_TotalHuntersPaid_Call{Call: _e.mock.On("TotalHuntersPaid", r, workspace)} } -func (_c *Database_TotalHuntersPaid_Call) Run(run func(r db.PaymentDateRange)) *Database_TotalHuntersPaid_Call { +func (_c *Database_TotalHuntersPaid_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_TotalHuntersPaid_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -5451,22 +6269,22 @@ func (_c *Database_TotalHuntersPaid_Call) Return(_a0 int64) *Database_TotalHunte return _c } -func (_c *Database_TotalHuntersPaid_Call) RunAndReturn(run func(db.PaymentDateRange) int64) *Database_TotalHuntersPaid_Call { +func (_c *Database_TotalHuntersPaid_Call) RunAndReturn(run func(db.PaymentDateRange, string) int64) *Database_TotalHuntersPaid_Call { _c.Call.Return(run) return _c } -// TotalPaidBounties provides a mock function with given fields: r -func (_m *Database) TotalPaidBounties(r db.PaymentDateRange) int64 { - ret := _m.Called(r) +// TotalPaidBounties provides a mock function with given fields: r, workspace +func (_m *Database) TotalPaidBounties(r db.PaymentDateRange, workspace string) int64 { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for TotalPaidBounties") } var r0 int64 - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) int64); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) int64); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(int64) } @@ -5481,13 +6299,14 @@ type Database_TotalPaidBounties_Call struct { // TotalPaidBounties is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) TotalPaidBounties(r interface{}) *Database_TotalPaidBounties_Call { - return &Database_TotalPaidBounties_Call{Call: _e.mock.On("TotalPaidBounties", r)} +// - workspace string +func (_e *Database_Expecter) TotalPaidBounties(r interface{}, workspace interface{}) *Database_TotalPaidBounties_Call { + return &Database_TotalPaidBounties_Call{Call: _e.mock.On("TotalPaidBounties", r, workspace)} } -func (_c *Database_TotalPaidBounties_Call) Run(run func(r db.PaymentDateRange)) *Database_TotalPaidBounties_Call { +func (_c *Database_TotalPaidBounties_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_TotalPaidBounties_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -5497,22 +6316,22 @@ func (_c *Database_TotalPaidBounties_Call) Return(_a0 int64) *Database_TotalPaid return _c } -func (_c *Database_TotalPaidBounties_Call) RunAndReturn(run func(db.PaymentDateRange) int64) *Database_TotalPaidBounties_Call { +func (_c *Database_TotalPaidBounties_Call) RunAndReturn(run func(db.PaymentDateRange, string) int64) *Database_TotalPaidBounties_Call { _c.Call.Return(run) return _c } -// TotalSatsPaid provides a mock function with given fields: r -func (_m *Database) TotalSatsPaid(r db.PaymentDateRange) uint { - ret := _m.Called(r) +// TotalSatsPaid provides a mock function with given fields: r, workspace +func (_m *Database) TotalSatsPaid(r db.PaymentDateRange, workspace string) uint { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for TotalSatsPaid") } var r0 uint - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) uint); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) uint); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(uint) } @@ -5527,13 +6346,14 @@ type Database_TotalSatsPaid_Call struct { // TotalSatsPaid is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) TotalSatsPaid(r interface{}) *Database_TotalSatsPaid_Call { - return &Database_TotalSatsPaid_Call{Call: _e.mock.On("TotalSatsPaid", r)} +// - workspace string +func (_e *Database_Expecter) TotalSatsPaid(r interface{}, workspace interface{}) *Database_TotalSatsPaid_Call { + return &Database_TotalSatsPaid_Call{Call: _e.mock.On("TotalSatsPaid", r, workspace)} } -func (_c *Database_TotalSatsPaid_Call) Run(run func(r db.PaymentDateRange)) *Database_TotalSatsPaid_Call { +func (_c *Database_TotalSatsPaid_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_TotalSatsPaid_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -5543,22 +6363,22 @@ func (_c *Database_TotalSatsPaid_Call) Return(_a0 uint) *Database_TotalSatsPaid_ return _c } -func (_c *Database_TotalSatsPaid_Call) RunAndReturn(run func(db.PaymentDateRange) uint) *Database_TotalSatsPaid_Call { +func (_c *Database_TotalSatsPaid_Call) RunAndReturn(run func(db.PaymentDateRange, string) uint) *Database_TotalSatsPaid_Call { _c.Call.Return(run) return _c } -// TotalSatsPosted provides a mock function with given fields: r -func (_m *Database) TotalSatsPosted(r db.PaymentDateRange) uint { - ret := _m.Called(r) +// TotalSatsPosted provides a mock function with given fields: r, workspace +func (_m *Database) TotalSatsPosted(r db.PaymentDateRange, workspace string) uint { + ret := _m.Called(r, workspace) if len(ret) == 0 { panic("no return value specified for TotalSatsPosted") } var r0 uint - if rf, ok := ret.Get(0).(func(db.PaymentDateRange) uint); ok { - r0 = rf(r) + if rf, ok := ret.Get(0).(func(db.PaymentDateRange, string) uint); ok { + r0 = rf(r, workspace) } else { r0 = ret.Get(0).(uint) } @@ -5573,13 +6393,14 @@ type Database_TotalSatsPosted_Call struct { // TotalSatsPosted is a helper method to define mock.On call // - r db.PaymentDateRange -func (_e *Database_Expecter) TotalSatsPosted(r interface{}) *Database_TotalSatsPosted_Call { - return &Database_TotalSatsPosted_Call{Call: _e.mock.On("TotalSatsPosted", r)} +// - workspace string +func (_e *Database_Expecter) TotalSatsPosted(r interface{}, workspace interface{}) *Database_TotalSatsPosted_Call { + return &Database_TotalSatsPosted_Call{Call: _e.mock.On("TotalSatsPosted", r, workspace)} } -func (_c *Database_TotalSatsPosted_Call) Run(run func(r db.PaymentDateRange)) *Database_TotalSatsPosted_Call { +func (_c *Database_TotalSatsPosted_Call) Run(run func(r db.PaymentDateRange, workspace string)) *Database_TotalSatsPosted_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(db.PaymentDateRange)) + run(args[0].(db.PaymentDateRange), args[1].(string)) }) return _c } @@ -5589,7 +6410,7 @@ func (_c *Database_TotalSatsPosted_Call) Return(_a0 uint) *Database_TotalSatsPos return _c } -func (_c *Database_TotalSatsPosted_Call) RunAndReturn(run func(db.PaymentDateRange) uint) *Database_TotalSatsPosted_Call { +func (_c *Database_TotalSatsPosted_Call) RunAndReturn(run func(db.PaymentDateRange, string) uint) *Database_TotalSatsPosted_Call { _c.Call.Return(run) return _c } diff --git a/routes/features.go b/routes/features.go new file mode 100644 index 000000000..b1343b382 --- /dev/null +++ b/routes/features.go @@ -0,0 +1,34 @@ +package routes + +import ( + "github.com/go-chi/chi" + "github.com/stakwork/sphinx-tribes/auth" + "github.com/stakwork/sphinx-tribes/db" + "github.com/stakwork/sphinx-tribes/handlers" +) + +func FeatureRoutes() chi.Router { + r := chi.NewRouter() + featureHandlers := handlers.NewFeatureHandler(&db.DB) + r.Group(func(r chi.Router) { + r.Use(auth.PubKeyContext) + + r.Post("/", featureHandlers.CreateOrEditFeatures) + r.Get("/{uuid}", featureHandlers.GetFeatureByUuid) + // Old route for to getting features for workspace uuid + r.Get("/forworkspace/{workspace_uuid}", featureHandlers.GetFeaturesByWorkspaceUuid) + r.Get("/workspace/count/{uuid}", featureHandlers.GetWorkspaceFeaturesCount) + r.Delete("/{uuid}", featureHandlers.DeleteFeature) + + r.Post("/phase", featureHandlers.CreateOrEditFeaturePhase) + r.Get("/{feature_uuid}/phase", featureHandlers.GetFeaturePhases) + r.Get("/{feature_uuid}/phase/{phase_uuid}", featureHandlers.GetFeaturePhaseByUUID) + r.Delete("/{feature_uuid}/phase/{phase_uuid}", featureHandlers.DeleteFeaturePhase) + + r.Post("/story", featureHandlers.CreateOrEditStory) + r.Get("/{feature_uuid}/story", featureHandlers.GetStoriesByFeatureUuid) + r.Get("/{feature_uuid}/story/{story_uuid}", featureHandlers.GetStoryByUuid) + r.Delete("/{feature_uuid}/story/{story_uuid}", featureHandlers.DeleteStory) + }) + return r +} diff --git a/routes/index.go b/routes/index.go index 98dc0c162..22090938c 100644 --- a/routes/index.go +++ b/routes/index.go @@ -36,6 +36,7 @@ func NewRouter() *http.Server { r.Mount("/gobounties", BountyRoutes()) r.Mount("/workspaces", WorkspaceRoutes()) r.Mount("/metrics", MetricsRoutes()) + r.Mount("/features", FeatureRoutes()) r.Group(func(r chi.Router) { r.Get("/tribe_by_feed", tribeHandlers.GetFirstTribeByFeed) diff --git a/routes/metrics.go b/routes/metrics.go index e24a1386d..19065e175 100644 --- a/routes/metrics.go +++ b/routes/metrics.go @@ -13,6 +13,8 @@ func MetricsRoutes() chi.Router { r.Group(func(r chi.Router) { r.Use(auth.PubKeyContextSuperAdmin) + r.Get("/workspaces", handlers.GetAdminWorkspaces) + r.Post("/payment", handlers.PaymentMetrics) r.Post("/people", handlers.PeopleMetrics) r.Post("/organization", handlers.WorkspacetMetrics) diff --git a/routes/workspaces.go b/routes/workspaces.go index d79a457bd..81f7160e0 100644 --- a/routes/workspaces.go +++ b/routes/workspaces.go @@ -42,6 +42,11 @@ func WorkspaceRoutes() chi.Router { r.Post("/mission", workspaceHandlers.UpdateWorkspace) r.Post("/tactics", workspaceHandlers.UpdateWorkspace) r.Post("/schematicurl", workspaceHandlers.UpdateWorkspace) + + r.Post("/repositories", workspaceHandlers.CreateWorkspaceRepository) + r.Get("/repositories/{uuid}", workspaceHandlers.GetWorkspaceRepositorByWorkspaceUuid) + // New route for to getting features for workspace uuid + r.Get("/{workspace_uuid}/features", workspaceHandlers.GetFeaturesByWorkspaceUuid) }) return r }