mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Feature: Provide api endpoint for reviewing addresses
Feature: show warning when address does not match the reference Feature: [address] do update the address from address reference when clicked inside address details
This commit is contained in:
parent
21e24c60c7
commit
8177a0fcce
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Chill\MainBundle\Controller;
|
|
||||||
|
|
||||||
use Chill\MainBundle\Entity\Address;
|
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
||||||
|
|
||||||
class AddressToReferenceMatcher
|
|
||||||
{
|
|
||||||
public function markAddressAsMatching(Address $address): JsonResponse
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
|
|
||||||
|
class AddressToReferenceMatcherController
|
||||||
|
{
|
||||||
|
private Security $security;
|
||||||
|
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
|
private SerializerInterface $serializer;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Security $security,
|
||||||
|
EntityManagerInterface $entityManager,
|
||||||
|
SerializerInterface $serializer
|
||||||
|
) {
|
||||||
|
$this->security = $security;
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
$this->serializer = $serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/api/1.0/main/address/reference-match/{id}/set/reviewed", methods={"POST"})
|
||||||
|
*/
|
||||||
|
public function markAddressAsReviewed(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (!$this->security->isGranted('ROLE_USER')) {
|
||||||
|
throw new AccessDeniedHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$address->setRefStatus(Address::ADDR_REFERENCE_STATUS_REVIEWED);
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/api/1.0/main/address/reference-match/{id}/sync-with-reference", methods={"POST"})
|
||||||
|
*/
|
||||||
|
public function syncAddressWithReference(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (null === $address->getAddressReference()) {
|
||||||
|
throw new BadRequestHttpException('this address does not have any address reference');
|
||||||
|
}
|
||||||
|
|
||||||
|
$address->syncWithReference($address->getAddressReference());
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -250,11 +250,20 @@ class Address implements TrackCreationInterface, TrackUpdateInterface
|
|||||||
public static function createFromAddressReference(AddressReference $original): Address
|
public static function createFromAddressReference(AddressReference $original): Address
|
||||||
{
|
{
|
||||||
return (new Address())
|
return (new Address())
|
||||||
->setPoint($original->getPoint())
|
->syncWithReference($original);
|
||||||
->setPostcode($original->getPostcode())
|
}
|
||||||
->setStreet($original->getStreet())
|
|
||||||
->setStreetNumber($original->getStreetNumber())
|
public function syncWithReference(AddressReference $addressReference): Address
|
||||||
->setAddressReference($original);
|
{
|
||||||
|
$this
|
||||||
|
->setPoint($addressReference->getPoint())
|
||||||
|
->setPostcode($addressReference->getPostcode())
|
||||||
|
->setStreet($addressReference->getStreet())
|
||||||
|
->setStreetNumber($addressReference->getStreetNumber())
|
||||||
|
->setRefStatus(self::ADDR_REFERENCE_STATUS_MATCH)
|
||||||
|
->setAddressReference($addressReference);
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAddressReference(): ?AddressReference
|
public function getAddressReference(): ?AddressReference
|
||||||
@ -514,8 +523,12 @@ class Address implements TrackCreationInterface, TrackUpdateInterface
|
|||||||
/**
|
/**
|
||||||
* Update the ref status
|
* Update the ref status
|
||||||
*
|
*
|
||||||
|
<<<<<<< HEAD
|
||||||
* @param Address::ADDR_REFERENCE_STATUS_* $refStatus
|
* @param Address::ADDR_REFERENCE_STATUS_* $refStatus
|
||||||
* @param bool|null $updateLastUpdate Also update the "refStatusLastUpdate"
|
* @param bool|null $updateLastUpdate Also update the "refStatusLastUpdate"
|
||||||
|
=======
|
||||||
|
* The refstatuslast update is also updated
|
||||||
|
>>>>>>> 31152616d (Feature: Provide api endpoint for reviewing addresses)
|
||||||
*/
|
*/
|
||||||
public function setRefStatus(string $refStatus, ?bool $updateLastUpdate = true): self
|
public function setRefStatus(string $refStatus, ?bool $updateLastUpdate = true): self
|
||||||
{
|
{
|
||||||
|
@ -21,3 +21,11 @@ export const getGeographicalUnitsByAddress = async (address: Address): Promise<S
|
|||||||
export const getAllGeographicalUnitLayers = async (): Promise<GeographicalUnitLayer[]> => {
|
export const getAllGeographicalUnitLayers = async (): Promise<GeographicalUnitLayer[]> => {
|
||||||
return fetchResults<GeographicalUnitLayer>(`/api/1.0/main/geographical-unit-layer.json`);
|
return fetchResults<GeographicalUnitLayer>(`/api/1.0/main/geographical-unit-layer.json`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const syncAddressWithReference = async (address: Address): Promise<Address> => {
|
||||||
|
return makeFetch<null, Address>("POST", `/api/1.0/main/address/reference-match/${address.address_id}/sync-with-reference`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const markAddressReviewed = async (address: Address): Promise<Address> => {
|
||||||
|
return makeFetch<null, Address>("POST", `/api/1.0/main/address/reference-match/${address.address_id}/set/reviewed`);
|
||||||
|
}
|
||||||
|
@ -67,9 +67,6 @@ export const makeFetch = <Input, Output>(method: 'POST'|'GET'|'PUT'|'PATCH'|'DEL
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('for url '+url, body);
|
|
||||||
console.log('for url '+url, body !== null);
|
|
||||||
|
|
||||||
if (body !== null && typeof body !== 'undefined') {
|
if (body !== null && typeof body !== 'undefined') {
|
||||||
Object.assign(opts, {body: JSON.stringify(body)})
|
Object.assign(opts, {body: JSON.stringify(body)})
|
||||||
}
|
}
|
||||||
@ -77,9 +74,6 @@ export const makeFetch = <Input, Output>(method: 'POST'|'GET'|'PUT'|'PATCH'|'DEL
|
|||||||
if (typeof options !== 'undefined') {
|
if (typeof options !== 'undefined') {
|
||||||
opts = Object.assign(opts, options);
|
opts = Object.assign(opts, options);
|
||||||
}
|
}
|
||||||
console.log('will fetch', url);
|
|
||||||
console.log('content for ' + url, opts);
|
|
||||||
|
|
||||||
return fetch(url, opts)
|
return fetch(url, opts)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
@ -2,12 +2,14 @@ import AddressDetailsButton from "../../vuejs/_components/AddressDetails/Address
|
|||||||
import {createApp} from "vue";
|
import {createApp} from "vue";
|
||||||
import {createI18n} from "vue-i18n";
|
import {createI18n} from "vue-i18n";
|
||||||
import {_createI18n} from "../../vuejs/_js/i18n";
|
import {_createI18n} from "../../vuejs/_js/i18n";
|
||||||
|
import {Address} from "../../types";
|
||||||
|
|
||||||
const i18n = _createI18n({});
|
const i18n = _createI18n({});
|
||||||
|
|
||||||
document.querySelectorAll<HTMLSpanElement>('span[data-address-details]').forEach((el) => {
|
document.querySelectorAll<HTMLSpanElement>('span[data-address-details]').forEach((el) => {
|
||||||
const dataset = el.dataset as {
|
const dataset = el.dataset as {
|
||||||
addressId: string
|
addressId: string,
|
||||||
|
addressRefStatus: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
@ -15,9 +17,17 @@ document.querySelectorAll<HTMLSpanElement>('span[data-address-details]').forEach
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
addressId: Number.parseInt(dataset.addressId),
|
addressId: Number.parseInt(dataset.addressId),
|
||||||
|
addressRefStatus: dataset.addressRefStatus,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: '<address-details-button :address_id="addressId"></address-details-button>'
|
template: '<address-details-button :address_id="addressId" :address_ref_status="addressRefStatus" @update-address="onUpdateAddress"></address-details-button>',
|
||||||
|
methods: {
|
||||||
|
onUpdateAddress: (address: Address): void => {
|
||||||
|
if (window.confirm("L'adresse a été modifiée. Vous pouvez continuer votre travail. Cependant, pour afficher les données immédiatement, veuillez recharger la page. \n\n Voulez-vous recharger la page immédiatement ?")) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(i18n);
|
app.use(i18n);
|
||||||
|
@ -1,36 +1,50 @@
|
|||||||
<template>
|
<template>
|
||||||
<a v-if="data.loading === false" @click.prevent="clickOrOpen"><span class="fa fa-map"></span></a>
|
<span v-if="data.working_ref_status === 'to_review'" class="badge bg-danger address-details-button-warning">L'adresse de référence a été modifiée</span>
|
||||||
|
<a v-if="data.loading === false" @click.prevent="clickOrOpen" class="btn btn-sm btn-misc">
|
||||||
|
<span class="fa fa-map address-details-button"></span>
|
||||||
|
</a>
|
||||||
<span v-if="data.loading" class="fa fa-spin fa-spinner "></span>
|
<span v-if="data.loading" class="fa fa-spin fa-spinner "></span>
|
||||||
<AddressModal :address="data.working_address" ref="address_modal"></AddressModal>
|
<AddressModal :address="data.working_address" @update-address="onUpdateAddress" ref="address_modal"></AddressModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {Address} from "../../../types";
|
import {Address, AddressRefStatus} from "../../../types";
|
||||||
import {reactive, ref} from "vue";
|
import {onMounted, reactive, ref} from "vue";
|
||||||
import {getAddressById} from "../../../lib/api/address";
|
import {getAddressById} from "../../../lib/api/address";
|
||||||
import AddressModal from "./AddressModal.vue";
|
import AddressModal from "./AddressModal.vue";
|
||||||
|
|
||||||
export interface AddressModalContentProps {
|
export interface AddressModalContentProps {
|
||||||
//address?: Address|null,
|
address_id: number;
|
||||||
address_id: number,
|
address_ref_status: AddressRefStatus | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = reactive<{
|
const data = reactive<{
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
working_address: Address | null,
|
working_address: Address | null,
|
||||||
|
working_ref_status: AddressRefStatus | null,
|
||||||
}>({
|
}>({
|
||||||
loading: false,
|
loading: false,
|
||||||
working_address: null,
|
working_address: null,
|
||||||
|
working_ref_status: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const props = defineProps<AddressModalContentProps>();
|
const props = defineProps<AddressModalContentProps>();
|
||||||
|
|
||||||
const address_modal = ref<InstanceType<typeof AddressModal> | null>(null)
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const address_modal = ref<InstanceType<typeof AddressModal> | null>(null);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
data.working_ref_status = props.address_ref_status;
|
||||||
|
});
|
||||||
|
|
||||||
async function clickOrOpen(): Promise<void> {
|
async function clickOrOpen(): Promise<void> {
|
||||||
if (data.working_address === null) {
|
if (data.working_address === null) {
|
||||||
data.loading = true;
|
data.loading = true;
|
||||||
data.working_address = await getAddressById(props.address_id);
|
data.working_address = await getAddressById(props.address_id);
|
||||||
|
data.working_ref_status = data.working_address.refStatus;
|
||||||
data.loading = false;
|
data.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,8 +52,18 @@ async function clickOrOpen(): Promise<void> {
|
|||||||
address_modal.value?.open();
|
address_modal.value?.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onUpdateAddress = (address: Address): void => {
|
||||||
|
console.log('from details button', address);
|
||||||
|
data.working_address = address;
|
||||||
|
data.working_ref_status = address.refStatus;
|
||||||
|
emit('update-address', address);
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
|
.address-details-button-warning {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 0.3rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<address-render-box :address="props.address"></address-render-box>
|
<address-render-box :address="props.address"></address-render-box>
|
||||||
|
<address-details-ref-matching :address="props.address" @update-address="onUpdateAddress"></address-details-ref-matching>
|
||||||
<address-details-map :address="props.address"></address-details-map>
|
<address-details-map :address="props.address"></address-details-map>
|
||||||
<address-details-geographical-layers :address="props.address"></address-details-geographical-layers>
|
<address-details-geographical-layers :address="props.address"></address-details-geographical-layers>
|
||||||
</template>
|
</template>
|
||||||
@ -9,6 +10,7 @@ import {Address} from "../../../types";
|
|||||||
import AddressDetailsMap from "./Parts/AddressDetailsMap.vue";
|
import AddressDetailsMap from "./Parts/AddressDetailsMap.vue";
|
||||||
import AddressRenderBox from "../Entity/AddressRenderBox.vue";
|
import AddressRenderBox from "../Entity/AddressRenderBox.vue";
|
||||||
import AddressDetailsGeographicalLayers from "./Parts/AddressDetailsGeographicalLayers.vue";
|
import AddressDetailsGeographicalLayers from "./Parts/AddressDetailsGeographicalLayers.vue";
|
||||||
|
import AddressDetailsRefMatching from "./Parts/AddressDetailsRefMatching.vue";
|
||||||
|
|
||||||
interface AddressModalContentProps {
|
interface AddressModalContentProps {
|
||||||
address: Address,
|
address: Address,
|
||||||
@ -16,6 +18,15 @@ interface AddressModalContentProps {
|
|||||||
|
|
||||||
const props = defineProps<AddressModalContentProps>();
|
const props = defineProps<AddressModalContentProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const onUpdateAddress = (address: Address): void => {
|
||||||
|
console.log('from details content', address);
|
||||||
|
emit('update-address', address);
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<h2>Détails d'une adresse</h2>
|
<h2>Détails d'une adresse</h2>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:body>
|
<template v-slot:body>
|
||||||
<address-details-content :address="props.address"></address-details-content>
|
<address-details-content :address="props.address" @update-address="onUpdateAddress"></address-details-content>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</modal>
|
||||||
</teleport>
|
</teleport>
|
||||||
@ -26,8 +26,12 @@ interface AddressModalState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<AddressModalProps>();
|
const props = defineProps<AddressModalProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
const state: AddressModalState = reactive({show_modal: false});
|
const state: AddressModalState = reactive({show_modal: false});
|
||||||
const dummy = ref(false);
|
|
||||||
|
|
||||||
const open = (): void => {
|
const open = (): void => {
|
||||||
state.show_modal = true;
|
state.show_modal = true;
|
||||||
@ -37,6 +41,11 @@ const close = (): void => {
|
|||||||
state.show_modal = false;
|
state.show_modal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onUpdateAddress = (address: Address): void => {
|
||||||
|
console.log('from details modal', address);
|
||||||
|
emit('update-address', address);
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
close,
|
close,
|
||||||
open,
|
open,
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
<template>
|
||||||
|
<template v-if="props.address.refStatus !== 'match'">
|
||||||
|
<div v-if="props.address.refStatus === 'to_review'" class="alert alert-danger">
|
||||||
|
<p><i class="fa fa-warning"></i> L'adresse de référence a été modifiée.</p>
|
||||||
|
|
||||||
|
<template v-if="props.address.addressReference.street !== props.address.street || props.address.addressReference.streetNumber !== props.address.streetNumber">
|
||||||
|
<template v-if="props.address.country.code === 'BE'">
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{ props.address.street }} {{props.address.streetNumber}}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.street }} {{ props.address.addressReference.streetNumber }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{props.address.streetNumber}} {{ props.address.street }}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.streetNumber }} {{ props.address.addressReference.street }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="props.address.addressReference.postcode.id !== props.address.postcode.id">
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{ props.address.postcode.code }} {{props.address.postcode.name }}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.postcode.code }} {{ props.address.addressReference.postcode.name }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="props.address.point !== null && (props.address.point.coordinates[0] !== props.address.addressReference.point.coordinates[0] || props.address.point.coordinates[1] !== props.address.addressReference.point.coordinates[1])">
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{ props.address.point.coordinates[0] }} {{ props.address.point.coordinates[1]}}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.point.coordinates[0] }} {{ props.address.addressReference.point.coordinates[1]}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li><button class="btn btn-sm btn-update" @click="applyUpdate">Appliquer les modifications</button></li>
|
||||||
|
<li><button class="btn btn-sm btn-primary" @click="keepCurrentAddress">Conserver</button></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import {Address} from "../../../../types";
|
||||||
|
import {markAddressReviewed, syncAddressWithReference} from "../../../../lib/api/address";
|
||||||
|
|
||||||
|
export interface AddressDetailsRefMatchingProps {
|
||||||
|
address: Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<AddressDetailsRefMatchingProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const applyUpdate = async () => {
|
||||||
|
const new_address = await syncAddressWithReference(props.address);
|
||||||
|
|
||||||
|
emit('update-address', new_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
const keepCurrentAddress = async () => {
|
||||||
|
const new_address = await markAddressReviewed(props.address);
|
||||||
|
|
||||||
|
emit("update-address", new_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.difference {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.old {
|
||||||
|
text-decoration: red line-through;
|
||||||
|
}
|
||||||
|
.new {
|
||||||
|
font-weight: bold;
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -69,7 +69,7 @@
|
|||||||
<i class="fa fa-li fa-map-marker"></i>
|
<i class="fa fa-li fa-map-marker"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.inline(address, options, streetLine, lines) }}
|
{{ _self.inline(address, options, streetLine, lines) }}
|
||||||
<span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" ></span>
|
<span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}" ></span>
|
||||||
</li>
|
</li>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@
|
|||||||
<i class="fa fa-fw fa-map-marker"></i>
|
<i class="fa fa-fw fa-map-marker"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.inline(address, options, streetLine, lines) }}
|
{{ _self.inline(address, options, streetLine, lines) }}
|
||||||
<span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" ></span>
|
<span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}"></span>
|
||||||
</span>
|
</span>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@
|
|||||||
<div class="noaddress">
|
<div class="noaddress">
|
||||||
{{ 'address.consider homeless'|trans }}
|
{{ 'address.consider homeless'|trans }}
|
||||||
</div>
|
</div>
|
||||||
<p><span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" ></span></p>
|
<p><span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}" ></span></p>
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="address{% if options['multiline'] %} multiline{% endif %}{% if options['with_delimiter'] %} delimiter{% endif %}">
|
<div class="address{% if options['multiline'] %} multiline{% endif %}{% if options['with_delimiter'] %} delimiter{% endif %}">
|
||||||
@ -112,7 +112,7 @@
|
|||||||
<i class="fa fa-fw fa-map-marker"></i>
|
<i class="fa fa-fw fa-map-marker"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.raw(lines) }}
|
{{ _self.raw(lines) }}
|
||||||
<p><span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" ></span></p>
|
<p><span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}"></span></p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.validity(address, options) }}
|
{{ _self.validity(address, options) }}
|
||||||
|
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Doctrine\Model\Point;
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Entity\AddressReference;
|
||||||
|
use Chill\MainBundle\Repository\AddressRepository;
|
||||||
|
use Chill\MainBundle\Test\PrepareClientTrait;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||||
|
|
||||||
|
class AddressToReferenceMatcherControllerTest extends WebTestCase
|
||||||
|
{
|
||||||
|
use PrepareClientTrait;
|
||||||
|
|
||||||
|
private AddressRepository $addressRepository;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$this->addressRepository = self::$container->get(AddressRepository::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider addressToReviewProvider
|
||||||
|
*/
|
||||||
|
public function testMarkAddressAsReviewed(int $addressId): void
|
||||||
|
{
|
||||||
|
$client = $this->getClientAuthenticated();
|
||||||
|
|
||||||
|
$client->request('POST', "/api/1.0/main/address/reference-match/${addressId}/set/reviewed");
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$address = $this->addressRepository->find($addressId);
|
||||||
|
|
||||||
|
$this->assertEquals(Address::ADDR_REFERENCE_STATUS_REVIEWED, $address->getRefStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider addressUnsyncedProvider
|
||||||
|
*/
|
||||||
|
public function testSyncAddressWithReference(int $addressId): void
|
||||||
|
{
|
||||||
|
$client = $this->getClientAuthenticated();
|
||||||
|
|
||||||
|
$client->request('POST', "/api/1.0/main/address/reference-match/${addressId}/sync-with-reference");
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$address = $this->addressRepository->find($addressId);
|
||||||
|
|
||||||
|
$this->assertEquals(Address::ADDR_REFERENCE_STATUS_MATCH, $address->getRefStatus());
|
||||||
|
$this->assertEquals($address->getAddressReference()->getStreet(), $address->getStreet());
|
||||||
|
$this->assertEquals($address->getAddressReference()->getStreetNumber(), $address->getStreetNumber());
|
||||||
|
$this->assertEquals($address->getAddressReference()->getPoint()->toWKT(), $address->getPoint()->toWKT());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function addressToReviewProvider(): iterable
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$nb = $em->createQuery('SELECT count(a) FROM '.Address::class.' a')
|
||||||
|
->getSingleScalarResult();
|
||||||
|
|
||||||
|
if (0 === $nb) {
|
||||||
|
throw new \RuntimeException("There aren't any address with a ref status 'matched'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Address $address */
|
||||||
|
$address = $em->createQuery('SELECT a FROM '.Address::class.' a')
|
||||||
|
->setFirstResult(rand(0, $nb))
|
||||||
|
->setMaxResults(1)
|
||||||
|
->getSingleResult();
|
||||||
|
|
||||||
|
$address->setRefStatus(Address::ADDR_REFERENCE_STATUS_TO_REVIEW);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
yield [$address->getId()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function addressUnsyncedProvider(): iterable
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$nb = $em->createQuery('SELECT count(a) FROM '.AddressReference::class.' a')
|
||||||
|
->getSingleScalarResult();
|
||||||
|
|
||||||
|
if (0 === $nb) {
|
||||||
|
throw new \RuntimeException("There isn't any address reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
$ref = $em->createQuery('SELECT a FROM '.AddressReference::class.' a')
|
||||||
|
->setMaxResults(1)
|
||||||
|
->setFirstResult(rand(0, $nb))
|
||||||
|
->getSingleResult();
|
||||||
|
|
||||||
|
$address = Address::createFromAddressReference($ref);
|
||||||
|
|
||||||
|
// make the address dirty
|
||||||
|
$address->setStreet('tagada')
|
||||||
|
->setStreetNumber('-250')
|
||||||
|
->setPoint(Point::fromLonLat(0, 0))
|
||||||
|
->setRefStatus(Address::ADDR_REFERENCE_STATUS_TO_REVIEW);
|
||||||
|
|
||||||
|
$em->persist($address);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
yield [$address->getId()];
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user