Commit c5a120d0 authored by thomas craipeau's avatar thomas craipeau
Browse files

update

parent 16a084ae
......@@ -270,6 +270,7 @@
"Actions still to be done and without a contributor that have more than": "Actions still to be done and without a contributor that have more than",
"number_month": "__count__ month",
"number_month_plural": "__count__ months",
"No member organization of this organization has the role of project manager": "<i class=\"icon fa fa-warning\"></i> No member organization of this organization has the role of project manager",
"Image Library": "Image Library",
"Take photo": "Take photo",
"Retake": "Retake",
......@@ -1307,7 +1308,28 @@
},
"financeurId": {
"label": "Financing",
"placeholder": "Financing"
"placeholder": "Choose One...",
"options": {
"select": "Choose One..."
}
},
"workType": {
"label": "Type of work performed",
"placeholder": "Type of work performed"
},
"workerId": {
"label": "Project manager",
"placeholder": "Choose One...",
"options": {
"select": "Choose One..."
}
},
"beneficiaryId": {
"label": "Beneficiary",
"placeholder": "Choose One...",
"options": {
"select": "Choose One..."
}
}
},
"organizationsocecorest": {
......
......@@ -271,6 +271,7 @@
"Actions still to be done and without a contributor that have more than": "Actions <strong>toujours à faire</strong> et <strong>sans contributeur</strong> qui ont plus de",
"number_month": "__count__ mois",
"number_month_plural": "__count__ mois",
"No member organization of this organization has the role of project manager": "<i class=\"icon fa fa-warning\"></i> Aucune organisation membre de cette organisation n'a le role de maitre d'oeuvre",
"Take photo": "Prendre une photo",
"Image Library": "Bibliothèque d'images",
"Retake": "Reprendre",
......@@ -1493,7 +1494,28 @@
},
"financeurId": {
"label": "Financeur",
"placeholder": "Financeur"
"placeholder": "Sélectionnez un...",
"options": {
"select": "Sélectionnez un..."
}
},
"workType": {
"label": "Type de travail effectué",
"placeholder": "Type de travail effectué"
},
"workerId": {
"label": "Maître d'oeuvre",
"placeholder": "Sélectionnez un...",
"options": {
"select": "Sélectionnez un..."
}
},
"beneficiaryId": {
"label": "Bénéficiaire",
"placeholder": "Sélectionnez un...",
"options": {
"select": "Sélectionnez un..."
}
}
},
"projectsrest": {
......
......@@ -163,13 +163,12 @@ Answers.helpers({
return moment(this.project.startDate, 'D/M/YYYY').format('L');
}
},
depenseArray() {
depenseArray(depenseIndex = null) {
if (this.answers.aapStep1.depense) {
const depenseKeys = Object.keys(this.answers.aapStep1.depense);
const depense = Object.values(this.answers.aapStep1.depense);
let count = 0;
const arrayDepense = depense.map((d) => {
d.key = count;
count += 1;
const arrayDepense = depense.filter((d, depenseKey) => depenseIndex === null || parseInt(depenseIndex) === parseInt(depenseKey)).map((d, depenseKey) => {
d.key = parseInt(depenseKeys[depenseKey]);
if (d.price) {
d.price = parseFloat(d.price);
}
......@@ -180,9 +179,10 @@ Answers.helpers({
d.nameArray = [];
// financer
if (d.financer) {
const financerKeys = Object.keys(d.financer);
d.financer = Object.values(d.financer);
d.financer = d.financer.map((f, financeKey) => {
f.financeKey = financeKey;
f.financeKey = parseInt(financerKeys[financeKey]);
if (f.amount) {
f.amount = parseFloat(f.amount);
d.totalAmount += f.amount;
......@@ -201,6 +201,18 @@ Answers.helpers({
}
return f;
});
if (d.totalAmount === d.price) {
d.isCompleteFinancer = true;
d.totalRemaining = 0;
} else if (d.totalAmount && d.price && d.totalAmount < d.price) {
d.totalRemaining = d.price - d.totalAmount;
d.isCompleteFinancer = false;
} else {
d.totalRemaining = d.price;
d.isCompleteFinancer = false;
}
d.isFinancer = true;
} else {
d.isFinancer = false;
......@@ -249,9 +261,12 @@ Answers.helpers({
d.worker.date = moment(d.worker.date, 'D/M/YYYY').format('L');
}
// payement
d.totalAmountPayement = 0;
if (d.payement) {
const payementKeys = Object.keys(d.financer);
d.payement = Object.values(d.payement);
d.payement = d.payement.map((f) => {
d.payement = d.payement.map((f, payementKey) => {
f.payementKey = parseInt(payementKeys[payementKey]);
if (f.amount) {
f.amount = parseFloat(f.amount);
d.totalAmountPayement += f.amount;
......@@ -267,13 +282,33 @@ Answers.helpers({
}
return f;
});
if (d.totalAmountPayement === d.price) {
d.isCompletePayement = true;
d.totalRemainingPayement = 0;
} else if (d.totalAmountPayement && d.price && d.totalAmountPayement < d.price) {
d.totalRemainingPayement = d.price - d.totalAmountPayement;
d.isCompletePayement = false;
} else {
d.totalRemainingPayement = d.price;
d.isCompletePayement = false;
}
d.isPayement = true;
} else {
d.isPayement = false;
}
if (d.price && d.totalAmountPayement) {
const pourcentage = (100 * d.totalAmountPayement) / d.price;
if (Number.isInteger(pourcentage)) {
d.pourcentageAmountPayement = pourcentage;
} else {
d.pourcentageAmountPayement = parseFloat(pourcentage).toFixed(2);
}
}
return d;
});
console.log(arrayDepense);
// console.log(arrayDepense);
return arrayDepense;
}
},
......@@ -283,6 +318,7 @@ Answers.helpers({
const total = {};
total.totalPrice = 0;
total.totalAmount = 0;
total.totalAmountPayement = 0;
depense.forEach((d) => {
if (d.price) {
total.totalPrice += parseFloat(d.price);
......@@ -297,6 +333,15 @@ Answers.helpers({
}
});
}
if (d.payement) {
d.payement = Object.values(d.payement);
d.payement.forEach((f) => {
if (f.amount) {
f.amount = parseFloat(f.amount);
total.totalAmountPayement += f.amount;
}
});
}
});
// console.log(total);
return total;
......
......@@ -1139,12 +1139,11 @@ Organizations.helpers({
}
}
},
roleFinanceurOrga() {
if (this.links && this.links.members) {
listRoleType(role, type = 'organizations') {
if (role && this.links && this.links.members) {
const arrayParentKeys = Object.keys(this.links.members);
const arrayRolesFinanceurs = arrayParentKeys.filter((key) => this.links.members && this.links.members[key] && this.links.members[key].roles && this.links.members[key].type && this.links.members[key].type === 'organizations' && Array.isArray(this.links.members[key].roles) && this.links.members[key].roles.includes('Financeur'));
const arrayRolesFinanceurs = arrayParentKeys.filter((key) => this.links.members && this.links.members[key] && this.links.members[key].roles && this.links.members[key].type && this.links.members[key].type === type && Array.isArray(this.links.members[key].roles) && this.links.members[key].roles.includes(role));
const arrayMongoId = arrayRolesFinanceurs.map((key) => new Mongo.ObjectID(key));
console.log(Organizations.find({ _id: { $in: arrayMongoId } }, { fields: { _id: 1, name: 1 } }).count())
return Organizations.find({ _id: { $in: arrayMongoId } }, { fields: { _id: 1, name: 1 } });
}
},
......
......@@ -1154,3 +1154,37 @@ export const matchTags = (doc, tags) => {
}
return doc;
};
export const removeObjectArray = (array, key, value) => {
const index = array.findIndex((obj) => obj[key] === value);
return index >= 0 ? [
...array.slice(0, index),
...array.slice(index + 1),
] : array;
};
export const isValidObjectId = (id) => {
const isValid = (id) => {
const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
if (id == null) return false;
if (typeof id === 'number') {
return true;
}
if (typeof id === 'string') {
return id.length === 12 || (id.length === 24 && checkForHexRegExp.test(id));
}
// Duck-Typing detection of ObjectId like objects
if (id.toHexString) {
return id.id.length === 12 || (id.id.length === 24 && checkForHexRegExp.test(id.id));
}
return false;
};
if (isValid(id)) {
if ((String)(new Mongo.ObjectID(id).toHexString()) === id) {
return true;
}
return false;
}
return false;
};
\ No newline at end of file
......@@ -244,3 +244,84 @@ export const SchemasAnswersDepenseFinanceRest = new SimpleSchema({
removeNullsFromArrays: true,
},
});
export const SchemasAnswersDepenseWorkerRest = new SimpleSchema({
workType: {
type: String,
},
workerId: {
type: String,
autoform: {
type: 'select',
},
},
keyDepense: {
type: String,
},
answerId: {
type: String,
},
parentId: {
type: String,
},
parentType: {
type: String,
allowedValues: ['forms'],
},
}, {
tracker: Tracker,
clean: {
filter: true,
autoConvert: true,
removeEmptyStrings: true,
trimStrings: true,
getAutoValues: true,
removeNullsFromArrays: true,
},
});
export const SchemasAnswersDepensePayementRest = new SimpleSchema({
financeurId: {
type: String,
autoform: {
type: 'select',
},
optional: true,
},
beneficiaryId: {
type: String,
autoform: {
type: 'select',
},
},
amount: {
type: Number,
},
keyDepense: {
type: String,
},
keyPayement: {
type: String,
optional: true,
},
answerId: {
type: String,
},
parentId: {
type: String,
},
parentType: {
type: String,
allowedValues: ['forms'],
},
}, {
tracker: Tracker,
clean: {
filter: true,
autoConvert: true,
removeEmptyStrings: true,
trimStrings: true,
getAutoValues: true,
removeNullsFromArrays: true,
},
});
This diff is collapsed.
......@@ -2217,7 +2217,12 @@ Meteor.publishComposite('detailAnswers', function (orgaCibleId, scope, scopeId,
children: [
{
find(orga) {
return orga.roleFinanceurOrga();
return orga.listRoleType('Financeur');
},
},
{
find(orga) {
return orga.listRoleType('maitreOuvrage');
},
},
],
......
......@@ -38,7 +38,7 @@ import { SchemasProposalsRest, BlockProposalsRest } from '../../api/schema/propo
import { SchemasActionsRest } from '../../api/schema/actions.js';
import { SchemasLogUserActionsRest, SchemasValidateUserActionsRest, SchemasTibilletRest } from '../../api/schema/loguseractions.js';
import { SchemasMessagesRest } from '../../api/schema/logemailsend.js';
import { SchemasAnswersRest, SchemasAnswersDepenseRest, SchemasAnswersDepenseEstimateRest, SchemasAnswersDepenseFinanceRest } from '../../api/schema/answers.js';
import { SchemasAnswersRest, SchemasAnswersDepenseRest, SchemasAnswersDepenseEstimateRest, SchemasAnswersDepenseFinanceRest, SchemasAnswersDepenseWorkerRest, SchemasAnswersDepensePayementRest } from '../../api/schema/answers.js';
import { SchemasShareRest, SchemasRolesRest } from '../../api/schema/schema.js';
......@@ -311,6 +311,8 @@ Meteor.startup(function () {
SchemasAnswersDepenseRest.i18n('schemas.answersdepenserest');
SchemasAnswersDepenseEstimateRest.i18n('schemas.answersdepenserest');
SchemasAnswersDepenseFinanceRest.i18n('schemas.answersdepenserest');
SchemasAnswersDepenseWorkerRest.i18n('schemas.answersdepenserest');
SchemasAnswersDepensePayementRest.i18n('schemas.answersdepenserest');
BlockCitoyensRest.info.i18n('schemas.global');
BlockCitoyensRest.network.i18n('schemas.global');
BlockCitoyensRest.descriptions.i18n('schemas.global');
......@@ -615,4 +617,6 @@ Meteor.startup(function () {
Template.registerHelper('SchemasAnswersDepenseRest', SchemasAnswersDepenseRest);
Template.registerHelper('SchemasAnswersDepenseEstimateRest', SchemasAnswersDepenseEstimateRest);
Template.registerHelper('SchemasAnswersDepenseFinanceRest', SchemasAnswersDepenseFinanceRest);
Template.registerHelper('SchemasAnswersDepenseWorkerRest', SchemasAnswersDepenseWorkerRest);
Template.registerHelper('SchemasAnswersDepensePayementRest', SchemasAnswersDepensePayementRest);
});
......@@ -513,13 +513,31 @@ Router.map(function () {
this.route('answersDepenseFinanceAdd', {
template: 'answersDepenseFinanceAdd',
path: '/organizations/:orgaCibleId/:scope/forms/:_id/answersdepenseestimates/:answerId/finance/:depensekey/add',
path: '/organizations/:orgaCibleId/:scope/forms/:_id/answersdepensefinances/:answerId/finance/:depensekey/add',
loadingTemplate: 'loading',
});
this.route('answersDepenseFinanceEdit', {
template: 'answersDepenseFinanceEdit',
path: '/organizations/:orgaCibleId/:scope/forms/:_id/answersdepenseestimates/:answerId/finance/:depensekey/edit/:key',
path: '/organizations/:orgaCibleId/:scope/forms/:_id/answersdepensefinances/:answerId/finance/:depensekey/edit/:key',
loadingTemplate: 'loading',
});
this.route('answersDepenseWorkerAdd', {
template: 'answersDepenseWorkerAdd',
path: '/organizations/:orgaCibleId/:scope/forms/:_id/answersdepenseworker/:answerId/worker/:depensekey/add',
loadingTemplate: 'loading',
});
this.route('answersDepenseWorkerEdit', {
template: 'answersDepenseWorkerEdit',
path: '/organizations/:orgaCibleId/:scope/forms/:_id/answersdepenseworker/:answerId/worker/:depensekey/edit',
loadingTemplate: 'loading',
});
this.route('answersDepensePayementAdd', {
template: 'answersDepensePayementAdd',
path: '/organizations/:orgaCibleId/:scope/forms/:_id/answersdepensepayement/:answerId/payement/:depensekey/add',
loadingTemplate: 'loading',
});
......
......@@ -131,18 +131,35 @@
<i class="fa fa-euro"></i> {{__ "Funding"}}
</div>
{{#each depense in depenseArray}}
<div class="row row-alternate row responsive-sm">
<div class="col col-25 col-center">
<h4>{{depense.poste}}</h4>
<p><small>{{depense.date}}</small></p>
{{> buttonsAnswersDepense orgaCibleId=orgaCibleId _id=../_id._str scope=../scopeVar answerId=_id._str key=depense.key isCreator=isCreator isAdmin=../isAdmin estimatesKeys=depense.estimatesKeys}}
<div class="row row-alternate responsive-sm">
<div class=" col col-25 col-center ">
<div class="row">
{{> buttonsAnswersDepense orgaCibleId=orgaCibleId _id=../_id._str scope=../scopeVar answerId=_id._str key=depense.key isCreator=isCreator isAdmin=../isAdmin estimatesKeys=depense.estimatesKeys isFinancer=depense.isFinancer isCompleteFinancer=depense.isCompleteFinancer isCompletePayement=depense.isCompletePayement isProject=project isWorker=depense.worker}}
</div>
<div class="row">
<h4>{{depense.poste}}</h4>
</div>
<div class="row">
<p>
<small>{{depense.date}}</small>
</p>
</div>
{{#if depense.worker}}
<div class="row">
<p>
<small>{{__ "Project manager"}} : {{depense.worker.name}}</small>
</p>
</div>
{{/if}}
</div>
<div class="col col-center">
<div class="row">
<div class="col col col-center text-left">
<span class="badge-simple badge-positive"> {{depense.totalAmount}}€ ( €
<span
class="badge-simple {{#if depense.isCompletePayement}}badge-balanced{{else}}badge-positive{{/if}}">
{{depense.totalAmount}}€ {{__ "funded"}}) ( {{depense.totalAmountPayement}}
{{__ "spent"}}) </span>
</div>
<div class="col col-33 col-center text-right">
......@@ -155,7 +172,7 @@
<div class="row row-no-padding">
<div class="progress-bar progress-bar-stable">
<span class="progress-bar-fill progress-bar-fill-balanced"
style="width: {{depense.pourcentageAmount}}%;">{{__ "Funded unspent"}}
style="width: {{depense.pourcentageAmount}}%;">{{__ "Funded"}}
{{depense.pourcentageAmount}}%</span>
</div>
</div>
......@@ -221,7 +238,7 @@
{{#if depense.isFinancer}}
{{#each finance in depense.financer}}
<div class="row">
<div class="col col-33 col-center">
<div class="col col-25 col-center">
<div class="row row-no-padding">
<div class="col col-center">
{{finance.name}}
......@@ -233,7 +250,7 @@
</div>
</div>
</div>
<div class="col col-33 col-center">
<div class="col col-25 col-center">
{{finance.line}}
</div>
<div class="col col-center">
......@@ -249,6 +266,44 @@
{{/each}}
{{/if}}
{{#if depense.isPayement}}
<div class="row">
<div class="col col-center text-center">
<div class="row row-no-padding">
<div class="progress-bar progress-bar-stable">
<span class="progress-bar-fill progress-bar-fill-balanced"
style="width: {{depense.pourcentageAmountPayement}}%;">{{__ "Payment"}}
{{depense.pourcentageAmountPayement}}%</span>
</div>
</div>
<div class="row row-no-padding row-center text-center padding-top">
<div class="col col-center text-center">
<h5>{{__"Payment and follow-up"}}</h5>
</div>
</div>
</div>
</div>
{{#each payement in depense.payement}}
<div class="row">
<div class="col col-25 col-center">
{{payement.financeur.name}}
</div>
<div class="col col-25 col-center">
{{payement.beneficiary.name}}
</div>
<div class="col col-center">
{{payement.amount}} €
</div>
<div class="col col-center">
{{payement.pourcentageAmountPayement}}%
</div>
<div class="col col-10 col-center text-right">
{{> buttonsAnswersDepensePayement orgaCibleId=orgaCibleId _id=../_id._str scope=../scopeVar answerId=_id._str key=depense.key userId=payement.user payementKey=payement.payementKey isCreator=isCreator isAdmin=../isAdmin}}
</div>
</div>
{{/each}}
{{/if}}
</div>
</div>
......@@ -274,6 +329,16 @@
</div>
</div>
{{/if}}
{{#if totalFinance.totalAmountPayement}}
<div class="row">
<div class="col col-33 col-center">
<h4>{{__ "TOTAL PAID"}}</h4>
</div>
<div class="col col-center text-right">
<span class="badge-simple badge-balanced"> {{totalFinance.totalAmountPayement}} € </span>
</div>
</div>
{{/if}}
{{/if}}
</div>
......@@ -329,6 +394,16 @@
{{/if}}
</template>
<template name="buttonsAnswersDepensePayement">
{{#if isAdmin}}
<button class="button button-small button-icon actions-answer-depense-payement-js"><i
class="icon fa fa-cog"></i></button>
{{else if isCreator}}
<button class="button button-small button-icon actions-answer-depense-payement-js"><i
class="icon fa fa-cog"></i></button>
{{/if}}
</template>
<template name="statusAnswers">
</template>
......@@ -644,7 +719,7 @@
</div>
{{/if}}
{{#autoForm id="addFinanceDepenseAnswer" schema=SchemasAnswersDepenseFinanceRest type="method-update" meteormethod="insertDepenseAnswerFinance" doc=finance singleMethodArgument=true template="ionic"}}
{{> answersDepenseFinanceFields scope=finance}}
{{> answersDepenseFinanceFields scope=finance depenseArray=depenseArray}}
<div class="item">
<div class="button-bar">
<button type="submit" class="button button-dark">{{__ "create"}}</button>
......@@ -687,7 +762,7 @@
</div>
{{/if}}
{{#autoForm id="editFinanceDepenseAnswer" schema=SchemasAnswersDepenseFinanceRest type="method-update" meteormethod="updateDepenseAnswerFinance" doc=finance singleMethodArgument=true template="ionic"}}
{{> answersDepenseFinanceFields editFinanceDepenseAnswer=true}}
{{> answersDepenseFinanceFields scope=finance depenseArray=depenseArray editFinanceDepenseAnswer=true}}
<div class="item">
<div class="button-bar">
<button type="submit" class="button button-dark">{{__ "edit"}}</button>
......@@ -703,6 +778,19 @@
</template>
<template name="answersDepenseFinanceFields">
<div class="item item-text-wrap text-center">
<h3 class="positive">{{depenseArray.poste}}</h3>
<p>Besoin de financement :
{{depenseArray.totalAmount}}€/{{depenseArray.price}}€, <br>
{{#if depenseArray.isCompleteFinancer}}
Le financement été complet avant votre modification, vous pouvez le reduire mais vous ne pouvez pas l'augmenter
{{else}}
Vous pouvez mettre un montant de maximum <span class="positive">{{depenseArray.totalRemaining}}€</span>
{{/if}}
</p>
</div>
{{> afQuickField name='communaute'}}
{{#if afFieldValue name='communaute'}}
{{> afQuickField name='financeurId' options=optionsFinanceur}}
......@@ -711,7 +799,174 @@
{{> afQuickField name='email'}}
{{/if}}
{{> afQuickField name='line'}}
{{> afQuickField name='amount'}}
{{> afQuickField name='amount' min=1 max=depenseArray.totalRemaining}}
</template>
<template name="answersDepenseWorkerAdd">