Skip to content

Commit

Permalink
Merge pull request #4729 from coopcycle/co2-calculation
Browse files Browse the repository at this point in the history
Calculate CO2 consumption on TaskList update
  • Loading branch information
Atala authored Nov 19, 2024
2 parents 560d6cf + d061662 commit a0435a4
Show file tree
Hide file tree
Showing 22 changed files with 521 additions and 43 deletions.
31 changes: 31 additions & 0 deletions app/DoctrineMigrations/Version20241030144348.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace Application\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20241030144348 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE vehicle ADD co2_emissions INT NOT NULL DEFAULT 0');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE vehicle DROP co2_emissions');
}
}
32 changes: 32 additions & 0 deletions app/DoctrineMigrations/Version20241031130556.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Application\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20241031130556 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE task ADD co2_emissions INT NOT NULL DEFAULT 0');
$this->addSql('ALTER TABLE task ADD distance_from_previous INT NOT NULL DEFAULT 0');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE task DROP co2_emissions');
}
}
1 change: 1 addition & 0 deletions app/config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,7 @@ fos_js_routing:
- admin_task_receipt
- admin_users_search
- admin_user_edit
- admin_vehicles
- order_continue
- profile_jwt
- profile_notifications
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ describe('Failed checkout; restaurant is closed', () => {

cy.get('form[name="checkout_payment"]').submit()

cy.wait('@createStripePaymentIntent')
cy.wait('@createStripePaymentIntent', {timeout: 5000})

cy.get('#order-timeline')
.contains('Commande en attente de validation')
Expand Down
152 changes: 152 additions & 0 deletions features/fixtures/ORM/task_list.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
AppBundle\Entity\Base\GeoCoordinates:
geo_1:
__construct: [ "48.864577", "2.333338" ]
geo_2:
__construct: [ "48.846656", "2.369052" ]
geo_3:
__construct: [ "48.878658", "2.341055" ]
geo_4:
__construct: [ "48.8532461", "2.3681042" ]
geo_5:
__construct: [ "48.867598", "2.362811" ]

AppBundle\Entity\Address:
address_1:
addressLocality: 'Paris'
postalCode: '75010'
streetAddress: '272, rue Saint Honoré 75001 Paris 1er'
geo: "@geo_1"
address_2:
addressLocality: 'Paris'
postalCode: '75010'
streetAddress: '18, avenue Ledru-Rollin 75012 Paris 12ème'
geo: "@geo_2"
address_3:
addressLocality: 'Paris'
postalCode: '75010'
streetAddress: '17, rue Milton 75009 Paris 9ème'
geo: "@geo_3"
address_4:
addressLocality: 'Paris'
postalCode: '75010'
streetAddress: 'Place de la Bastille'
geo: "@geo_4"
address_5:
addressLocality: 'Paris'
postalCode: '75010'
streetAddress: 'Place de la République'
geo: "@geo_5"

AppBundle\Entity\Task:
task_1:
address: "@address_4"
doneAfter: <identity(new \DateTime('2018-03-02 10:30:00'))>
doneBefore: <identity(new \DateTime('2018-03-02 11:00:00'))>
comments: ""
task_2:
address: "@address_2"
doneAfter: <identity(new \DateTime('2018-03-02 11:30:00'))>
doneBefore: <identity(new \DateTime('2018-03-02 12:00:00'))>
comments: "#bob"
task_3:
address: "@address_5"
doneAfter: <identity(new \DateTime('2018-03-02 12:00:00'))>
doneBefore: <identity(new \DateTime('2018-03-02 12:30:00'))>
comments: "#bob"
status: "DONE"
task_4:
address: "@address_1"
doneAfter: <identity(new \DateTime('2018-03-03 12:00:00'))>
doneBefore: <identity(new \DateTime('2018-03-03 12:30:00'))>
comments: "addToProblem"
task_5:
address: "@address_2"
doneAfter: <identity(new \DateTime('2018-03-03 13:00:00'))>
doneBefore: <identity(new \DateTime('2018-03-03 13:30:00'))>
comments: "addToProblem"
previous: "@task_4"
task_6:
address: "@address_3"
doneAfter: <identity(new \DateTime('2018-03-02 12:00:00'))>
doneBefore: <identity(new \DateTime('2018-03-02 12:30:00'))>
comments: "addToProblem"
status: "CANCELLED"
task_7:
address: "@address_3"
doneAfter: <identity(new \DateTime('2018-02-02 12:00:00'))>
doneBefore: <identity(new \DateTime('2018-02-02 12:30:00'))>
comments: "addToProblem"
status: "DONE"

AppBundle\Entity\User:
bob:
__factory:
'@Nucleos\UserBundle\Util\UserManipulator::create':
- 'bob'
- '123456'
- '[email protected]'
- true
- false

AppBundle\Entity\Tour:
tour_1:
name: "Example tour"
date: <identity(new \DateTime('2018-03-02 12:00:00'))>
tasks:
- '@task_1'
- '@task_2'
- '@task_3'
tour_2:
name: "Example tour"
date: <identity(new \DateTime('2018-03-02 12:00:00'))>
tasks:
- '@task_4'

AppBundle\Entity\TaskList\Item:
item_1:
tour: "@tour_1"
position: 0
item_2:
tour: "@tour_2"
position: 1
item_3:
task: "@task_5"
position: 2
item_4:
task: "@task_6"
position: 3
item_5:
task: "@task_7"
position: 4


AppBundle\Entity\TaskList:
tasklist_1:
courier: "@bob"
date: <identity(new \DateTime('2018-03-02 12:00:00'))>
__calls:
- addItem:
- "@item_1"
- addItem:
- "@item_2"
- addItem:
- "@item_3"
- addItem:
- "@item_4"
- addItem:
- "@item_5"

AppBundle\Entity\Warehouse:
warehouse1:
name: 'Test warehouse'
address: "@address_3"

AppBundle\Entity\Vehicle:
vehicle1:
name: 'Test vehicle'
co2_emissions: 10
max_volume_units: 10
max_weight: 10
color: "#123123"
is_electric: false
warehouse: "@warehouse1"
20 changes: 20 additions & 0 deletions js/app/components/FleetManagement/VehicleForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default ({initialValues, onSubmit, warehouses, closeModal}) => {

initialValues = {
...initialValues,
co2emissions: initialValues.co2emissions || 0,
maxWeight: initialValues.maxWeight ? initialValues.maxWeight / 1000 : null,
warehouse: initialValues.warehouse ? initialValues.warehouse['@id'] : warehouses[0]['@id']
}
Expand Down Expand Up @@ -183,6 +184,25 @@ export default ({initialValues, onSubmit, warehouses, closeModal}) => {
}
</div>
</div>
<div className="row form-group">
<div className="col-md-4">
<div className={ `${errors.co2emissions ? 'has-error': ''}` }>
<label className="control-label" htmlFor="co2emissions">{ t('ADMIN_VEHICLE_EMISSIONS_LABEL') }</label>
<Field
className="form-control"
type="number"
value={ values.co2emissions }
name="co2emissions"
required
/>
{ errors.co2emissions && touched.co2emissions && (
<div className="has-error px-4">
<small className="help-block">{ errors.co2emissions }</small>
</div>
)}
</div>
</div>
</div>
<div className="row form-group">
<div className="col-md-12">
<div className={ `${errors.warehouse ? 'has-error': ''}` }>
Expand Down
37 changes: 20 additions & 17 deletions js/app/dashboard/components/context-menus/VehicleSelectMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { selectAllVehicles, selectVehicleIdToTaskListIdMap } from "../../../../s
import { Item, Menu, useContextMenu } from "react-contexify"
import { useTranslation } from "react-i18next"
import { setTaskListTrailer, setTaskListVehicle } from "../../redux/actions"
import { selectIsFleetManagementLoaded } from "../../redux/selectors"

const { hideAll } = useContextMenu({
id: 'vehicle-selectmenu',
Expand All @@ -15,29 +16,31 @@ export default () => {
const vehicles = useSelector(selectAllVehicles)
const vehicleIdToTaskListIdMap = useSelector(selectVehicleIdToTaskListIdMap)
const dispatch = useDispatch()
const isLoaded = useSelector(selectIsFleetManagementLoaded)

const onVehicleClick = ({ props, data }) => {
dispatch(setTaskListVehicle(props.username, data.vehicleId))
dispatch(setTaskListTrailer(props.username, null))
hideAll()
}

return (
<Menu id="vehicle-selectmenu">
{
vehicles.map((vehicle, index) => {
return (
<Item
onClick={onVehicleClick}
data={{vehicleId: vehicle['@id']}}
disabled={vehicleIdToTaskListIdMap.has(vehicle['@id'])}
key={index} >
{vehicle.name}
</Item>)
})
}
<Item key={-1} onClick={onVehicleClick} data={{vehicleId: null}}>{ t('CLEAR') }<i className="fa fa-close ml-1"></i></Item>
</Menu>
return (<>
<Menu id="vehicle-selectmenu">
{vehicles.map((vehicle, index) => {
return (
<Item
onClick={onVehicleClick}
data={{vehicleId: vehicle['@id']}}
disabled={vehicleIdToTaskListIdMap.has(vehicle['@id'])}
key={index} >
{vehicle.name}
</Item>)
})}
{ isLoaded && vehicles.length === 0 ?
<Item key={-1}><a className="text-reset" href={ window.Routing.generate("admin_vehicles")} target="_blank" rel="noreferrer" >{ t('ADMIN_DASHBOARD_PLEASE_ADD_VEHICLE') }</a></Item> :
<Item key={-1} onClick={onVehicleClick} data={{vehicleId: null}}>{ t('CLEAR') }<i className="fa fa-close ml-1"></i></Item>
}
</Menu>
</>
)

}
1 change: 1 addition & 0 deletions js/app/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
"ADMIN_VEHICLE_WAREHOUSE_LABEL": "Lager",
"ADMIN_VEHICLE_NO_WAREHOUSE": "Bitte erstellen Sie ein Lager, bevor Sie Fahrzeuge hinzufügen: Jedes Fahrzeug befindet sich in einem Lager!",
"ADMIN_VEHICLE_NO_VEHICLE": "Bitte erstellen Sie ein Fahrzeug, bevor Sie Anhänger hinzufügen: Jeder Anhänger ist mit bestimmten Fahrzeugen kompatibel!",
"ADMIN_VEHICLE_EMISSIONS_LABEL": "CO2-Emissionen (g/km)",
"DELIVERY_TIME_SLOTS": "Lieferzeitraum",
"OPENING_HOURS_RANGE_TIME_SLOT": "Vom {{fromDay}} bis {{toDay}}, zwischen {{open}} und {{close}}",
"OPENING_HOURS_SINGLE_TIME_SLOT": "Am {{day}} zwischen {{open}} und {{close}}",
Expand Down
2 changes: 2 additions & 0 deletions js/app/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@
"ADMIN_VEHICLE_NO_WAREHOUSE": "Please create a warehouse before adding vehicles: each vehicle sits in a warehouse!",
"ADMIN_VEHICLE_NO_VEHICLE": "Please create a vehicle before adding trailers: each trailer is compatible to given vehicles!",
"ADMIN_VEHICLE_TO_WAREHOUSE_PAGE": "To warehouses admin page",
"ADMIN_VEHICLE_EMISSIONS_LABEL": "CO2 emissions (g/km)",
"ADMIN_DASHBOARD_OPTIMIZATION_UNASSIGNED_TASKS": "{{ count }} item(s) were unassigned because it did not fit in the constraints.",
"ADMIN_DASHBOARD_OPTIMIZATION_DONE": "The assignements were optimized. Previous distance was {{ previousDistance }}, previous duration {{ previousDuration }}.",
"USER_EDIT_ENABLED_LABEL": "Enabled",
Expand Down Expand Up @@ -466,6 +467,7 @@
"PM_CASH": "Cash",
"PM_EDENRED": "Edenred",
"ADMIN_DASHBOARD_SETTINGS_TOURS_ENABLED": "Show tours panel",
"ADMIN_DASHBOARD_PLEASE_ADD_VEHICLE": "Please add a vehicle first",
"SEE_ALL": "See all",
"ORDER_DELAYED_NOTIFICATION": "Order {{orderNumber}} was delayed. New shipping time range: {{shippingTimeRange}}",
"DELETE_ALL": "Delete all",
Expand Down
1 change: 1 addition & 0 deletions js/app/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
"ADMIN_VEHICLE_WAREHOUSE_LABEL": "Almacén",
"ADMIN_VEHICLE_NO_WAREHOUSE": "Por favor, cree un almacén antes de agregar vehículos: ¡cada vehículo se encuentra en un almacén!",
"ADMIN_VEHICLE_NO_VEHICLE": "Por favor, cree un vehículo antes de agregar remolques: ¡cada remolque es compatible con vehículos específicos!",
"ADMIN_VEHICLE_EMISSIONS_LABEL": "Emisiones de CO2 (g/km)",
"USER_EDIT_ENABLED_LABEL": "Activado",
"USER_EDIT_DISABLED_LABEL": "Desactivado",
"ORDER_TIMELINE_CREATED_TITLE": "{{date}} Pedido creado",
Expand Down
1 change: 1 addition & 0 deletions js/app/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@
"ADMIN_VEHICLE_WAREHOUSE_LABEL": "Entrepôt",
"ADMIN_VEHICLE_NO_WAREHOUSE": "Veuillez créer un entrepôt avant d'ajouter des véhicules : chaque véhicule se trouve dans un entrepôt !",
"ADMIN_VEHICLE_NO_VEHICLE": "Veuillez créer un véhicule avant d'ajouter des remorques : chaque remorque est compatible avec des véhicules donnés !",
"ADMIN_VEHICLE_EMISSIONS_LABEL": "Émissions de CO2 (g/km)",
"ALLERGEN": {
"CEREALS_CONTAINING_GLUTEN": "Céréales contenant du gluten",
"CRUSTACEANS": "Crustacés",
Expand Down
1 change: 1 addition & 0 deletions js/app/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"ADMIN_DASHBOARD_INCLUDE_TASKS_FROM_ORDER": "Includi tutte le attività dall'ordini",
"ADMIN_DASHBOARD_TOOLTIP_TOTAL": "Totale",
"ADMIN_DASHBOARD_HIDE_SHOW_ON_MAP": "Nascondi/mostra sulla mappa",
"ADMIN_VEHICLE_EMISSIONS_LABEL": "Emissioni di CO2 (g/km)",
"ORDER_TIMELINE_CREATED_TITLE": "{{date}} Ordine creato",
"ORDER_TIMELINE_ACCEPTED_TITLE": "{{date}} Ordine confermato",
"ORDER_TIMELINE_PICKED_TITLE": "{{date}} Ordine ritirato",
Expand Down
Loading

0 comments on commit a0435a4

Please sign in to comment.