mirror of
https://github.com/hcengineering/platform.git
synced 2025-01-01 16:11:23 +03:00
EZQMS-1069: Fix request model (#6131)
Signed-off-by: Alexey Zinoviev <alexey.zinoviev@xored.com>
This commit is contained in:
parent
77f0a2c3e1
commit
ed903a9396
@ -49,6 +49,7 @@ import { questionsOperation } from '@hcengineering/model-questions'
|
|||||||
import { trainingOperation } from '@hcengineering/model-training'
|
import { trainingOperation } from '@hcengineering/model-training'
|
||||||
import { documentsOperation } from '@hcengineering/model-controlled-documents'
|
import { documentsOperation } from '@hcengineering/model-controlled-documents'
|
||||||
import { productsOperation } from '@hcengineering/model-products'
|
import { productsOperation } from '@hcengineering/model-products'
|
||||||
|
import { requestOperation } from '@hcengineering/model-request'
|
||||||
|
|
||||||
export const migrateOperations: [string, MigrateOperation][] = [
|
export const migrateOperations: [string, MigrateOperation][] = [
|
||||||
['core', coreOperation],
|
['core', coreOperation],
|
||||||
@ -72,6 +73,7 @@ export const migrateOperations: [string, MigrateOperation][] = [
|
|||||||
['documents', documentsOperation],
|
['documents', documentsOperation],
|
||||||
['questions', questionsOperation],
|
['questions', questionsOperation],
|
||||||
['training', trainingOperation],
|
['training', trainingOperation],
|
||||||
|
['request', requestOperation],
|
||||||
['products', productsOperation],
|
['products', productsOperation],
|
||||||
['board', boardOperation],
|
['board', boardOperation],
|
||||||
['hr', hrOperation],
|
['hr', hrOperation],
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import activity from '@hcengineering/activity'
|
import activity from '@hcengineering/activity'
|
||||||
import type { PersonAccount } from '@hcengineering/contact'
|
import type { Person } from '@hcengineering/contact'
|
||||||
import contact from '@hcengineering/contact'
|
import contact from '@hcengineering/contact'
|
||||||
import { type Timestamp, type Domain, type Ref, type Tx } from '@hcengineering/core'
|
import { type Timestamp, type Domain, type Ref, type Tx } from '@hcengineering/core'
|
||||||
import {
|
import {
|
||||||
@ -43,6 +43,7 @@ import {
|
|||||||
import { type AnyComponent } from '@hcengineering/ui/src/types'
|
import { type AnyComponent } from '@hcengineering/ui/src/types'
|
||||||
import request from './plugin'
|
import request from './plugin'
|
||||||
|
|
||||||
|
export { requestOperation } from './migration'
|
||||||
export { requestId } from '@hcengineering/request'
|
export { requestId } from '@hcengineering/request'
|
||||||
export { default } from './plugin'
|
export { default } from './plugin'
|
||||||
|
|
||||||
@ -51,13 +52,13 @@ export const DOMAIN_REQUEST = 'request' as Domain
|
|||||||
@Model(request.class.Request, core.class.AttachedDoc, DOMAIN_REQUEST)
|
@Model(request.class.Request, core.class.AttachedDoc, DOMAIN_REQUEST)
|
||||||
@UX(request.string.Request, request.icon.Requests)
|
@UX(request.string.Request, request.icon.Requests)
|
||||||
export class TRequest extends TAttachedDoc implements Request {
|
export class TRequest extends TAttachedDoc implements Request {
|
||||||
@Prop(ArrOf(TypeRef(contact.class.PersonAccount)), request.string.Requested)
|
@Prop(ArrOf(TypeRef(contact.class.Person)), request.string.Requested)
|
||||||
// @Index(IndexKind.Indexed)
|
// @Index(IndexKind.Indexed)
|
||||||
requested!: Ref<PersonAccount>[]
|
requested!: Ref<Person>[]
|
||||||
|
|
||||||
@Prop(ArrOf(TypeRef(contact.class.PersonAccount)), request.string.Approved)
|
@Prop(ArrOf(TypeRef(contact.class.Person)), request.string.Approved)
|
||||||
@ReadOnly()
|
@ReadOnly()
|
||||||
approved!: Ref<PersonAccount>[]
|
approved!: Ref<Person>[]
|
||||||
|
|
||||||
approvedDates?: Timestamp[]
|
approvedDates?: Timestamp[]
|
||||||
|
|
||||||
@ -70,9 +71,9 @@ export class TRequest extends TAttachedDoc implements Request {
|
|||||||
tx!: Tx
|
tx!: Tx
|
||||||
rejectedTx?: Tx
|
rejectedTx?: Tx
|
||||||
|
|
||||||
@Prop(TypeRef(contact.class.PersonAccount), request.string.Rejected)
|
@Prop(TypeRef(contact.class.Person), request.string.Rejected)
|
||||||
@ReadOnly()
|
@ReadOnly()
|
||||||
rejected?: Ref<PersonAccount>
|
rejected?: Ref<Person>
|
||||||
|
|
||||||
@Prop(Collection(chunter.class.ChatMessage), chunter.string.Comments)
|
@Prop(Collection(chunter.class.ChatMessage), chunter.string.Comments)
|
||||||
comments?: number
|
comments?: number
|
||||||
|
99
models/request/src/migration.ts
Normal file
99
models/request/src/migration.ts
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//
|
||||||
|
// Copyright © 2024 Hardcore Engineering Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
import core, { DOMAIN_TX, type Ref, type TxCreateDoc } from '@hcengineering/core'
|
||||||
|
import request, { requestId, type Request } from '@hcengineering/request'
|
||||||
|
import {
|
||||||
|
type MigrateUpdate,
|
||||||
|
type MigrationDocumentQuery,
|
||||||
|
tryMigrate,
|
||||||
|
type MigrateOperation,
|
||||||
|
type MigrationClient,
|
||||||
|
type MigrationUpgradeClient,
|
||||||
|
type ModelLogger
|
||||||
|
} from '@hcengineering/model'
|
||||||
|
import contact, { type Person, type PersonAccount } from '@hcengineering/contact'
|
||||||
|
|
||||||
|
import { DOMAIN_REQUEST } from '.'
|
||||||
|
|
||||||
|
async function migrateRequestPersonAccounts (client: MigrationClient): Promise<void> {
|
||||||
|
const descendants = client.hierarchy.getDescendants(request.class.Request)
|
||||||
|
const requests = await client.find<Request>(DOMAIN_REQUEST, {
|
||||||
|
_class: { $in: descendants }
|
||||||
|
})
|
||||||
|
const personAccountsCreateTxes = await client.find(DOMAIN_TX, {
|
||||||
|
_class: core.class.TxCreateDoc,
|
||||||
|
objectClass: contact.class.PersonAccount
|
||||||
|
})
|
||||||
|
const personAccountToPersonMap = personAccountsCreateTxes.reduce<Record<Ref<PersonAccount>, Ref<Person>>>(
|
||||||
|
(map, tx) => {
|
||||||
|
const ctx = tx as TxCreateDoc<PersonAccount>
|
||||||
|
|
||||||
|
map[ctx.objectId] = ctx.attributes.person
|
||||||
|
|
||||||
|
return map
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
const operations: { filter: MigrationDocumentQuery<Request>, update: MigrateUpdate<Request> }[] = []
|
||||||
|
for (const request of requests) {
|
||||||
|
const newRequestedPersons = request.requested
|
||||||
|
.map((paId) => personAccountToPersonMap[paId as unknown as Ref<PersonAccount>])
|
||||||
|
.filter((p) => p != null)
|
||||||
|
const newApprovedPersons = request.approved
|
||||||
|
.map((paId) => personAccountToPersonMap[paId as unknown as Ref<PersonAccount>])
|
||||||
|
.filter((p) => p != null)
|
||||||
|
const newRejectedPerson =
|
||||||
|
request.rejected != null ? personAccountToPersonMap[request.rejected as unknown as Ref<PersonAccount>] : undefined
|
||||||
|
|
||||||
|
if (newRequestedPersons.length > 0) {
|
||||||
|
operations.push({
|
||||||
|
filter: {
|
||||||
|
_id: request._id
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
requested: newRequestedPersons,
|
||||||
|
approved: newApprovedPersons
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newRejectedPerson !== undefined) {
|
||||||
|
operations.push({
|
||||||
|
filter: {
|
||||||
|
_id: request._id
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
rejected: newRejectedPerson
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operations.length > 0) {
|
||||||
|
await client.bulk(DOMAIN_REQUEST, operations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const requestOperation: MigrateOperation = {
|
||||||
|
async migrate (client: MigrationClient, logger: ModelLogger): Promise<void> {
|
||||||
|
await tryMigrate(client, requestId, [
|
||||||
|
{
|
||||||
|
state: 'migrateRequestPersonAccounts',
|
||||||
|
func: migrateRequestPersonAccounts
|
||||||
|
}
|
||||||
|
])
|
||||||
|
},
|
||||||
|
async upgrade (state: Map<string, Set<string>>, client: () => Promise<MigrationUpgradeClient>): Promise<void> {}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
// Copyright © 2023 Hardcore Engineering Inc.
|
// Copyright © 2023, 2024 Hardcore Engineering Inc.
|
||||||
//
|
//
|
||||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License. You may
|
// you may not use this file except in compliance with the License. You may
|
||||||
@ -17,7 +17,7 @@
|
|||||||
import { Label, Scroller } from '@hcengineering/ui'
|
import { Label, Scroller } from '@hcengineering/ui'
|
||||||
import { createQuery } from '@hcengineering/presentation'
|
import { createQuery } from '@hcengineering/presentation'
|
||||||
import documents, { DocumentApprovalRequest, DocumentReviewRequest } from '@hcengineering/controlled-documents'
|
import documents, { DocumentApprovalRequest, DocumentReviewRequest } from '@hcengineering/controlled-documents'
|
||||||
import { employeeByIdStore, personAccountByIdStore } from '@hcengineering/contact-resources'
|
import { employeeByIdStore } from '@hcengineering/contact-resources'
|
||||||
import { Employee, Person, formatName } from '@hcengineering/contact'
|
import { Employee, Person, formatName } from '@hcengineering/contact'
|
||||||
import { IntlString } from '@hcengineering/platform'
|
import { IntlString } from '@hcengineering/platform'
|
||||||
|
|
||||||
@ -98,13 +98,12 @@
|
|||||||
|
|
||||||
if (reviewRequest !== undefined) {
|
if (reviewRequest !== undefined) {
|
||||||
reviewRequest.approved.forEach((reviewer, idx) => {
|
reviewRequest.approved.forEach((reviewer, idx) => {
|
||||||
const rAcc = $personAccountByIdStore.get(reviewer)
|
|
||||||
const date = reviewRequest.approvedDates?.[idx]
|
const date = reviewRequest.approvedDates?.[idx]
|
||||||
|
|
||||||
signers.push({
|
signers.push({
|
||||||
id: rAcc?.person,
|
id: reviewer,
|
||||||
role: 'reviewer',
|
role: 'reviewer',
|
||||||
name: getNameByEmployeeId(rAcc?.person),
|
name: getNameByEmployeeId(reviewer),
|
||||||
date: formatSignatureDate(date ?? reviewRequest.modifiedOn)
|
date: formatSignatureDate(date ?? reviewRequest.modifiedOn)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -112,13 +111,12 @@
|
|||||||
|
|
||||||
if (approvalRequest !== undefined) {
|
if (approvalRequest !== undefined) {
|
||||||
approvalRequest.approved.forEach((approver, idx) => {
|
approvalRequest.approved.forEach((approver, idx) => {
|
||||||
const aAcc = $personAccountByIdStore.get(approver)
|
|
||||||
const date = approvalRequest.approvedDates?.[idx]
|
const date = approvalRequest.approvedDates?.[idx]
|
||||||
|
|
||||||
signers.push({
|
signers.push({
|
||||||
id: aAcc?.person,
|
id: approver,
|
||||||
role: 'approver',
|
role: 'approver',
|
||||||
name: getNameByEmployeeId(aAcc?.person),
|
name: getNameByEmployeeId(approver),
|
||||||
date: formatSignatureDate(date ?? approvalRequest.modifiedOn)
|
date: formatSignatureDate(date ?? approvalRequest.modifiedOn)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
import { slide } from 'svelte/transition'
|
import { slide } from 'svelte/transition'
|
||||||
import documents, { DocumentRequest } from '@hcengineering/controlled-documents'
|
import documents, { DocumentRequest } from '@hcengineering/controlled-documents'
|
||||||
import chunter from '@hcengineering/chunter'
|
import chunter from '@hcengineering/chunter'
|
||||||
import { type Person, type PersonAccount } from '@hcengineering/contact'
|
import { type Person } from '@hcengineering/contact'
|
||||||
import { PersonAccountRefPresenter, personAccountByIdStore } from '@hcengineering/contact-resources'
|
import { PersonRefPresenter, personAccountByIdStore } from '@hcengineering/contact-resources'
|
||||||
import { Ref } from '@hcengineering/core'
|
import { Ref } from '@hcengineering/core'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import { Chevron, Label, tooltip } from '@hcengineering/ui'
|
import { Chevron, Label, tooltip } from '@hcengineering/ui'
|
||||||
@ -20,7 +20,6 @@
|
|||||||
export let initiallyExpanded: boolean = false
|
export let initiallyExpanded: boolean = false
|
||||||
|
|
||||||
interface PersonalApproval {
|
interface PersonalApproval {
|
||||||
account: Ref<PersonAccount>
|
|
||||||
person?: Ref<Person>
|
person?: Ref<Person>
|
||||||
approved: 'approved' | 'rejected' | 'cancelled' | 'waiting'
|
approved: 'approved' | 'rejected' | 'cancelled' | 'waiting'
|
||||||
timestamp?: number
|
timestamp?: number
|
||||||
@ -61,16 +60,14 @@
|
|||||||
req.rejected !== undefined
|
req.rejected !== undefined
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
account: req.rejected,
|
person: req.rejected,
|
||||||
person: accountById.get(req.rejected)?.person,
|
|
||||||
approved: 'rejected',
|
approved: 'rejected',
|
||||||
timestamp: req.modifiedOn
|
timestamp: req.modifiedOn
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
: []
|
: []
|
||||||
const approvedBy: PersonalApproval[] = req.approved.map((id, idx) => ({
|
const approvedBy: PersonalApproval[] = req.approved.map((id, idx) => ({
|
||||||
account: id,
|
person: id,
|
||||||
person: accountById.get(id)?.person,
|
|
||||||
approved: 'approved',
|
approved: 'approved',
|
||||||
timestamp: req.approvedDates?.[idx] ?? req.modifiedOn
|
timestamp: req.approvedDates?.[idx] ?? req.modifiedOn
|
||||||
}))
|
}))
|
||||||
@ -79,8 +76,7 @@
|
|||||||
.filter((p) => !(req?.approved as string[]).includes(p))
|
.filter((p) => !(req?.approved as string[]).includes(p))
|
||||||
.map(
|
.map(
|
||||||
(id): PersonalApproval => ({
|
(id): PersonalApproval => ({
|
||||||
account: id,
|
person: id,
|
||||||
person: accountById.get(id)?.person,
|
|
||||||
approved: req?.rejected !== undefined ? 'cancelled' : 'waiting'
|
approved: req?.rejected !== undefined ? 'cancelled' : 'waiting'
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -125,7 +121,7 @@
|
|||||||
<div class="section" transition:slide|local>
|
<div class="section" transition:slide|local>
|
||||||
{#each approvals as approver}
|
{#each approvals as approver}
|
||||||
<div class="approver">
|
<div class="approver">
|
||||||
<PersonAccountRefPresenter value={approver.account} avatarSize="x-small" />
|
<PersonRefPresenter value={approver.person} avatarSize="x-small" />
|
||||||
{#key approver.timestamp}
|
{#key approver.timestamp}
|
||||||
<!-- For some reason tooltip is not interactive w/o remount -->
|
<!-- For some reason tooltip is not interactive w/o remount -->
|
||||||
<span
|
<span
|
||||||
|
@ -202,8 +202,8 @@ export const $documentStateForCurrentUser = combine($controlledDocument, $review
|
|||||||
return ControlledDocumentState.InReview
|
return ControlledDocumentState.InReview
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentAccount = getCurrentAccount()._id as Ref<PersonAccount>
|
const currentPerson = (getCurrentAccount() as PersonAccount).person
|
||||||
if (reviewRequest.approved?.includes(currentAccount)) {
|
if (reviewRequest.approved?.includes(currentPerson)) {
|
||||||
return ControlledDocumentState.Reviewed
|
return ControlledDocumentState.Reviewed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,7 +228,7 @@ export const $documentState = $controlledDocument.map((doc) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const $documentReviewIsActive = combine($reviewRequest, $documentStateForCurrentUser, (reviewReq, state) => {
|
export const $documentReviewIsActive = combine($reviewRequest, $documentStateForCurrentUser, (reviewReq, state) => {
|
||||||
const me = getCurrentAccount()._id as Ref<PersonAccount>
|
const me = (getCurrentAccount() as PersonAccount).person
|
||||||
|
|
||||||
if (reviewReq == null) {
|
if (reviewReq == null) {
|
||||||
return false
|
return false
|
||||||
@ -244,7 +244,7 @@ export const $documentApprovalIsActive = combine(
|
|||||||
$approvalRequest,
|
$approvalRequest,
|
||||||
$documentStateForCurrentUser,
|
$documentStateForCurrentUser,
|
||||||
(doc, approvalReq, state) => {
|
(doc, approvalReq, state) => {
|
||||||
const me = getCurrentAccount()._id as Ref<PersonAccount>
|
const me = (getCurrentAccount() as PersonAccount).person
|
||||||
|
|
||||||
if (approvalReq == null) {
|
if (approvalReq == null) {
|
||||||
return false
|
return false
|
||||||
|
@ -56,8 +56,8 @@ async function getDocumentStateForCurrentUser (
|
|||||||
return ControlledDocumentState.InReview
|
return ControlledDocumentState.InReview
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentAccount = getCurrentAccount()._id as Ref<PersonAccount>
|
const me = (getCurrentAccount() as PersonAccount).person
|
||||||
if (reviewRequest.approved?.includes(currentAccount)) {
|
if (reviewRequest.approved?.includes(me)) {
|
||||||
return ControlledDocumentState.Reviewed
|
return ControlledDocumentState.Reviewed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ import core, {
|
|||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import { type IntlString, getMetadata, getResource, translate } from '@hcengineering/platform'
|
import { type IntlString, getMetadata, getResource, translate } from '@hcengineering/platform'
|
||||||
import presentation, { copyDocumentContent, getClient } from '@hcengineering/presentation'
|
import presentation, { copyDocumentContent, getClient } from '@hcengineering/presentation'
|
||||||
import contact, { type Employee, type PersonAccount } from '@hcengineering/contact'
|
import { type Person, type Employee, type PersonAccount } from '@hcengineering/contact'
|
||||||
import request, { RequestStatus } from '@hcengineering/request'
|
import request, { RequestStatus } from '@hcengineering/request'
|
||||||
import textEditor from '@hcengineering/text-editor'
|
import textEditor from '@hcengineering/text-editor'
|
||||||
import { isEmptyMarkup } from '@hcengineering/text'
|
import { isEmptyMarkup } from '@hcengineering/text'
|
||||||
@ -313,16 +313,6 @@ export async function sendReviewRequest (
|
|||||||
controlledDoc: ControlledDocument,
|
controlledDoc: ControlledDocument,
|
||||||
reviewers: Array<Ref<Employee>>
|
reviewers: Array<Ref<Employee>>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const reviewersAccounts = await client.findAll(contact.class.PersonAccount, { person: { $in: reviewers } })
|
|
||||||
|
|
||||||
if (reviewersAccounts.length === 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reviewersAccounts.length < reviewers.length) {
|
|
||||||
console.warn('Number of user accounts is less than requested for document review request')
|
|
||||||
}
|
|
||||||
|
|
||||||
const approveTx = client.txFactory.createTxUpdateDoc(controlledDoc._class, controlledDoc.space, controlledDoc._id, {
|
const approveTx = client.txFactory.createTxUpdateDoc(controlledDoc._class, controlledDoc.space, controlledDoc._id, {
|
||||||
controlledState: ControlledDocumentState.Reviewed
|
controlledState: ControlledDocumentState.Reviewed
|
||||||
})
|
})
|
||||||
@ -338,7 +328,7 @@ export async function sendReviewRequest (
|
|||||||
controlledDoc._class,
|
controlledDoc._class,
|
||||||
documents.class.DocumentReviewRequest,
|
documents.class.DocumentReviewRequest,
|
||||||
controlledDoc.space,
|
controlledDoc.space,
|
||||||
reviewersAccounts.map((u) => u._id),
|
reviewers,
|
||||||
approveTx,
|
approveTx,
|
||||||
undefined,
|
undefined,
|
||||||
true
|
true
|
||||||
@ -350,16 +340,6 @@ export async function sendApprovalRequest (
|
|||||||
controlledDoc: ControlledDocument,
|
controlledDoc: ControlledDocument,
|
||||||
approvers: Array<Ref<Employee>>
|
approvers: Array<Ref<Employee>>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const approversAccounts = await client.findAll(contact.class.PersonAccount, { person: { $in: approvers } })
|
|
||||||
|
|
||||||
if (approversAccounts.length === 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (approversAccounts.length < approvers.length) {
|
|
||||||
console.warn('Number of user accounts is less than requested for document approval request')
|
|
||||||
}
|
|
||||||
|
|
||||||
const approveTx = client.txFactory.createTxUpdateDoc(controlledDoc._class, controlledDoc.space, controlledDoc._id, {
|
const approveTx = client.txFactory.createTxUpdateDoc(controlledDoc._class, controlledDoc.space, controlledDoc._id, {
|
||||||
controlledState: ControlledDocumentState.Approved
|
controlledState: ControlledDocumentState.Approved
|
||||||
})
|
})
|
||||||
@ -379,7 +359,7 @@ export async function sendApprovalRequest (
|
|||||||
controlledDoc._class,
|
controlledDoc._class,
|
||||||
documents.class.DocumentApprovalRequest,
|
documents.class.DocumentApprovalRequest,
|
||||||
controlledDoc.space,
|
controlledDoc.space,
|
||||||
approversAccounts.map((u) => u._id),
|
approvers,
|
||||||
approveTx,
|
approveTx,
|
||||||
rejectTx,
|
rejectTx,
|
||||||
true
|
true
|
||||||
@ -392,7 +372,7 @@ async function createRequest<T extends Doc> (
|
|||||||
attachedToClass: Ref<Class<T>>,
|
attachedToClass: Ref<Class<T>>,
|
||||||
reqClass: Ref<Class<Request>>,
|
reqClass: Ref<Class<Request>>,
|
||||||
space: Ref<DocumentSpace>,
|
space: Ref<DocumentSpace>,
|
||||||
users: Array<Ref<PersonAccount>>,
|
users: Array<Ref<Person>>,
|
||||||
approveTx: Tx,
|
approveTx: Tx,
|
||||||
rejectedTx?: Tx,
|
rejectedTx?: Tx,
|
||||||
areAllApprovesRequired = true
|
areAllApprovesRequired = true
|
||||||
@ -429,7 +409,7 @@ export async function completeRequest (
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const req = await getActiveRequest(client, reqClass, controlledDoc)
|
const req = await getActiveRequest(client, reqClass, controlledDoc)
|
||||||
|
|
||||||
const me = getCurrentAccount()._id as Ref<PersonAccount>
|
const me = (getCurrentAccount() as PersonAccount).person
|
||||||
|
|
||||||
if (req == null || !req.requested.includes(me) || req.approved.includes(me)) {
|
if (req == null || !req.requested.includes(me) || req.approved.includes(me)) {
|
||||||
return
|
return
|
||||||
@ -465,7 +445,7 @@ export async function rejectRequest (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const me = getCurrentAccount()._id as Ref<PersonAccount>
|
const me = (getCurrentAccount() as PersonAccount).person
|
||||||
|
|
||||||
await saveComment(rejectionNote, req)
|
await saveComment(rejectionNote, req)
|
||||||
|
|
||||||
|
@ -32,14 +32,16 @@
|
|||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const me = getCurrentAccount()._id as Ref<PersonAccount>
|
const me = getCurrentAccount()._id as Ref<PersonAccount>
|
||||||
|
const myPerson = (getCurrentAccount() as PersonAccount).person
|
||||||
|
|
||||||
const approvable = value.requested.filter((a) => a === me).length > value.approved.filter((a) => a === me).length
|
const approvable =
|
||||||
|
value.requested.filter((a) => a === myPerson).length > value.approved.filter((a) => a === myPerson).length
|
||||||
|
|
||||||
async function approve () {
|
async function approve () {
|
||||||
await saveComment()
|
await saveComment()
|
||||||
await client.update(value, {
|
await client.update(value, {
|
||||||
$push: {
|
$push: {
|
||||||
approved: me
|
approved: myPerson
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -49,7 +51,7 @@
|
|||||||
async function reject () {
|
async function reject () {
|
||||||
await saveComment()
|
await saveComment()
|
||||||
await client.update(value, {
|
await client.update(value, {
|
||||||
rejected: me,
|
rejected: myPerson,
|
||||||
status: RequestStatus.Rejected
|
status: RequestStatus.Rejected
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -13,29 +13,34 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import contact, { PersonAccount } from '@hcengineering/contact'
|
import contact, { Person, PersonAccount } from '@hcengineering/contact'
|
||||||
import { PersonAccountRefPresenter } from '@hcengineering/contact-resources'
|
import { personAccountByIdStore, PersonRefPresenter } from '@hcengineering/contact-resources'
|
||||||
import { Account, Ref } from '@hcengineering/core'
|
import { Ref } from '@hcengineering/core'
|
||||||
import { createQuery, MessageViewer } from '@hcengineering/presentation'
|
import { createQuery, MessageViewer } from '@hcengineering/presentation'
|
||||||
import { Request, RequestDecisionComment } from '@hcengineering/request'
|
import { Request, RequestDecisionComment } from '@hcengineering/request'
|
||||||
import { BooleanIcon, Label, ShowMore } from '@hcengineering/ui'
|
import { BooleanIcon, Label, ShowMore } from '@hcengineering/ui'
|
||||||
import request from '../plugin'
|
import request from '../plugin'
|
||||||
|
|
||||||
export let value: Request
|
export let value: Request
|
||||||
let comments = new Map<Ref<Account>, RequestDecisionComment>()
|
let comments = new Map<Ref<Person> | undefined, RequestDecisionComment>()
|
||||||
|
|
||||||
const query = createQuery()
|
const query = createQuery()
|
||||||
$: query.query(request.mixin.RequestDecisionComment, { attachedTo: value._id }, (res) => {
|
$: query.query(request.mixin.RequestDecisionComment, { attachedTo: value._id }, (res) => {
|
||||||
comments = new Map(res.map((r) => [r.modifiedBy, r]))
|
comments = new Map(
|
||||||
|
res.map((r) => {
|
||||||
|
const personAccount = $personAccountByIdStore.get(r.modifiedBy as Ref<PersonAccount>)
|
||||||
|
return [personAccount?.person, r]
|
||||||
|
})
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
interface RequestDecision {
|
interface RequestDecision {
|
||||||
employee: Ref<PersonAccount>
|
employee: Ref<Person>
|
||||||
decision?: boolean
|
decision?: boolean
|
||||||
comment?: RequestDecisionComment
|
comment?: RequestDecisionComment
|
||||||
}
|
}
|
||||||
|
|
||||||
function convert (value: Request, comments: Map<Ref<Account>, RequestDecisionComment>): RequestDecision[] {
|
function convert (value: Request, comments: Map<Ref<Person> | undefined, RequestDecisionComment>): RequestDecision[] {
|
||||||
const res: RequestDecision[] = []
|
const res: RequestDecision[] = []
|
||||||
for (const emp of value.requested) {
|
for (const emp of value.requested) {
|
||||||
const decision = value.rejected === emp ? false : value.approved.includes(emp) ? true : undefined
|
const decision = value.rejected === emp ? false : value.approved.includes(emp) ? true : undefined
|
||||||
@ -63,7 +68,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{#each convert(value, comments) as requested}
|
{#each convert(value, comments) as requested}
|
||||||
<tr class="antiTable-body__row">
|
<tr class="antiTable-body__row">
|
||||||
<td><PersonAccountRefPresenter value={requested.employee} /></td>
|
<td><PersonRefPresenter value={requested.employee} /></td>
|
||||||
<td><BooleanIcon value={requested.decision} /></td>
|
<td><BooleanIcon value={requested.decision} /></td>
|
||||||
<td
|
<td
|
||||||
>{#if requested.comment}
|
>{#if requested.comment}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { PersonAccount } from '@hcengineering/contact'
|
import { type Person } from '@hcengineering/contact'
|
||||||
import type { AttachedDoc, Class, Doc, Mixin, Ref, Timestamp, Tx } from '@hcengineering/core'
|
import type { AttachedDoc, Class, Doc, Mixin, Ref, Timestamp, Tx } from '@hcengineering/core'
|
||||||
import type { Asset, IntlString, Plugin } from '@hcengineering/platform'
|
import type { Asset, IntlString, Plugin } from '@hcengineering/platform'
|
||||||
import { plugin } from '@hcengineering/platform'
|
import { plugin } from '@hcengineering/platform'
|
||||||
@ -24,11 +24,11 @@ import { ChatMessage } from '@hcengineering/chunter'
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export interface Request extends AttachedDoc {
|
export interface Request extends AttachedDoc {
|
||||||
requested: Ref<PersonAccount>[]
|
requested: Ref<Person>[]
|
||||||
approved: Ref<PersonAccount>[]
|
approved: Ref<Person>[]
|
||||||
approvedDates?: Timestamp[]
|
approvedDates?: Timestamp[]
|
||||||
requiredApprovesCount: number
|
requiredApprovesCount: number
|
||||||
rejected?: Ref<PersonAccount>
|
rejected?: Ref<Person>
|
||||||
status: RequestStatus
|
status: RequestStatus
|
||||||
tx: Tx
|
tx: Tx
|
||||||
rejectedTx?: Tx
|
rejectedTx?: Tx
|
||||||
|
Loading…
Reference in New Issue
Block a user