diff --git a/assets/i18n/ar.json b/assets/i18n/ar.json index c56862f90..10035caed 100644 --- a/assets/i18n/ar.json +++ b/assets/i18n/ar.json @@ -104,6 +104,7 @@ "CAPACITY_STRENGTHENING_COST": "تكلفة تعزيز القدرات", "CAPACITY_STRENGTHENING_COST_AUTOMATIC": "النسبة المئوية لتكلفة تعزيز القدرات", "CAPACITY_STRENGTHENING_COST_DESCRIPTION": "تكلفة تعزيز القدرات", + "UNFUNDED_HQ_CASH": "تعزيز القدرات غير ممولة", "CASH_TRANSFERED": "تحويل نقدي", "CASH_TRANSFER_MOD": "طريقة (طرق) التحويل النقدي", "CASH_TRANSFER_MODALITIES": { @@ -126,6 +127,7 @@ "COMPLETED": "مكتمل", "CONFIDENTIAL": "مؤتمن", "CONFIDENTIAL_INFO": "سيمنع هذا التبديل استخدام PD في لوحات المعلومات الخارجية لليونيسف.", + "HAS_UNFUNDED_CASH": "تتضمن وثيقة البرنامج هذه مبالغ غير ممولة", "CONFIRM_BTN_TEXT": "نعم", "CONFIRM_BTN_TXT": "نعم", "CONTEXT": "سياق", @@ -313,6 +315,7 @@ "INVALID_ERR": "غير صالح", "INVALID_NUMBER": "رقم غير صالح", "INVALID_TOTAL_ACTIVITY_ITEMS": "بيانات الميزانية غير صالحة. يجب أن تكون أموال اليونيسف + الشريك مساوية لإجمالي النقد.", + "INVALID_TOTAL_UNFUNDED_ACTIVITY_ITEMS": "بيانات الميزانية غير صالحة. اليونيسف + النقد الشريك + النقد غير الممول يجب أن يكون مساوياً لإجمالي النقد.", "IS_ACTIVE": "نشط", "ITEM_ALL_PRICES": "البند (جميع الأسعار بعملة PD)", "ITEM_DESCRIPTION": "وصف السلعة", @@ -671,6 +674,7 @@ "TITLE_3": "التخطيط والمراقبة والتقييم والاتصال", "TOTAL": "المجموع", "TOTAL_AMT": "المبلغ الإجمالي (النقد + العرض)", + "TOTAL_AMT_UNFUNDED": "المبلغ الإجمالي (النقد + العرض + غير الممول)", "TOTAL_CASH": "مجموع المبالغ النقدية", "TOTAL_CASH_AMT": "المبلغ النقدي الإجمالي", "TOTAL_CASH_BUDGET": "إجمالي الميزانية النقدية", @@ -688,6 +692,7 @@ "TOTAL_UNICEF_CONTRIB": "إجمالي مساهمة اليونيسيف", "TOTAL_UNICEF_CONTRIBUTION": "إجمالي مساهمة اليونيسف", "TOTAL_UNICEF_SUPPLY": "إجمالي العرض", + "TOTAL_UNFUNDED": "إجمالي غير الممول", "TOTAL_VALUE_UNICEF_CONTRIB_EFF": "النسبة المئوية للقيمة الإجمالية لمساهمة اليونيسف التي تمثل تكلفة إدارة البرامج الفعالة والفعالة", "TOTAL_VAL_EFF_PROG_MGMT_COST": "القيمة الإجمالية لتكلفة إدارة البرنامج الفعال", "TRUE": "حقيقي", @@ -710,6 +715,7 @@ "UNICEF_SUPPLY_CONTRIB": "مساهمة إمدادات اليونيسف", "UNICEF_USER_ERR": "الرجاء تحديد مستخدم اليونيسف", "UNIT": "وحدة", + "UNFUNDED_CASH": "النقدية غير الممولة", "UNKNOWN": "مجهول", "UNLOCK": "الغاء القفل", "UNLOCK_PROMPT": "أنت على وشك إزالة جميع الموافقات على هذا المستند ، من قبل اليونيسف أو الشريك ، من أجل تمكين التحرير. هل أنت متأكد أنك تريد الاستمرار؟", diff --git a/assets/i18n/en.json b/assets/i18n/en.json index fff25c5b6..751873132 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -104,6 +104,7 @@ "CAPACITY_STRENGTHENING_COST": "Capacity-Strengthening Cost", "CAPACITY_STRENGTHENING_COST_AUTOMATIC": "Capacity-Strengthening Cost Percentage", "CAPACITY_STRENGTHENING_COST_DESCRIPTION": "Capacity-Strengthening Cost", + "UNFUNDED_HQ_CASH": "Capacity-Strengthening Unfunded", "CASH_TRANSFERED": "Cash Transferred", "CASH_TRANSFER_MOD": "Cash Transfer Modality(ies)", "CASH_TRANSFER_MODALITIES": { @@ -126,6 +127,7 @@ "COMPLETED": "Completed", "CONFIDENTIAL": "Confidential", "CONFIDENTIAL_INFO": "This toggle will prevent this PD to be used in dashboards external to UNICEF.", + "HAS_UNFUNDED_CASH": "This Programme Document includes unfunded amounts", "CONFIRM_BTN_TEXT": "Yes", "CONFIRM_BTN_TXT": "Yes", "CONTEXT": "Context", @@ -313,6 +315,7 @@ "INVALID_ERR": "Invalid", "INVALID_NUMBER": "Invalid number", "INVALID_TOTAL_ACTIVITY_ITEMS": "Invalid budget data. UNICEF + Partner Cash should be equal to Total Cash.", + "INVALID_TOTAL_UNFUNDED_ACTIVITY_ITEMS": "Invalid budget data. UNICEF + Partner Cash + Unfunded Cash should be equal to Total Cash.", "IS_ACTIVE": "Is active", "ITEM_ALL_PRICES": "Item (all prices in PD Currency)", "ITEM_DESCRIPTION": "Item Description", @@ -671,6 +674,7 @@ "TITLE_3": "Planning, monitoring, evaluation and communication", "TOTAL": "Total", "TOTAL_AMT": "Total Amt (Cash + Supply)", + "TOTAL_AMT_UNFUNDED": "Total Amt (Cash + Supply + Unfunded)", "TOTAL_CASH": "Total Cash", "TOTAL_CASH_AMT": "Total Cash Amt", "TOTAL_CASH_BUDGET": "Total Cash Budget", @@ -688,6 +692,7 @@ "TOTAL_UNICEF_CONTRIB": "Total UNICEF Contrib", "TOTAL_UNICEF_CONTRIBUTION": "Total UNICEF Contribution", "TOTAL_UNICEF_SUPPLY": "Total UNICEF Supply", + "TOTAL_UNFUNDED": "Total Unfunded", "TOTAL_VALUE_UNICEF_CONTRIB_EFF": "% Total value of UNICEF's contribution that is Effective and Efficient Programme Management Cost", "TOTAL_VAL_EFF_PROG_MGMT_COST": "Total value of the Effective Programme management Cost", "TRUE": "True", @@ -710,6 +715,7 @@ "UNICEF_SUPPLY_CONTRIB": "UNICEF Supply Contribution", "UNICEF_USER_ERR": "Please select UNICEF user", "UNIT": "Unit", + "UNFUNDED_CASH": "Unfunded Cash", "UNKNOWN": "Unknown", "UNLOCK": "Unlock", "UNLOCK_PROMPT": "You are about to remove all approvals of this document, by unicef or partner, in order to enable editing. Are you sure you want to continue?", diff --git a/assets/i18n/es.json b/assets/i18n/es.json index 42c6f8fe7..2c959a651 100644 --- a/assets/i18n/es.json +++ b/assets/i18n/es.json @@ -104,6 +104,7 @@ "CAPACITY_STRENGTHENING_COST": "Coste del refuerzo de las capacidades", "CAPACITY_STRENGTHENING_COST_AUTOMATIC": "Porcentaje del coste de refuerzo de las capacidades", "CAPACITY_STRENGTHENING_COST_DESCRIPTION": "Coste del refuerzo de las capacidades", + "UNFUNDED_HQ_CASH": "Fortalecimiento de capacidades Sin financiación", "CASH_TRANSFERED": "Efectivo transferido", "CASH_TRANSFER_MOD": "Modalidad(es) de transferencia de efectivo", "CASH_TRANSFER_MODALITIES": { @@ -126,6 +127,7 @@ "COMPLETED": "COMPLETADO", "CONFIDENTIAL": "Confidencial", "CONFIDENTIAL_INFO": "Este conmutador impedirá que esta EP se utilice en cuadros de mando externos a UNICEF.", + "HAS_UNFUNDED_CASH": "Este documento de programa incluye montos no financiados", "CONFIRM_BTN_TEXT": "Sí", "CONFIRM_BTN_TXT": "Sí", "CONTEXT": "Contexto", @@ -313,6 +315,7 @@ "INVALID_ERR": "Invalido", "INVALID_NUMBER": "Número inválido", "INVALID_TOTAL_ACTIVITY_ITEMS": "Datos presupuestarios no válidos. UNICEF + Efectivo de los socios debe ser igual a Efectivo total.", + "INVALID_TOTAL_UNFUNDED_ACTIVITY_ITEMS": "Datos de presupuesto no válidos. UNICEF + Efectivo de socios + Efectivo no financiado debe ser igual al Efectivo total.", "IS_ACTIVE": "Está activo", "ITEM_ALL_PRICES": "Artículo (todos los precios en moneda PD)", "ITEM_DESCRIPTION": "Descripción del artículo", @@ -671,6 +674,7 @@ "TITLE_3": "Planificación, seguimiento, evaluación y comunicación", "TOTAL": "TOTAL", "TOTAL_AMT": "Importe total (efectivo + suministros)", + "TOTAL_AMT_UNFUNDED": "Importe total (Efectivo + Suministro + No financiado)", "TOTAL_CASH": "Total de efectivo", "TOTAL_CASH_AMT": "Importe total en efectivo", "TOTAL_CASH_BUDGET": "Presupuesto de tesorería total", @@ -688,6 +692,7 @@ "TOTAL_UNICEF_CONTRIB": "Total UNICEF Contrib", "TOTAL_UNICEF_CONTRIBUTION": "Contribución total de UNICEF", "TOTAL_UNICEF_SUPPLY": "Suministro total de UNICEF", + "TOTAL_UNFUNDED": "Total no financiado", "TOTAL_VALUE_UNICEF_CONTRIB_EFF": "% Valor total de la contribución de UNICEF que es Eficaz y eficiente Coste de gestión del programa", "TOTAL_VAL_EFF_PROG_MGMT_COST": "Valor total de la gestión efectiva del programa Coste", "TRUE": "Verdadero", @@ -710,6 +715,7 @@ "UNICEF_SUPPLY_CONTRIB": "Contribución de UNICEF", "UNICEF_USER_ERR": "Seleccione el usuario de UNICEF", "UNIT": "Unidad", + "UNFUNDED_CASH": "Efectivo sin financiar", "UNKNOWN": "Desconocido", "UNLOCK": "Desbloquear", "UNLOCK_PROMPT": "Usted está a punto de eliminar todas las aprobaciones de este documento, por unicef o socio, con el fin de permitir la edición. ¿Está seguro de que desea continuar?", diff --git a/assets/i18n/fr.json b/assets/i18n/fr.json index 56087a06f..d34261535 100644 --- a/assets/i18n/fr.json +++ b/assets/i18n/fr.json @@ -104,6 +104,7 @@ "CAPACITY_STRENGTHENING_COST": "Coût du renforcement des capacités", "CAPACITY_STRENGTHENING_COST_AUTOMATIC": "Pourcentage des coûts de renforcement des capacités", "CAPACITY_STRENGTHENING_COST_DESCRIPTION": "Coût du renforcement des capacités", + "UNFUNDED_HQ_CASH": "Renforcement des capacités Non financé", "CASH_TRANSFERED": "Espèces transférées ", "CASH_TRANSFER_MOD": "Modalité(s) de transfert(s) monétaire(s)", "CASH_TRANSFER_MODALITIES": { @@ -126,6 +127,7 @@ "COMPLETED": "Complété", "CONFIDENTIAL": "Confidentiel ", "CONFIDENTIAL_INFO": "Cette bascule empêchera ce DP d’être utilisée dans des tableaux de bord extérieurs à l’UNICEF", + "HAS_UNFUNDED_CASH": "Ce Document de Programme comprend des montants non financés", "CONFIRM_BTN_TEXT": "Oui", "CONFIRM_BTN_TXT": "Oui", "CONTEXT": "Contexte", @@ -313,6 +315,7 @@ "INVALID_ERR": "Invalide", "INVALID_NUMBER": "Numéro non valide", "INVALID_TOTAL_ACTIVITY_ITEMS": "Données budgétaires non valides. Espèces UNICEF + Partenaire devrait être égal au Total Espèces.", + "INVALID_TOTAL_UNFUNDED_ACTIVITY_ITEMS": "Données budgétaires non valides. L'UNICEF + l'argent du partenaire + l'argent non financé doit être égal au total de l'argent.", "IS_ACTIVE": "C'est actif", "ITEM_ALL_PRICES": "Article (tous les prix dans la devise du DP)", "ITEM_DESCRIPTION": "Description de l’objet ", @@ -671,6 +674,7 @@ "TITLE_3": "Planification, suivi, évaluation et communication", "TOTAL": "Total", "TOTAL_AMT": "Total Amdt (Espèces + Fournitures)", + "TOTAL_AMT_UNFUNDED": "Montant total (liquidités + crédits + non financés)", "TOTAL_CASH": "Total Espèces ", "TOTAL_CASH_AMT": "Total Amdt Espèces", "TOTAL_CASH_BUDGET": "Budget Total Esp", @@ -688,6 +692,7 @@ "TOTAL_UNICEF_CONTRIB": "Contribution totale de l’UNICEF", "TOTAL_UNICEF_CONTRIBUTION": "Contribution totale de l’UNICEF", "TOTAL_UNICEF_SUPPLY": "Total Fournitures UNICEF", + "TOTAL_UNFUNDED": "Total non financé", "TOTAL_VALUE_UNICEF_CONTRIB_EFF": "Valeur totale de la contribution de l’UNICEF qui est un coût de gestion efficace et efficiente du programme", "TOTAL_VAL_EFF_PROG_MGMT_COST": "Valeur totale du Coût Réel de Gestion du Programme", "TRUE": "Vrai", @@ -710,6 +715,7 @@ "UNICEF_SUPPLY_CONTRIB": "Contribution en approvisionnement de l’UNICEF", "UNICEF_USER_ERR": "Veuillez sélectionner l’utilisateur UNICEF", "UNIT": "Unité", + "UNFUNDED_CASH": "Espèces non financées", "UNKNOWN": "Inconnu", "UNLOCK": "Déverrouiller", "UNLOCK_PROMPT": "هل أنت تأكد أنك تريد فتحه؟", diff --git a/assets/i18n/pt.json b/assets/i18n/pt.json index 873e5eac8..75f6c76cd 100644 --- a/assets/i18n/pt.json +++ b/assets/i18n/pt.json @@ -104,6 +104,7 @@ "CAPACITY_STRENGTHENING_COST": "Custo de fortalecimento da capacidade", "CAPACITY_STRENGTHENING_COST_AUTOMATIC": "Porcentagem de custo de fortalecimento da capacidade", "CAPACITY_STRENGTHENING_COST_DESCRIPTION": "Custo de reforço da capacidade", + "UNFUNDED_HQ_CASH": "Reforço de Capacidade Não Financiado", "CASH_TRANSFERED": "Valor financeiro Transferido", "CASH_TRANSFER_MOD": "Modalidade (s) de transferência financeira ", "CASH_TRANSFER_MODALITIES": { @@ -126,6 +127,7 @@ "COMPLETED": "Concluído", "CONFIDENTIAL": "Confidencial", "CONFIDENTIAL_INFO": "Esta alternância impedirá que este PD seja usado em painéis externos ao UNICEF", + "HAS_UNFUNDED_CASH": "Este documento do programa inclui valores não financiados", "CONFIRM_BTN_TEXT": "Sim", "CONFIRM_BTN_TXT": "Sim", "CONTEXT": "Contexto", @@ -313,6 +315,7 @@ "INVALID_ERR": "Inválido", "INVALID_NUMBER": "Número inválido", "INVALID_TOTAL_ACTIVITY_ITEMS": "Dado orçamentário inválido. Orçamento financeiro do Unicef + Parceiro deve ser igual ao orçamento total.", + "INVALID_TOTAL_UNFUNDED_ACTIVITY_ITEMS": "Dados de orçamento inválidos. UNICEF + Dinheiro do Parceiro + Dinheiro Não Financiado deve ser igual ao Dinheiro Total.", "IS_ACTIVE": "Está ativo", "ITEM_ALL_PRICES": "Item (todos os valoresna moeda do PD)", "ITEM_DESCRIPTION": "Descrição do item", @@ -671,6 +674,7 @@ "TITLE_3": "Planejamento, monitoramento, avaliação e comunicação", "TOTAL": "Total", "TOTAL_AMT": "Valor total (dinheiro+ suprimentos)", + "TOTAL_AMT_UNFUNDED": "Montante total (Caixa + Fornecimento + Não financiado)", "TOTAL_CASH": "Oçamento financeiro total", "TOTAL_CASH_AMT": "Valor Total em Dinheiro", "TOTAL_CASH_BUDGET": "Total de recurso financeiro", @@ -688,6 +692,7 @@ "TOTAL_UNICEF_CONTRIB": "Contribuição Total UNICEF", "TOTAL_UNICEF_CONTRIBUTION": "Contribuição Total do UNICEF", "TOTAL_UNICEF_SUPPLY": "Suprimento Total UNICEF", + "TOTAL_UNFUNDED": "Total não financiado", "TOTAL_VALUE_UNICEF_CONTRIB_EFF": "% Valor total da contribuição do Unicef como custo efetivo e eficiente da gestão do programa", "TOTAL_VAL_EFF_PROG_MGMT_COST": "Valor total do custo efetivo da gestão do programa", "TRUE": "Verdadeiro", @@ -710,6 +715,7 @@ "UNICEF_SUPPLY_CONTRIB": "Contribuição em suprimentos do UNICEF", "UNICEF_USER_ERR": "Por favor, selecione usuário do UNICEF", "UNIT": "Unidade", + "UNFUNDED_CASH": "Dinheiro não financiado", "UNKNOWN": "Desconhecido", "UNLOCK": "Desbloquear", "UNLOCK_PROMPT": "Você está prestes a remover todas as aprovações para este documento, tanto pelo UNICEF quanto pelo parceiro, a fim de permitir edição. Você tem certeza de que deseja continuar??", diff --git a/assets/i18n/ru.json b/assets/i18n/ru.json index a7a8ff5ce..28737a564 100644 --- a/assets/i18n/ru.json +++ b/assets/i18n/ru.json @@ -104,6 +104,7 @@ "CAPACITY_STRENGTHENING_COST": "Затраты на укрепление потенциала", "CAPACITY_STRENGTHENING_COST_AUTOMATIC": "Процент затрат на укрепление мощностей", "CAPACITY_STRENGTHENING_COST_DESCRIPTION": "Затраты на укрепление потенциала", + "UNFUNDED_HQ_CASH": "Укрепление потенциала", "CASH_TRANSFERED": "Перечислено денежных средств", "CASH_TRANSFER_MOD": "Метод/ы денежных переводов", "CASH_TRANSFER_MODALITIES": { @@ -126,6 +127,7 @@ "COMPLETED": "Завершено", "CONFIDENTIAL": "Конфиденциально", "CONFIDENTIAL_INFO": "Эта функция позволит предотвратить использование этого ПД на других информационных платформах, не относящихся к ЮНИСЕФ. ", + "HAS_UNFUNDED_CASH": "Этот программный документ включает необеспеченные суммы", "CONFIRM_BTN_TEXT": "Да", "CONFIRM_BTN_TXT": "Да", "CONTEXT": "контекст", @@ -313,6 +315,7 @@ "INVALID_ERR": "Неверно", "INVALID_NUMBER": "Неправильный номер", "INVALID_TOTAL_ACTIVITY_ITEMS": "Ошибка бюджета. Денежный вклад ЮНИСЕФ + денежный вклад партнера должны равняться Общей сумме денежных средств", + "INVALID_TOTAL_UNFUNDED_ACTIVITY_ITEMS": "Неверные данные бюджета. Денежные средства ЮНИСЕФ + Партнерские денежные средства + Необеспеченные денежные средства должны равняться общей сумме денежных средств.", "IS_ACTIVE": "Активен", "ITEM_ALL_PRICES": "Статья (все суммы в валюте ПД)", "ITEM_DESCRIPTION": "Описание статьи", @@ -671,6 +674,7 @@ "TITLE_3": "Планирование, мониторинг и коммуникации", "TOTAL": "Итого ", "TOTAL_AMT": "Общая сумма (денежная+материальная)", + "TOTAL_AMT_UNFUNDED": "Общая сумма (наличные + обеспечение + нефинансирование)", "TOTAL_CASH": "Итого денежных средств ", "TOTAL_CASH_AMT": "Общая денежная сумма ", "TOTAL_CASH_BUDGET": "Общий денежный бюджет", @@ -688,6 +692,7 @@ "TOTAL_UNICEF_CONTRIB": "Общий вклад ЮНИСЕФ", "TOTAL_UNICEF_CONTRIBUTION": "Общий вклад ЮНИСЕФ", "TOTAL_UNICEF_SUPPLY": "Общий объем поставок ЮНИСЕФ", + "TOTAL_UNFUNDED": "Всего не профинансировано", "TOTAL_VALUE_UNICEF_CONTRIB_EFF": "% от общей стоимости вклада ЮНИСЕФ, которая представляет собой расходы на эффективное управление программами", "TOTAL_VAL_EFF_PROG_MGMT_COST": "Общая стоимость затрат на эффективное управление программой", "TRUE": "верно", @@ -710,6 +715,7 @@ "UNICEF_SUPPLY_CONTRIB": "Вклад ЮНИСЕФ в снабжение", "UNICEF_USER_ERR": "Пожалуйста, выберите пользователя ЮНИСЕФ", "UNIT": "Единица", + "UNFUNDED_CASH": "Необеспеченные денежные средства", "UNKNOWN": "Неизвестно", "UNLOCK": "Разблокировать", "UNLOCK_PROMPT": "Что бы активировать правку документа, вы собираетесь удалить все одобрения со стороны ЮНИСЕФ или партнера. Вы уверены, что хотите продолжить? ", diff --git a/common/budget-summary/budget-summary.ts b/common/budget-summary/budget-summary.ts index 9a9128078..345851991 100644 --- a/common/budget-summary/budget-summary.ts +++ b/common/budget-summary/budget-summary.ts @@ -10,7 +10,7 @@ import '@unicef-polymer/etools-info-tooltip/etools-info-tooltip'; import {InfoElementStyles} from '@unicef-polymer/etools-modules-common/dist/styles/info-element-styles'; import {CommentsMixin} from '../components/comments/comments-mixin'; import {FrsDetails, Intervention} from '@unicef-polymer/etools-types'; -import {translate} from 'lit-translate'; +import {translate, get as getTranslation} from 'lit-translate'; import {TABS} from '../constants'; import {isUnicefUser} from '../selectors'; import FrNumbersConsistencyMixin from '@unicef-polymer/etools-modules-common/dist/mixins/fr-numbers-consistency-mixin'; @@ -95,7 +95,7 @@ export class BudgetSummaryEl extends CommentsMixin(FrNumbersConsistencyMixin(Lit
${this.getTable()}
- +
${this.budgetSummary.currency} ${displayCurrencyAmount( String(this.budgetSummary.total_local) @@ -186,7 +186,7 @@ export class BudgetSummaryEl extends CommentsMixin(FrNumbersConsistencyMixin(Lit
- +
${displayCurrencyAmount(String(this.budgetSummary.total_local))}
@@ -213,6 +213,14 @@ export class BudgetSummaryEl extends CommentsMixin(FrNumbersConsistencyMixin(Lit (${displayCurrencyAmount(String(this.budgetSummary.total_partner_contribution_local))})
+ ${this.intervention.planned_budget.has_unfunded_cash + ? html`
+ +
+ ${displayCurrencyAmount(String(this.budgetSummary.total_unfunded))} +
+
` + : ''}
`; } @@ -250,8 +258,8 @@ export class BudgetSummaryEl extends CommentsMixin(FrNumbersConsistencyMixin(Lit ) { return; } - this.budgetSummary = selectBudgetSummary(state); this.intervention = state.interventions.current; + this.budgetSummary = selectBudgetSummary(state); this.frsDetails = this.intervention.frs_details; if (isUnicefUser(state)) { this.setFrsConsistencyWarning(); @@ -279,6 +287,10 @@ export class BudgetSummaryEl extends CommentsMixin(FrNumbersConsistencyMixin(Lit return !value && value !== 0; } + getTotalLabel(intervention: Intervention) { + return getTranslation(intervention.planned_budget.has_unfunded_cash ? 'TOTAL_AMT_UNFUNDED' : 'TOTAL_AMT'); + } + currenciesMatch() { if (!this.frsDetails.frs.length) { // if no FR number added, hide currency-mismatch tooltip diff --git a/common/budget-summary/budgetSummary.models.ts b/common/budget-summary/budgetSummary.models.ts index eb3698298..1a63edb2b 100644 --- a/common/budget-summary/budgetSummary.models.ts +++ b/common/budget-summary/budgetSummary.models.ts @@ -21,4 +21,5 @@ export class BudgetSummary extends ModelsBase { total_hq_cash_local = 0; partner_supply_local = 0; total_partner_contribution_local = 0; + total_unfunded = 0; } diff --git a/common/components/activity/activity-item-row.ts b/common/components/activity/activity-item-row.ts index 904ae37bf..ce408816b 100644 --- a/common/components/activity/activity-item-row.ts +++ b/common/components/activity/activity-item-row.ts @@ -41,11 +41,14 @@ export class ActivityItemRow extends ActivitiesCommonMixin(LitElement) { @property() invalidName = false; @property() invalidUnit = false; @property() invalidNoUnits = false; + @property() invalidUnitPrice = false; + @property() invalidCsoCash = false; + @property() invalidUnicefCash = false; + @property() invalidUnfundedCash = false; @property() invalidSum = false; @property() readonly: boolean | undefined = false; @property() lastItem: boolean | undefined = false; - @property({type: String}) - currency = ''; + @property({type: String}) currency = ''; protected render(): TemplateResult { return this.activityItem @@ -109,6 +112,7 @@ export class ActivityItemRow extends ActivitiesCommonMixin(LitElement) { }}" no-of-decimals="2" error-message="" + required >
@@ -134,16 +145,23 @@ export class ActivityItemRow extends ActivitiesCommonMixin(LitElement) { data-col-header-label="${translate('PARTNER_CASH')}" >
+ ${this.hasUnfundedCash + ? html`
+ +
` + : ``}
[] = []; @property() readonly: boolean | undefined = false; @property() dialogElement!: EtoolsDialog; - @property({type: String}) - currency = ''; + @property({type: String}) currency = ''; + @property() hasUnfundedCash = false; protected render(): TemplateResult { // language=html @@ -57,9 +57,12 @@ export class ActivityItemsTable extends LitElement {
-
${translate('PRICE_UNIT')}
-
${translate('PARTNER_CASH')}
-
${translate('UNICEF_CASH')}
+
+
+
+
+ +
${translate('TOTAL_CASH')} (${this.currency})
@@ -76,6 +79,7 @@ export class ActivityItemsTable extends LitElement { .readonly="${this.readonly}" .lastItem="${this.isLastItem(index)}" .currency="${this.currency}" + .hasUnfundedCash="${this.hasUnfundedCash}" >` )} ${!this.readonly @@ -111,7 +115,8 @@ export class ActivityItemsTable extends LitElement { cso_cash: '0', unicef_cash: '0', name: '', - unit_price: '0' + unit_price: '0', + unfunded_cash: '0' } ]; this.setFocusOnActivityRow(); diff --git a/common/components/activity/get-total.helper.ts b/common/components/activity/get-total.helper.ts index c2d8785ec..089504671 100644 --- a/common/components/activity/get-total.helper.ts +++ b/common/components/activity/get-total.helper.ts @@ -1,10 +1,18 @@ import {displayCurrencyAmount} from '@unicef-polymer/etools-currency-amount-input/mixins/etools-currency-module'; -export function getTotalCash(csoCash: number | string, unicefCash: number | string): number { - return Number(((Number(csoCash) || 0) + (Number(unicefCash) || 0)).toFixed(2)); +export function getTotalCash( + csoCash: number | string, + unicefCash: number | string, + unfundedCash?: number | string +): number { + return Number(((Number(csoCash) || 0) + (Number(unicefCash) || 0) + (Number(unfundedCash) || 0)).toFixed(2)); } -export function getTotalCashFormatted(csoCash: number | string, unicefCash: number | string): string { - return displayCurrencyAmount(String(getTotalCash(csoCash, unicefCash)), '0', 2); +export function getTotalCashFormatted( + csoCash: number | string, + unicefCash: number | string, + unfundedCash?: number | string +): string { + return displayCurrencyAmount(String(getTotalCash(csoCash, unicefCash, unfundedCash)), '0', 2); } export function getMultiplyProductCash(unit: number | string, price: number | string): number { diff --git a/common/mixins/activities-common.mixin.ts b/common/mixins/activities-common.mixin.ts index f63a8eb55..e39e2b1f1 100644 --- a/common/mixins/activities-common.mixin.ts +++ b/common/mixins/activities-common.mixin.ts @@ -5,19 +5,23 @@ import {getItemTotal} from '../components/activity/get-total.helper'; export function ActivitiesCommonMixin>(baseClass: T) { return class ActivitiesCommonClass extends ModelChangedMixin(baseClass) { + // @ts-ignore + @property({type: Boolean}) + hasUnfundedCash!: boolean; + cashFieldChanged( detail: {value: any}, - field: 'unicef_cash' | 'cso_cash', - item: Partial + field: 'unicef_cash' | 'cso_cash' | 'unfunded_cash', + item: Partial, + setSecondCashField = true ): void { this.numberChanged(detail, field, item); - if (!item.unit_price || !item.no_units) { - return; - } - const secondCashField = field === 'unicef_cash' ? 'cso_cash' : 'unicef_cash'; const total = getItemTotal(item); - const value = Number(Math.max(0, total - detail.value).toFixed(2)); // in js 12019.15-11130 = 889.1499999999996 - this.numberChanged({value}, secondCashField, item); + if (setSecondCashField) { + const secondCashField = field === 'unicef_cash' ? 'cso_cash' : 'unicef_cash'; + const value = Number(Math.max(0, total - detail.value).toFixed(2)); // in js 12019.15-11130 = 889.1499999999996 + this.numberChanged({value}, secondCashField, item); + } } activityItemInvalidChanged(detail: {value: any}, field: string, item: any) { @@ -65,22 +69,22 @@ export function ActivitiesCommonMixin>(baseCla } validateCsoAndUnicefCashForItem(item: any) { - if (Number(item.no_units) == 0 || Number(item.unit_price) == 0) { - return; - } - let total = (Number(item.no_units) || 0) * (Number(item.unit_price) || 0); total = Number(total.toFixed(2)); - let sum = (Number(item.cso_cash) || 0) + (Number(item.unicef_cash) || 0); + let sum = + (Number(item.cso_cash) || 0) + + (Number(item.unicef_cash) || 0) + + (this.hasUnfundedCash ? Number(item.unfunded_cash) || 0 : 0); sum = Number(sum.toFixed(2)); if (total != sum) { - item.invalid = {...item.invalid, ...{cso_cash: true, unicef_cash: true}}; + item.invalid = {...item.invalid, ...{cso_cash: true, unicef_cash: true, unfunded_cash: true}}; } else { item.invalid = { ...item.invalid, ...{ cso_cash: item.cso_cash === null || item.cso_cash === undefined || isNaN(item.cso_cash), - unicef_cash: item.unicef_cash === null || item.unicef_cash === undefined || isNaN(item.unicef_cash) + unicef_cash: item.unicef_cash === null || item.unicef_cash === undefined || isNaN(item.unicef_cash), + unfunded_cash: item.unfunded_cash === null || item.unfunded_cash === undefined || isNaN(item.unfunded_cash) } }; } @@ -98,7 +102,8 @@ export function ActivitiesCommonMixin>(baseCla no_units: false, unit_price: false, cso_cash: false, - unicef_cash: false + unicef_cash: false, + unfunded_cash: false }; }); } @@ -119,6 +124,11 @@ export function ActivitiesCommonMixin>(baseCla activity.unicef_cash = String( activity.items.reduce((sum: number, item: {unicef_cash: any}) => sum + Number(item.unicef_cash), 0) ); + if (this.hasUnfundedCash) { + activity.unfunded_cash = String( + activity.items.reduce((sum: number, item: {unfunded_cash: any}) => sum + Number(item.unfunded_cash), 0) + ); + } } }; } diff --git a/common/types/editor-page-types.ts b/common/types/editor-page-types.ts index f8a72f0bf..bc5a39210 100644 --- a/common/types/editor-page-types.ts +++ b/common/types/editor-page-types.ts @@ -24,6 +24,7 @@ export declare type InterventionActivity = { name: string; time_frames: number[]; unicef_cash: string; + unfunded_cash: string; unicef_suppies: number; is_active: boolean; created: string; @@ -61,6 +62,7 @@ type InvalidItem = { unit_price: boolean; cso_cash: boolean; unicef_cash: boolean; + unfunded_cash: boolean; }; export type InterventionActivityExtended = InterventionActivity & { @@ -70,7 +72,14 @@ export type InterventionActivityExtended = InterventionActivity & { total: string; }; -type ItemInvalid = {name: boolean; context_details: boolean; time_frames: boolean}; +type ItemInvalid = { + name: boolean; + context_details: boolean; + time_frames: boolean; + cso_cash: boolean; + unicef_cash: boolean; + unfunded_cash: boolean; +}; export type ResultLinkLowerResultExtended = ResultLinkLowerResult & { inEditMode: boolean; @@ -98,6 +107,7 @@ export type ProgrammeManagementRow = { context_details: string; cso_cash: string; unicef_cash: string; + unfunded_cash: string; totalProgrammeManagementCash: number; total: string; items: ProgrammeManagementRowItemExtended[]; @@ -110,6 +120,6 @@ export type ProgrammeManagementRow = { export type ProgrammeManagementRowExtended = ProgrammeManagementRow & { inEditMode: boolean; itemsInEditMode: boolean; - invalid?: Partial<{unicef_cash: boolean; cso_cash: boolean}>; + invalid?: Partial<{unicef_cash: boolean; cso_cash: boolean; unfunded_cash: boolean}>; total: string; }; diff --git a/intervention-metadata/other/other.models.ts b/intervention-metadata/other/other.models.ts index 96a3fb4bf..eac591054 100644 --- a/intervention-metadata/other/other.models.ts +++ b/intervention-metadata/other/other.models.ts @@ -23,5 +23,6 @@ export class OtherPermissions extends ModelsBase { document_type = true; document_currency = true; confidential = true; + has_unfunded_cash = true; cfei_number = false; } diff --git a/intervention-metadata/other/other.ts b/intervention-metadata/other/other.ts index e48430380..861276222 100644 --- a/intervention-metadata/other/other.ts +++ b/intervention-metadata/other/other.ts @@ -86,9 +86,11 @@ export class Other extends CommentsMixin(ComponentBaseMixin(LitElement)) { max-height: 96px; } } - .confidential-row { + .toggle-row { + padding-bottom: 15px; + } + .mt-4 { margin-top: -4px; - padding-bottom: 12px; } paper-input { width: 100%; @@ -213,7 +215,7 @@ export class Other extends CommentsMixin(ComponentBaseMixin(LitElement)) { -
+
+
+ + ${translate('HAS_UNFUNDED_CASH')} + +
+ ${this.renderActions(this.editMode, this.canEditAtLeastOneField)} `; @@ -285,7 +301,7 @@ export class Other extends CommentsMixin(ComponentBaseMixin(LitElement)) { })) ]; } - this.data = selectOtherData(state); + this.data = cloneDeep(selectOtherData(state)); this.originalData = cloneDeep(this.data); this.setPermissions(state); super.stateChanged(state); @@ -356,13 +372,14 @@ export class Other extends CommentsMixin(ComponentBaseMixin(LitElement)) { removeUnchangedData(data: OtherData) { Object.keys(data).forEach((key) => { if (key == 'planned_budget') { - if (!this.permissions.edit.document_currency) { + if (!this.permissions.edit.document_currency && !this.permissions.edit.has_unfunded_cash) { // @ts-ignore delete data.planned_budget; } else { data.planned_budget = { id: data.planned_budget.id, - currency: data.planned_budget.currency + currency: data.planned_budget.currency, + has_unfunded_cash: data.planned_budget.has_unfunded_cash }; } } diff --git a/intervention-workplan-editor/editor-table.ts b/intervention-workplan-editor/editor-table.ts index 3103c3ae6..e0be57230 100644 --- a/intervention-workplan-editor/editor-table.ts +++ b/intervention-workplan-editor/editor-table.ts @@ -145,6 +145,9 @@ export class EditorTable extends CommentsMixin( .v-middle { vertical-align: middle; } + label[required] { + background: url('./images/required.svg') no-repeat 99% 20%/5px; + } @@ -156,6 +159,7 @@ export class EditorTable extends CommentsMixin( + ${this.hasUnfundedCash ? html`` : ''} @@ -175,7 +179,7 @@ export class EditorTable extends CommentsMixin( > - + - + @@ -233,7 +237,7 @@ export class EditorTable extends CommentsMixin( - + - + - + ` : ''} - + - - + + + ${this.hasUnfundedCash ? html`` : ``} @@ -193,6 +194,9 @@ export function ActivitiesMixin>(baseClass: T) ?readonly="${this.isReadonlyCash(activity.inEditMode, activity.items)}" @keydown="${(e: any) => this.handleEsc(e)}" @value-changed="${({detail}: CustomEvent) => this.numberChanged(detail, 'cso_cash', activity)}" + required + .invalid="${activity.invalid?.cso_cash}" + error-message="${translate('THIS_FIELD_IS_REQUIRED')}" > + ${this.hasUnfundedCash + ? html` ` + : ``} + ${this.hasUnfundedCash ? html`` : ``} @@ -383,15 +415,18 @@ export function ActivitiesMixin>(baseClass: T) validateActivity(activity: InterventionActivityExtended) { activity.invalid = {}; - if (!activity.name) { - activity.invalid.name = true; - } + + activity.invalid.name = !activity.name; + activity.invalid.unicef_cash = isNaN(parseFloat(String(activity.unicef_cash))); + activity.invalid.cso_cash = isNaN(parseFloat(String(activity.cso_cash))); + activity.invalid.unfunded_cash = isNaN(parseFloat(String(activity.unfunded_cash))); + if (this.quarters && this.quarters.length) { if (!(activity.time_frames && activity.time_frames.length)) { activity.invalid.time_frames = true; } } - return !Object.keys(activity.invalid).length; + return !Object.values(activity.invalid).some((val) => val === true); } // @ts-ignore diff --git a/intervention-workplan-editor/editor-utils/activity-item-mixin.ts b/intervention-workplan-editor/editor-utils/activity-item-mixin.ts index b83effae8..6bf8b66f9 100644 --- a/intervention-workplan-editor/editor-utils/activity-item-mixin.ts +++ b/intervention-workplan-editor/editor-utils/activity-item-mixin.ts @@ -205,7 +205,7 @@ export function ActivityItemsMixin>(baseClass: .value="${item.cso_cash}" @keydown="${(e: any) => this.handleEsc(e)}" @value-changed="${({detail}: CustomEvent) => { - this.cashFieldChanged(detail, 'cso_cash', item); + this.cashFieldChanged(detail, 'cso_cash', item, !this.hasUnfundedCash); this.updateActivityCashFromItem(activity, item); }}" > @@ -226,11 +226,35 @@ export function ActivityItemsMixin>(baseClass: .value="${item.unicef_cash}" @keydown="${(e: any) => this.handleEsc(e)}" @value-changed="${({detail}: CustomEvent) => { - this.cashFieldChanged(detail, 'unicef_cash', item); + this.cashFieldChanged(detail, 'unicef_cash', item, !this.hasUnfundedCash); this.updateActivityCashFromItem(activity, item); }}" > + ${this.hasUnfundedCash + ? html` ` + : ``} + + ${this.hasUnfundedCash + ? html` ` + : ``} + + ${this.hasUnfundedCash ? html`` : ``} - + ${repeat( @@ -90,6 +91,7 @@ export function ProgrammeManagementMixin>(base + ${this.hasUnfundedCash ? html`` : ''} @@ -148,6 +150,31 @@ export function ProgrammeManagementMixin>(base @value-changed="${({detail}: CustomEvent) => this.numberChanged(detail, 'unicef_cash', item)}" > + ${this.hasUnfundedCash + ? html` + + ` + : ``} + ${this.hasUnfundedCash ? html`` : ``} @@ -248,6 +276,7 @@ export function ProgrammeManagementMixin>(base context_details: getTranslation('DESCRIPTION_1'), cso_cash: data.act1_partner, unicef_cash: data.act1_unicef, + unfunded_cash: data.act1_unfunded, totalProgrammeManagementCash: getTotalCash(data.act1_partner, data.act1_unicef), total: data.act1_total, items: data.items.filter( @@ -264,6 +293,7 @@ export function ProgrammeManagementMixin>(base context_details: getTranslation('DESCRIPTION_2'), cso_cash: data.act2_partner, unicef_cash: data.act2_unicef, + unfunded_cash: data.act2_unfunded, totalProgrammeManagementCash: getTotalCash(data.act2_partner, data.act2_unicef), total: data.act2_total, items: data.items.filter( @@ -280,6 +310,7 @@ export function ProgrammeManagementMixin>(base context_details: getTranslation('DESCRIPTION_3'), cso_cash: data.act3_partner, unicef_cash: data.act3_unicef, + unfunded_cash: data.act3_unfunded, totalProgrammeManagementCash: getTotalCash(data.act3_partner, data.act3_unicef), total: data.act3_total, items: data.items.filter( @@ -334,7 +365,11 @@ export function ProgrammeManagementMixin>(base // @ts-ignore saveProgrammeManagement(programmeManagement: ProgrammeManagementRowExtended, interventionId: number) { - if (!this.validateProgrammeManagement(programmeManagement) || !this.validateActivityItems(programmeManagement)) { + if ( + !validateRequiredFields(this) || + !this.validateProgrammeManagement(programmeManagement) || + !this.validateActivityItems(programmeManagement) + ) { this.requestUpdate(); fireEvent(this, 'toast', { text: getTranslation('FIX_VALIDATION_ERRORS') @@ -385,6 +420,7 @@ export function ProgrammeManagementMixin>(base formatDataBeforeSave(data: any) { data[this.getPropertyName(data, 'partner')] = data.cso_cash; data[this.getPropertyName(data, 'unicef')] = data.unicef_cash; + data[this.getPropertyName(data, 'unfunded')] = data.unfunded_cash; } }; } diff --git a/intervention-workplan/effective-efficient-programme-mgmt/activity-dialog.ts b/intervention-workplan/effective-efficient-programme-mgmt/activity-dialog.ts index 78fc37558..f0b936af8 100644 --- a/intervention-workplan/effective-efficient-programme-mgmt/activity-dialog.ts +++ b/intervention-workplan/effective-efficient-programme-mgmt/activity-dialog.ts @@ -140,6 +140,19 @@ export class ActivityDialog extends ComponentBaseMixin(LitElement) { auto-validate > + + ` : html` + `}
${translate('UNICEF_CASH')} + + ${ + this.hasUnfundedCash + ? html` + ${translate('UNFUNDED_CASH')}` + : '' + } ${getTranslation('GENERAL.TOTAL') + ' (' + this.data.currency + ')'} @@ -130,6 +138,11 @@ export class EffectiveAndEfficientProgrammeManagement extends CommentsMixin(Comp
${item.unicef_cash}
+ ${this.hasUnfundedCash + ? html`
+ ${item.unfunded_cash} +
` + : ''}
${item.total}
@@ -179,6 +192,9 @@ export class EffectiveAndEfficientProgrammeManagement extends CommentsMixin(Comp @property({type: Number}) interventionId!: number; + @property({type: Boolean}) + hasUnfundedCash?: boolean; + connectedCallback() { super.connectedCallback(); } @@ -191,6 +207,7 @@ export class EffectiveAndEfficientProgrammeManagement extends CommentsMixin(Comp return; } this.interventionId = state.interventions.current.id!; + this.hasUnfundedCash = state.interventions.current.planned_budget.has_unfunded_cash; this.data = selectProgrammeManagement(state); this.originalData = cloneDeep(this.data); @@ -211,6 +228,7 @@ export class EffectiveAndEfficientProgrammeManagement extends CommentsMixin(Comp description: translate('DESCRIPTION_1'), partner_contribution: addCurrencyAmountDelimiter(data.act1_partner), unicef_cash: addCurrencyAmountDelimiter(data.act1_unicef), + unfunded_cash: addCurrencyAmountDelimiter(data.act1_unfunded), total: addCurrencyAmountDelimiter(data.act1_total), index: 1, kind: KindChoices.inCountry @@ -220,6 +238,7 @@ export class EffectiveAndEfficientProgrammeManagement extends CommentsMixin(Comp description: translate('DESCRIPTION_2'), partner_contribution: addCurrencyAmountDelimiter(data.act2_partner), unicef_cash: addCurrencyAmountDelimiter(data.act2_unicef), + unfunded_cash: addCurrencyAmountDelimiter(data.act2_unfunded), total: addCurrencyAmountDelimiter(data.act2_total), index: 2, kind: KindChoices.operational @@ -229,6 +248,7 @@ export class EffectiveAndEfficientProgrammeManagement extends CommentsMixin(Comp description: translate('DESCRIPTION_3'), partner_contribution: addCurrencyAmountDelimiter(data.act3_partner), unicef_cash: addCurrencyAmountDelimiter(data.act3_unicef), + unfunded_cash: addCurrencyAmountDelimiter(data.act3_unfunded), total: addCurrencyAmountDelimiter(data.act3_total), index: 3, kind: KindChoices.planning @@ -243,6 +263,7 @@ export class EffectiveAndEfficientProgrammeManagement extends CommentsMixin(Comp activity: {...activity, items: cloneDeep(this.data.items)}, interventionId: this.interventionId, currency: this.data.currency, + hasUnfundedCash: this.hasUnfundedCash, readonly: !this.canEdit } }); diff --git a/intervention-workplan/effective-efficient-programme-mgmt/effectiveEfficientProgrammeMgmt.models.ts b/intervention-workplan/effective-efficient-programme-mgmt/effectiveEfficientProgrammeMgmt.models.ts index db7e527c9..b0e28cce0 100644 --- a/intervention-workplan/effective-efficient-programme-mgmt/effectiveEfficientProgrammeMgmt.models.ts +++ b/intervention-workplan/effective-efficient-programme-mgmt/effectiveEfficientProgrammeMgmt.models.ts @@ -15,12 +15,15 @@ export class ProgrammeManagement extends ModelsBase { } act1_unicef = '0'; act1_partner = '0'; + act1_unfunded = '0'; act1_total = '0'; act2_unicef = '0'; act2_partner = '0'; + act2_unfunded = '0'; act2_total = '0'; act3_unicef = '0'; act3_partner = '0'; + act3_unfunded = '0'; act3_total = '0'; total = '0'; currency = ''; diff --git a/intervention-workplan/hq-contribution/hq-contribution.ts b/intervention-workplan/hq-contribution/hq-contribution.ts index f52c4a139..ce2532c99 100644 --- a/intervention-workplan/hq-contribution/hq-contribution.ts +++ b/intervention-workplan/hq-contribution/hq-contribution.ts @@ -65,6 +65,9 @@ export class HqContributionElement extends CommentsMixin(ComponentBaseMixin(LitE color: darkred; padding-bottom: 5px; } + etools-currency-amount-input[required] { + --paper-input-container-label-floating_-_max-width: 133%; + } + +
+
+
@@ -166,6 +187,15 @@ export class HqContributionElement extends CommentsMixin(ComponentBaseMixin(LitE this.requestUpdate(); } + unfundedCashChanged(detail: any) { + if (areEqual(this.data.planned_budget.unfunded_hq_cash, detail.value)) { + return; + } + + this.data.planned_budget.unfunded_hq_cash = detail.value; + this.requestUpdate(); + } + updateSlider(e: CustomEvent) { if (!e.detail) { return; @@ -235,7 +265,8 @@ export class HqContributionElement extends CommentsMixin(ComponentBaseMixin(LitE } data.planned_budget = { id: data.planned_budget.id, - total_hq_cash_local: data.planned_budget.total_hq_cash_local + total_hq_cash_local: data.planned_budget.total_hq_cash_local, + unfunded_hq_cash: data.planned_budget.unfunded_hq_cash }; return data; } diff --git a/intervention-workplan/hq-contribution/hqContribution.models.ts b/intervention-workplan/hq-contribution/hqContribution.models.ts index c9881dd3f..2611805be 100644 --- a/intervention-workplan/hq-contribution/hqContribution.models.ts +++ b/intervention-workplan/hq-contribution/hqContribution.models.ts @@ -17,4 +17,5 @@ export class HqContributionPermissions extends ModelsBase { } hq_support_cost = true; planned_budget = true; + has_unfunded_cash = true; } diff --git a/intervention-workplan/results-structure/modals/activity-dialog/activity-data-dialog.ts b/intervention-workplan/results-structure/modals/activity-dialog/activity-data-dialog.ts index df09a5e90..b344e553b 100644 --- a/intervention-workplan/results-structure/modals/activity-dialog/activity-data-dialog.ts +++ b/intervention-workplan/results-structure/modals/activity-dialog/activity-data-dialog.ts @@ -43,11 +43,13 @@ export class ActivityDataDialog extends DataMixin()(LitEle @query('etools-dialog') private dialogElement!: EtoolsDialog; @query('activity-items-table') private activityItemsTable!: ActivityItemsTable; quarters: ActivityTimeFrames[] = []; + @property() hasUnfundedCash = false; - set dialogData({activityId, pdOutputId, interventionId, quarters, readonly, currency}: any) { + set dialogData({activityId, pdOutputId, interventionId, quarters, readonly, currency, hasUnfundedCash}: any) { this.quarters = quarters; this.readonly = readonly; this.currency = currency; + this.hasUnfundedCash = hasUnfundedCash; if (!activityId) { this.data = {} as InterventionActivity; this.isEditDialog = false; @@ -185,11 +187,14 @@ export class ActivityDataDialog extends DataMixin()(LitEle ${!this.useInputLevel ? html` (LitEle ?readonly="${this.readonly}" .value="${this.editedData.unicef_cash}" @value-changed="${({detail}: CustomEvent) => this.updateModelValue('unicef_cash', detail.value)}" + required + auto-validate + > + + ` : html` @@ -215,6 +234,14 @@ export class ActivityDataDialog extends DataMixin()(LitEle label=${translate('UNICEF_CASH_BUDGET')} .value="${this.getSumValue('unicef_cash')}" > + `}
@@ -242,6 +269,7 @@ export class ActivityDataDialog extends DataMixin()(LitEle .activityItems="${this.editedData.items || []}" .readonly="${this.readonly}" .currency="${this.currency}" + .hasUnfundedCash="${this.hasUnfundedCash}" @activity-items-changed="${({detail}: CustomEvent) => { this.editedData.items = detail; this.requestUpdate(); @@ -266,7 +294,7 @@ export class ActivityDataDialog extends DataMixin()(LitEle fireEvent(this, 'dialog-closed', {confirmed: false}); } - getSumValue(field: 'cso_cash' | 'unicef_cash'): string { + getSumValue(field: 'cso_cash' | 'unicef_cash' | 'unfunded_cash'): string { const columnTotal = (this.editedData.items || []).reduce( (sum: number, item: Partial) => sum + Number(item[field]), 0 @@ -277,11 +305,16 @@ export class ActivityDataDialog extends DataMixin()(LitEle getTotalValue(): string { if (!this.useInputLevel) { - return getTotalCashFormatted(this.editedData.cso_cash || 0, this.editedData.unicef_cash || 0); + return getTotalCashFormatted( + this.editedData.cso_cash || 0, + this.editedData.unicef_cash || 0, + this.editedData.unfunded_cash || 0 + ); } else { const cso: string = this.getSumValue('cso_cash').replace(/,/g, ''); const unicef: string = this.getSumValue('unicef_cash').replace(/,/g, ''); - return getTotalCashFormatted(cso, unicef); + const unfunded: string = this.hasUnfundedCash ? this.getSumValue('unfunded_cash').replace(/,/g, '') : '0'; + return getTotalCashFormatted(cso, unicef, unfunded); } } @@ -305,6 +338,12 @@ export class ActivityDataDialog extends DataMixin()(LitEle }, 0); } + getInvalidTotalMessage() { + return this.hasUnfundedCash + ? getTranslation('INVALID_TOTAL_UNFUNDED_ACTIVITY_ITEMS') + : getTranslation('INVALID_TOTAL_ACTIVITY_ITEMS'); + } + validate() { return validateRequiredFields(this); } @@ -323,7 +362,7 @@ export class ActivityDataDialog extends DataMixin()(LitEle fireEvent(this, 'toast', { text: activityItemsValidationSummary.invalidRequired ? getTranslation('FILL_ALL_ACTIVITY_ITEMS') - : getTranslation('INVALID_TOTAL_ACTIVITY_ITEMS') + : this.getInvalidTotalMessage() }); return; } diff --git a/intervention-workplan/results-structure/pd-activities.ts b/intervention-workplan/results-structure/pd-activities.ts index 94aff7ba2..35e8044e9 100644 --- a/intervention-workplan/results-structure/pd-activities.ts +++ b/intervention-workplan/results-structure/pd-activities.ts @@ -45,6 +45,9 @@ export class PdActivities extends CommentsMixin(TruncateMixin(LitElement)) { @property({type: String}) interventionStatus!: string; + @property({type: Boolean}) + hasUnfundedCash!: boolean; + @property({type: Boolean}) showInactive!: boolean; interventionId!: number; @@ -76,6 +79,9 @@ export class PdActivities extends CommentsMixin(TruncateMixin(LitElement)) {
${translate('TIME_PERIODS')}
${translate('PARTNER_CASH')}
${translate('UNICEF_CASH')}
+ ${this.hasUnfundedCash + ? html`
${translate('UNFUNDED_CASH')}
` + : ``}
${translate('GENERAL.TOTAL')} (${this.currency})
@@ -135,11 +141,22 @@ export class PdActivities extends CommentsMixin(TruncateMixin(LitElement)) { ${displayCurrencyAmount(String(activity.unicef_cash || 0), '0', 2)} + + ${this.hasUnfundedCash + ? html`
+ ${displayCurrencyAmount(String(activity.unfunded_cash || 0), '0', 2)} +
` + : ``} +
- ${displayCurrencyAmount(String(this.getTotal(activity.cso_cash, activity.unicef_cash)), '0', 2)} + ${displayCurrencyAmount( + String(this.getTotal(activity.cso_cash, activity.unicef_cash, activity.unfunded_cash)), + '0', + 2 + )}
@@ -241,8 +258,8 @@ export class PdActivities extends CommentsMixin(TruncateMixin(LitElement)) { return [{element, relatedTo, relatedToDescription}]; } - getTotal(partner: string, unicef: string): number { - return (Number(partner) || 0) + (Number(unicef) || 0); + getTotal(partner: string, unicef: string, unfunded: string): number { + return (Number(partner) || 0) + (Number(unicef) || 0) + (this.hasUnfundedCash ? Number(unfunded) || 0 : 0); } openAllRows(): void { @@ -259,7 +276,8 @@ export class PdActivities extends CommentsMixin(TruncateMixin(LitElement)) { pdOutputId: this.pdOutputId, quarters: this.quarters, readonly: readonly, - currency: this.currency + currency: this.currency, + hasUnfundedCash: this.hasUnfundedCash } }); } diff --git a/intervention-workplan/results-structure/results-structure.ts b/intervention-workplan/results-structure/results-structure.ts index 3b6e41b27..226ec7430 100644 --- a/intervention-workplan/results-structure/results-structure.ts +++ b/intervention-workplan/results-structure/results-structure.ts @@ -266,6 +266,7 @@ export class ResultsStructure extends CommentsMixin(ContentPanelMixin(LitElement .readonly="${!this.permissions.edit.result_links || this.commentMode}" .currency="${this.intervention.planned_budget.currency}" .inAmendment="${this.intervention.in_amendment}" + .hasUnfundedCash="${this.intervention.planned_budget.has_unfunded_cash}" >
${translate('ADD_PD_OUTPUT')}
${translate('ID')} ${translate('COUNTRY_PROGRAME_OUTPUT')} ${translate('TOTAL')}
${result.cp_output_name || translate('UNASSOCIATED_TO_CP_OUTPUT')} ${this.intervention.planned_budget.currency} ${displayCurrencyAmount(result.total, '0.00')} @@ -242,7 +246,7 @@ export class EditorTable extends CommentsMixin(
${translate('PD_OUTPUT')} ${translate('TOTAL')}
>(baseClass: T) ${translate('ACTIVITY')} ${translate('TIME_PERIODS')}${translate('PARTNER_CASH')}${translate('UNICEF_CASH')}${translate('GENERAL.TOTAL')}
>(baseClass: T) ?readonly="${this.isReadonlyCash(activity.inEditMode, activity.items)}" @keydown="${(e: any) => this.handleEsc(e)}" @value-changed="${({detail}: CustomEvent) => this.numberChanged(detail, 'unicef_cash', activity)}" + required + .invalid="${activity.invalid?.unicef_cash}" + error-message="${translate('THIS_FIELD_IS_REQUIRED')}" > + + >(baseClass: T) >
${this.intervention.planned_budget.currency} - ${getTotalCashFormatted(activity.cso_cash, activity.unicef_cash)} + + ${getTotalCashFormatted(activity.cso_cash, activity.unicef_cash, activity.unfunded_cash)} +
>(baseClass: T)
${translate('PRICE_UNIT')} ${translate('PARTNER_CASH')} ${translate('UNICEF_CASH')}${translate('UNFUNDED_CASH')}${translate('TOTAL')} (${this.intervention.planned_budget.currency})
+ + >(baseClass: if (!activity.items) { activity.items = []; } - activity.items?.push({name: '', cso_cash: '0', unicef_cash: '0', unit_price: '0', inEditMode: true} as any); + activity.items?.push({ + name: '', + cso_cash: '0', + unicef_cash: '0', + unit_price: '0', + unfunded_cash: '0', + inEditMode: true + } as any); activity.inEditMode = true; activity.itemsInEditMode = true; this.oneEntityInEditMode = true; diff --git a/intervention-workplan-editor/editor-utils/programme-management-item-mixin.ts b/intervention-workplan-editor/editor-utils/programme-management-item-mixin.ts index ea85241f8..4fc566568 100644 --- a/intervention-workplan-editor/editor-utils/programme-management-item-mixin.ts +++ b/intervention-workplan-editor/editor-utils/programme-management-item-mixin.ts @@ -201,7 +201,7 @@ export function ProgrammeManagementItemMixin>( .value="${item.cso_cash}" @keydown="${(e: any) => this.handleEsc(e)}" @value-changed="${({detail}: CustomEvent) => { - this.cashFieldChanged(detail, 'cso_cash', item); + this.cashFieldChanged(detail, 'cso_cash', item, !this.hasUnfundedCash); this.updateActivityCashFromItem(programmeManagement, item); }}" > @@ -221,11 +221,34 @@ export function ProgrammeManagementItemMixin>( .value="${item.unicef_cash}" @keydown="${(e: any) => this.handleEsc(e)}" @value-changed="${({detail}: CustomEvent) => { - this.cashFieldChanged(detail, 'unicef_cash', item); + this.cashFieldChanged(detail, 'unicef_cash', item, !this.hasUnfundedCash); this.updateActivityCashFromItem(programmeManagement, item); }}" > + + >(
>(base
${translate('EFFECTIVE_EFFICIENT_PROG_MGM')}${translate('EFFECTIVE_EFFICIENT_PROG_MGM')}
${translate('ACTIVITY')} ${translate('PARTNER_CASH')} ${translate('UNICEF_CASH')}${translate('UNFUNDED_CASH')}${translate('GENERAL.TOTAL')}
+ + >(base >
${this.intervention.planned_budget.currency} - ${getTotalCashFormatted(item.cso_cash, item.unicef_cash)} + ${getTotalCashFormatted(item.cso_cash, item.unicef_cash, item.unfunded_cash)}
>(base
${translate('PRICE_UNIT')} ${translate('PARTNER_CASH')} ${translate('UNICEF_CASH')}${translate('UNFUNDED_CASH')}${translate('TOTAL')} (${this.intervention.planned_budget.currency})