Fixes
This commit is contained in:
parent
47057ea7a3
commit
7e46c1fc5d
@ -64,10 +64,10 @@ server {
|
||||
try_files $uri @sfFront;
|
||||
}
|
||||
|
||||
location /w2p/ {
|
||||
proxy_pass http://tp:8080/w2p/;
|
||||
proxy_temp_path /tmp/proxy;
|
||||
}
|
||||
# location /w2p/ {
|
||||
# proxy_pass http://tp:8080/w2p/;
|
||||
# proxy_temp_path /tmp/proxy;
|
||||
# }
|
||||
|
||||
location @sfFront { # Symfony
|
||||
if ($request_method = 'OPTIONS') {
|
||||
|
||||
@ -474,7 +474,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
||||
* datetime?: array{
|
||||
* default_format?: scalar|null, // Default: "Y-m-d\\TH:i:sP"
|
||||
* default_deserialization_formats?: list<scalar|null>,
|
||||
* default_timezone?: scalar|null, // Default: "Europe/Berlin"
|
||||
* default_timezone?: scalar|null, // Default: "UTC"
|
||||
* cdata?: scalar|null, // Default: true
|
||||
* },
|
||||
* array_collection?: array{
|
||||
@ -574,7 +574,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
||||
* datetime?: array{
|
||||
* default_format?: scalar|null, // Default: "Y-m-d\\TH:i:sP"
|
||||
* default_deserialization_formats?: list<scalar|null>,
|
||||
* default_timezone?: scalar|null, // Default: "Europe/Berlin"
|
||||
* default_timezone?: scalar|null, // Default: "UTC"
|
||||
* cdata?: scalar|null, // Default: true
|
||||
* },
|
||||
* array_collection?: array{
|
||||
|
||||
@ -1,226 +1,188 @@
|
||||
{% extends 'backend_base.html.twig' %}
|
||||
{% extends 'backend_tailwind_base.html.twig' %}
|
||||
{% form_theme form 'tailwind_formtheme.html.twig' %}
|
||||
{% trans_default_domain 'core_voucher_edit' %}
|
||||
{% block body %}
|
||||
|
||||
<div class="header">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
|
||||
<h3>
|
||||
<i class="fa-fw fa fa-id-card"></i>
|
||||
{{'Voucher'|trans}} <span>>
|
||||
{{'create'|trans}} </span>
|
||||
</h3>
|
||||
{% block header %}
|
||||
<div class="flex flex-wrap items-center gap-4 justify-between w-full">
|
||||
<div>
|
||||
<h1 class="text-psc text-2xl font-medium flex flex-row gap-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-8">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 010 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 010-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375z" />
|
||||
</svg>
|
||||
{{'Voucher'|trans}} <span class="text-gray-500">{{'create'|trans}}</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-4 justify-end shrink-0 ml-auto">
|
||||
<a href="{{ path('psc_shop_voucher_backend_list') }}" class="inline-flex items-center justify-center py-1 gap-1 font-medium rounded-md px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" />
|
||||
</svg>
|
||||
{{'back'|trans}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="w-full flex flex-col gap-6">
|
||||
{{ form_start(form, {attr: {class: ''}}) }}
|
||||
|
||||
<div class="tab-group flex-none md:flex w-full" data-dui-orientation="vertical">
|
||||
{# Vertical Tab Navigation #}
|
||||
<div role="tablist" class="relative mr-5 rounded-md flex flex-col p-1 w-full md:w-2/12">
|
||||
<div class="tab-indicator absolute left-0 w-1 bg-psc-500 transition-transform duration-300"></div>
|
||||
|
||||
<a href="#" class="tab-link flex items-center text-sm active px-4 py-2 relative" data-dui-tab-target="general">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||
</svg>
|
||||
{{'General'|trans}}
|
||||
</a>
|
||||
|
||||
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="validity">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
|
||||
</svg>
|
||||
Gültigkeit
|
||||
</a>
|
||||
|
||||
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="filter">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 0 1-.659 1.591l-5.432 5.432a2.25 2.25 0 0 0-.659 1.591v2.927a2.25 2.25 0 0 1-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 0 0-.659-1.591L3.659 7.409A2.25 2.25 0 0 1 3 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0 1 12 3Z" />
|
||||
</svg>
|
||||
{{'Filter'|trans}}
|
||||
</a>
|
||||
|
||||
{% for customGroup in customGroups %}
|
||||
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="{{ customGroup.id }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||
</svg>
|
||||
{{ customGroup.title }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{# Tab Content Area #}
|
||||
<div class="rounded-md w-full border bg-white p-5 shadow-lg dark:border-strokedark dark:bg-boxdark">
|
||||
{# General Tab #}
|
||||
<div id="general" class="tab-content w-full text-stone-500 text-sm block">
|
||||
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{'General'|trans}}</h6>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.title) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.enable) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.percent) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.value) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.mode) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.more) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.count) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.code) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.zeroPayment) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.zeroShipping) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 text-end">
|
||||
<a href="{{ path("psc_shop_voucher_backend_list") }}" class="btn btn-default btn-sm"><i class="fa fa-lg fa-fw fa-arrow-left"></i> {{'back'|trans}}</a>
|
||||
|
||||
{# Validity Tab #}
|
||||
<div id="validity" class="tab-content w-full text-stone-500 text-sm hidden">
|
||||
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">Gültigkeit</h6>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.fromDate) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.toDate) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.minBasketValue) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Filter Tab #}
|
||||
<div id="filter" class="tab-content w-full text-stone-500 text-sm hidden">
|
||||
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{'Filter'|trans}}</h6>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.payment) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.shipping) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.productIds) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.productGroupIds) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Custom Tabs #}
|
||||
{% for customGroup in customGroups %}
|
||||
<div id="{{ customGroup.id }}" class="tab-content w-full text-stone-500 text-sm hidden">
|
||||
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{ customGroup.title }}</h6>
|
||||
{% for customField in customFields %}
|
||||
{% if customField.group == customGroup.id and customField.getTemplate %}
|
||||
{{ include(customField.getTemplate, { 'form': form }) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
{{ form_start(form, { 'attr': {'class': ''}}) }}
|
||||
<div class="panel">
|
||||
<div class="header">
|
||||
<h4>{{ voucher.title }}</h4>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<ul class="nav nav-pills flex-column" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-bs-toggle="tab" href="#all" role="tab">{{'General'|trans}}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-bs-toggle="tab" href="#add" role="tab">{{'Others'|trans}}</a>
|
||||
</li>
|
||||
{% for customGroup in customGroups %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-bs-toggle="tab" href="#{{ customGroup.id }}" role="tab">{{ customGroup.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="all" role="tabpanel">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.title) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.title) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row">
|
||||
<div class="col-md-6">{{ form_widget(form.enable) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.fromDate) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.fromDate) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.toDate) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.toDate) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.percent) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.percent) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.value) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.value) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.mode) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.mode) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.more) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.more) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.count) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.count) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.code) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.code) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.payment) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.payment) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.shipping) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.shipping) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.zeroPayment) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.zeroPayment) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.zeroShipping) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.zeroShipping) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.minBasketValue) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.minBasketValue) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="add" role="tabpanel">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.productIds) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.productIds) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.productGroupIds) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.productGroupIds) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% for customGroup in customGroups %}
|
||||
<div class="tab-pane" id="{{ customGroup.id }}" role="tabpanel">
|
||||
{% for customField in customFields %}
|
||||
{% if customField.group == customGroup.id and customField.getTemplate %}
|
||||
{{ include(customField.getTemplate, { 'form': form }) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-offset-1 col-md-11">
|
||||
{{ form_widget(form.save, {attr: {class: 'btn btn-primary btn-sm'}}) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
{# Save Button outside Card #}
|
||||
<div class="text-end my-2">
|
||||
{{ form_widget(form.save, {
|
||||
attr: {
|
||||
class: 'inline-flex items-center justify-center py-1 gap-1 font-medium rounded-md px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem]'
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
|
||||
{{ summernote_mediabundle_init('default') }}
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
|
||||
{{ summernote_mediabundle_init('default') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -1,39 +1,82 @@
|
||||
{% extends 'backend_base.html.twig' %}
|
||||
{% extends 'backend_tailwind_base.html.twig' %}
|
||||
{% trans_default_domain 'core_voucher_delete' %}
|
||||
|
||||
{% block header %}
|
||||
<div class="flex flex-wrap items-center gap-4 justify-between w-full">
|
||||
<div>
|
||||
<h1 class="text-psc text-2xl font-medium flex flex-row gap-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-8">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 010 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 010-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375z" />
|
||||
</svg>
|
||||
{{'Voucher'|trans}} <span class="text-gray-500">{{'del'|trans}}</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-4 justify-end shrink-0 ml-auto">
|
||||
<a href="{{ path('psc_shop_voucher_backend_list') }}" class="inline-flex items-center justify-center py-1 gap-1 font-medium rounded-md px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" />
|
||||
</svg>
|
||||
{{'back'|trans}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="header">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
|
||||
<h3>
|
||||
<i class="fa-fw fa fa-id-card"></i>
|
||||
{{'Voucher'|trans}} <span>>
|
||||
{{'del'|trans}}</span>
|
||||
<div class="flex flex-col gap-6">
|
||||
{{ form_start(form, { 'attr': {'class': ''}}) }}
|
||||
<div class="rounded-md border border-red-200 bg-white shadow-lg dark:border-strokedark dark:bg-boxdark">
|
||||
{# Card Header #}
|
||||
<div class="border-b border-red-200 bg-red-50 px-7.5 py-4 dark:border-strokedark dark:bg-red-900/20">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-6 h-6 text-red-600 dark:text-red-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
|
||||
</svg>
|
||||
<h3 class="text-xl font-medium text-red-900 dark:text-red-200">
|
||||
{{'DelVoucher'|trans}}?
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
<div class="panel">
|
||||
<div class="header">
|
||||
<h4>{{'DelVoucher'|trans}}?</h4>
|
||||
</div>
|
||||
<div class="body">
|
||||
|
||||
<h5>{{ voucher.title }}</h5>
|
||||
|
||||
{{ form_start(form, { 'attr': {'class': ''}}) }}
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-1 form-control-label"></label>
|
||||
<div class="col-md-1">
|
||||
{{ form_widget(form.yes, {attr: {class: 'btn btn-lg btn-warning btn-sm'}}) }}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
{{ form_widget(form.no, {attr: {class: 'btn btn-lg btn-primary btn-sm'}}) }}
|
||||
</div>
|
||||
{# Card Body #}
|
||||
<div class="px-7.5 py-6">
|
||||
<div class="p-4 bg-yellow-50 rounded-md border border-yellow-200 mb-4">
|
||||
<div class="flex gap-3">
|
||||
<svg class="w-5 h-5 text-yellow-600 flex-shrink-0 mt-0.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
|
||||
</svg>
|
||||
<p class="text-sm text-yellow-800">
|
||||
{{'This action cannot be undone'|trans}}.
|
||||
</p>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
|
||||
<div class="p-4 bg-gray-50 rounded-md border border-gray-200 dark:bg-boxdark-2 dark:border-strokedark">
|
||||
<h5 class="text-lg font-medium text-gray-900 dark:text-bodydark mb-2">
|
||||
{{ voucher.title }}
|
||||
</h5>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">
|
||||
UID: {{ voucher.uid }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Card Footer #}
|
||||
<div class="border-t border-gray-200 px-7.5 py-4 bg-gray-50 dark:border-strokedark dark:bg-boxdark-2">
|
||||
<div class="flex justify-end gap-3">
|
||||
{{ form_widget(form.no, {
|
||||
attr: {
|
||||
class: 'inline-flex items-center justify-center py-2 gap-2 font-medium rounded-md px-4 text-sm text-psc-600 border border-psc-500 bg-white hover:bg-gray-50 hover:ring-2 hover:ring-psc-500 hover:ring-offset-1 shadow-sm'
|
||||
}
|
||||
}) }}
|
||||
{{ form_widget(form.yes, {
|
||||
attr: {
|
||||
class: 'inline-flex items-center justify-center py-2 gap-2 font-medium rounded-md px-4 text-sm text-white shadow-lg bg-red-600 hover:bg-red-700 hover:ring-2 hover:ring-red-500 hover:ring-offset-2'
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@ -1,250 +1,188 @@
|
||||
{% extends 'backend_base.html.twig' %}
|
||||
{% extends 'backend_tailwind_base.html.twig' %}
|
||||
{% form_theme form 'tailwind_formtheme.html.twig' %}
|
||||
{% trans_default_domain 'core_voucher_edit' %}
|
||||
|
||||
{% block header %}
|
||||
<div class="flex flex-wrap items-center gap-4 justify-between w-full">
|
||||
<div>
|
||||
<h1 class="text-psc text-2xl font-medium flex flex-row gap-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-8">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 010 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 010-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375z" />
|
||||
</svg>
|
||||
{{'Voucher'|trans}} <span class="text-gray-500">{{'edit'|trans}}</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-4 justify-end shrink-0 ml-auto">
|
||||
<a href="{{ path('psc_shop_voucher_backend_list') }}" class="inline-flex items-center justify-center py-1 gap-1 font-medium rounded-md px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" />
|
||||
</svg>
|
||||
{{'back'|trans}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="w-full flex flex-col gap-6">
|
||||
{{ form_start(form, {attr: {class: ''}}) }}
|
||||
|
||||
<div class="header">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
|
||||
<h3>
|
||||
<i class="fa-fw fa fa-id-card"></i>
|
||||
{{'Voucher'|trans}} <span>>
|
||||
{{'edit'|trans}} </span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 text-end">
|
||||
<a href="{{ path("psc_shop_voucher_backend_list") }}" class="btn btn-default btn-sm"><i class="fa fa-lg fa-fw fa-arrow-left"></i> {{'back'|trans}}</a>
|
||||
</div>
|
||||
<div class="tab-group flex-none md:flex w-full" data-dui-orientation="vertical">
|
||||
{# Vertical Tab Navigation #}
|
||||
<div role="tablist" class="relative mr-5 rounded-md flex flex-col p-1 w-full md:w-2/12">
|
||||
<div class="tab-indicator absolute left-0 w-1 bg-psc-500 transition-transform duration-300"></div>
|
||||
|
||||
<a href="#" class="tab-link flex items-center text-sm active px-4 py-2 relative" data-dui-tab-target="general">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||
</svg>
|
||||
{{'General'|trans}}
|
||||
</a>
|
||||
|
||||
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="validity">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
|
||||
</svg>
|
||||
Gültigkeit
|
||||
</a>
|
||||
|
||||
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="filter">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 0 1-.659 1.591l-5.432 5.432a2.25 2.25 0 0 0-.659 1.591v2.927a2.25 2.25 0 0 1-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 0 0-.659-1.591L3.659 7.409A2.25 2.25 0 0 1 3 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0 1 12 3Z" />
|
||||
</svg>
|
||||
{{'Filter'|trans}}
|
||||
</a>
|
||||
|
||||
{% for customGroup in customGroups %}
|
||||
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="{{ customGroup.id }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||
</svg>
|
||||
{{ customGroup.title }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
{{ form_start(form, { 'attr': {'class': ''}}) }}
|
||||
<div class="panel">
|
||||
<div class="header">
|
||||
<h4>{{ voucher.title }}</h4>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<ul class="nav nav-pills flex-column" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-bs-toggle="tab" href="#all" role="tab">{{'General'|trans}}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-bs-toggle="tab" href="#add" role="tab">{{'Others'|trans}}</a>
|
||||
</li>
|
||||
{% for customGroup in customGroups %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-bs-toggle="tab" href="#{{ customGroup.id }}" role="tab">{{ customGroup.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{# Tab Content Area #}
|
||||
<div class="rounded-md w-full border bg-white p-5 shadow-lg dark:border-strokedark dark:bg-boxdark">
|
||||
{# General Tab #}
|
||||
<div id="general" class="tab-content w-full text-stone-500 text-sm block">
|
||||
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{'General'|trans}}</h6>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.title) }}
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="all" role="tabpanel">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.title) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.title) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row">
|
||||
<div class="col-md-6">{{ form_widget(form.enable) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.enable) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.fromDate) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.fromDate) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.toDate) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.toDate) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.percent) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.percent) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.value) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.value) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.mode) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.mode) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.more) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.more) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.count) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.count) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.code) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.code) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.zeroPayment) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.zeroPayment) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.zeroShipping) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.zeroShipping) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.minBasketValue) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.minBasketValue) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.payment) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.payment) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.shipping) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.shipping) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="add" role="tabpanel">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.productIds) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.productIds) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-3 form-control-label">{{ form_label(form.productGroupIds) }}</label>
|
||||
<div class="col-md-9">
|
||||
{{ form_widget(form.productGroupIds) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% for customGroup in customGroups %}
|
||||
<div class="tab-pane" id="{{ customGroup.id }}" role="tabpanel">
|
||||
{% for customField in customFields %}
|
||||
{% if customField.group == customGroup.id and customField.getTemplate %}
|
||||
{{ include(customField.getTemplate, { 'form': form }) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.percent) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.value) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.mode) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.more) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.count) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.code) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.zeroPayment) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.zeroShipping) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-offset-1 col-md-11">
|
||||
{{ form_widget(form.save, {attr: {class: 'btn btn-primary btn-sm'}}) }}
|
||||
{# Validity Tab #}
|
||||
<div id="validity" class="tab-content w-full text-stone-500 text-sm hidden">
|
||||
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">Gültigkeit</h6>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.fromDate) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.toDate) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-4/12 px-4">
|
||||
{{ form_row(form.minBasketValue) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
|
||||
{{ summernote_mediabundle_init('default') }}
|
||||
|
||||
<div class="panel">
|
||||
<div class="header">
|
||||
<h4>{{ 'Changes'|trans }}</h4>
|
||||
</div>
|
||||
<div class="body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr><th>{{ 'Date'|trans }}</th><th>{{ 'Username'|trans }}</th><th>{{'Changes'|trans}}</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for change in changes %}
|
||||
<tr><td>{{ change.created|date('H:i:s d.m.Y') }}</td><td>{{ change.username }}</td><td>
|
||||
{% for key,set in change.changeset %}
|
||||
{% if set[1] is not iterable %}
|
||||
<strong>{{key}}</strong> <span class="badge bg-danger"><del>{{ set[0]}}</del></span><span class="badge bg-success">{% if set[1] is null %}0{% else %}{{ set[1] }}{% endif %}</span></br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<td></tr>
|
||||
{# Filter Tab #}
|
||||
<div id="filter" class="tab-content w-full text-stone-500 text-sm hidden">
|
||||
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{'Filter'|trans}}</h6>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.payment) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.shipping) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.productIds) }}
|
||||
</div>
|
||||
<div class="w-full lg:w-6/12 px-4">
|
||||
{{ form_row(form.productGroupIds) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Custom Tabs #}
|
||||
{% for customGroup in customGroups %}
|
||||
<div id="{{ customGroup.id }}" class="tab-content w-full text-stone-500 text-sm hidden">
|
||||
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{ customGroup.title }}</h6>
|
||||
{% for customField in customFields %}
|
||||
{% if customField.group == customGroup.id and customField.getTemplate %}
|
||||
{{ include(customField.getTemplate, { 'form': form }) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Save Button outside Card #}
|
||||
<div class="text-end my-2">
|
||||
{{ form_widget(form.save, {
|
||||
attr: {
|
||||
class: 'inline-flex items-center justify-center py-1 gap-1 font-medium rounded-md px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem]'
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
|
||||
{{ summernote_mediabundle_init('default') }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -1,75 +1,145 @@
|
||||
{% extends 'backend_base.html.twig' %}
|
||||
{% extends 'backend_tailwind_base.html.twig' %}
|
||||
{% trans_default_domain 'core_voucher_list' %}
|
||||
{% block body %}
|
||||
<div class="header">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
|
||||
<h3>
|
||||
<i class="fa-fw fa fa-id-card"></i>
|
||||
{{'Voucher'|trans}} <span>>
|
||||
{{'List'|trans}} </span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{% block header %}
|
||||
<div class="flex flex-wrap items-center gap-4 justify-between w-full">
|
||||
<div>
|
||||
<h1 class="text-psc text-2xl font-medium flex flex-row gap-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-8">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 010 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 010-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375z" />
|
||||
</svg>
|
||||
{{'Voucher'|trans}} <span class="text-gray-500">{{'List'|trans}}</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="panel">
|
||||
<div class="body">
|
||||
<a class="btn btn-info btn-sm" href="{{ path("psc_shop_voucher_backend_create") }}">{{'Addvoucher'|trans}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="body">
|
||||
<table class="table">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Uid'|trans, 'voucher.uid') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Createdat'|trans, 'product.createdAt') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Updatedat'|trans, 'product.updatedAt') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'active'|trans, 'voucher.enable') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Name'|trans, 'voucher.title') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'from'|trans, 'voucher.fromDate') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'to'|trans, 'voucher.toDate') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Percent'|trans, 'voucher.percent') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Value'|trans, 'voucher.value') }}</th>
|
||||
<th>{{'Numbertogenerate'|trans}}</th>
|
||||
<th>{{'Numbergenerated'|trans}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for voucher in pagination %}
|
||||
<tr {% if loop.index is odd %}class="color"{% endif %}>
|
||||
<td>{{ voucher.uid }}</td>
|
||||
<td>{{ voucher.createdAt|date('H:i d.m.Y') }}</td>
|
||||
<td>{{ voucher.updatedAt|date('H:i d.m.Y') }}</td>
|
||||
<td>{% if voucher.enable %}<span class="badge bg-success">{{'yes'|trans}}</span>{% else %}<span
|
||||
class="badge bg-warning">{{'no'|trans}}</span>{% endif %}</td>
|
||||
<td>{{ voucher.title }}</td>
|
||||
<td>{{ voucher.fromDate|date('d.m.Y') }}</td>
|
||||
<td>{{ voucher.toDate|date('d.m.Y') }}</td>
|
||||
<td>{% if voucher.percent %}<span class="badge bg-success">{{'yes'|trans}}</span>{% else %}<span
|
||||
class="badge bg-warning">{{'no'|trans}}</span>{% endif %}</td>
|
||||
<td>{{ voucher.value|number_format(2, ',', '.') }}</td>
|
||||
<td>{% if voucher.more %}Keine Individuellen Codes{% else %}{{ voucher.count }}{% endif %}</td>
|
||||
<td>{% if voucher.more %}Keine Individuellen Codes{% else %}{{ voucher.voucherItems|length }}{% endif %}</td>
|
||||
<td class="text-end">
|
||||
<a href="{{ path('psc_shop_voucher_backend_export', {uid: voucher.uid}) }}" target="_blank" class="btn btn-info btn-sm" style="color: white !important;">{{'Export'|trans}}</a>
|
||||
<a href="{{ path("psc_shop_voucher_backend_generate", {uid: voucher.uid}) }}"
|
||||
class="btn btn-warning btn-sm"><span class="fa fa-trash"></span> {{'Generate'|trans}}</a>
|
||||
<a href="{{ path("psc_shop_voucher_backend_edit", {uid: voucher.uid}) }}"
|
||||
class="btn btn-info btn-sm"><span class="fa fa-edit"></span></a>
|
||||
<a href="{{ path("psc_shop_voucher_backend_delete", {uid: voucher.uid}) }}"
|
||||
class="btn btn-danger btn-sm"><span class="fa fa-trash"></span></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="navigation">
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-4 justify-end shrink-0 ml-auto">
|
||||
<a href="{{ path('psc_shop_voucher_backend_create') }}" class="inline-flex items-center justify-center py-1 gap-1 font-medium rounded-md px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||
</svg>
|
||||
{{'Addvoucher'|trans}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="flex flex-col gap-6">
|
||||
<div class="rounded-md border bg-white px-7.5 py-6 shadow-lg dark:border-strokedark dark:bg-boxdark">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full text-sm">
|
||||
<thead class="bg-slate-50 dark:bg-gray-800">
|
||||
<tr class="border-b-2 border-gray-200 dark:border-gray-700">
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{ knp_pagination_sortable(pagination, 'Uid'|trans, 'voucher.uid') }}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{ knp_pagination_sortable(pagination, 'Createdat'|trans, 'product.createdAt') }}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{ knp_pagination_sortable(pagination, 'Updatedat'|trans, 'product.updatedAt') }}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{ knp_pagination_sortable(pagination, 'active'|trans, 'voucher.enable') }}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{ knp_pagination_sortable(pagination, 'Name'|trans, 'voucher.title') }}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{ knp_pagination_sortable(pagination, 'from'|trans, 'voucher.fromDate') }}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{ knp_pagination_sortable(pagination, 'to'|trans, 'voucher.toDate') }}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{ knp_pagination_sortable(pagination, 'Percent'|trans, 'voucher.percent') }}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{ knp_pagination_sortable(pagination, 'Value'|trans, 'voucher.value') }}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{'Numbertogenerate'|trans}}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
{{'Numbergenerated'|trans}}
|
||||
</th>
|
||||
<th class="px-4 py-4 text-right text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">
|
||||
Aktionen
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white dark:bg-boxdark">
|
||||
{% for voucher in pagination %}
|
||||
<tr class="border-t border-gray-100 hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800/50 transition-colors">
|
||||
<td class="px-4 py-3">
|
||||
<a href="{{ path("psc_shop_voucher_backend_edit", {uid: voucher.uid}) }}"
|
||||
class="inline-flex items-center px-2.5 py-1 rounded-md text-xs font-mono font-medium bg-gray-100 text-gray-800 border border-gray-200 hover:bg-psc-50 hover:text-psc-700 hover:border-psc-300 transition-colors dark:bg-gray-700 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-psc-900 dark:hover:text-psc-300">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-3.5 h-3.5 mr-1.5 text-gray-500 dark:text-gray-400">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 8.25h15m-16.5 7.5h15m-1.8-13.5l-3.9 19.5m-2.1-19.5l-3.9 19.5" />
|
||||
</svg>
|
||||
{{ voucher.uid }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ voucher.createdAt|date('H:i d.m.Y') }}</td>
|
||||
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ voucher.updatedAt|date('H:i d.m.Y') }}</td>
|
||||
<td class="px-4 py-3">
|
||||
{% if voucher.enable %}
|
||||
<span class="badge-yes">{{'yes'|trans}}</span>
|
||||
{% else %}
|
||||
<span class="badge-no">{{'no'|trans}}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-4 py-3 font-medium text-gray-900 dark:text-gray-100">{{ voucher.title }}</td>
|
||||
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ voucher.fromDate|date('d.m.Y') }}</td>
|
||||
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ voucher.toDate|date('d.m.Y') }}</td>
|
||||
<td class="px-4 py-3">
|
||||
{% if voucher.percent %}
|
||||
<span class="badge-yes">{{'yes'|trans}}</span>
|
||||
{% else %}
|
||||
<span class="badge-no">{{'no'|trans}}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ voucher.value|number_format(2, ',', '.') }}</td>
|
||||
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{% if voucher.more %}Keine Individuellen Codes{% else %}{{ voucher.count }}{% endif %}</td>
|
||||
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{% if voucher.more %}Keine Individuellen Codes{% else %}{{ voucher.voucherItems|length }}{% endif %}</td>
|
||||
<td class="px-4 py-3 text-right">
|
||||
<div class="flex flex-row gap-2 justify-end">
|
||||
{# Export - BLAU #}
|
||||
<a href="{{ path('psc_shop_voucher_backend_export', {uid: voucher.uid}) }}" target="_blank" title="{{'Export'|trans}}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="table-icon text-blue-600 hover:text-blue-700 dark:text-blue-500 dark:hover:text-blue-400">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3" />
|
||||
</svg>
|
||||
</a>
|
||||
{# Generate - GELB #}
|
||||
<a href="{{ path("psc_shop_voucher_backend_generate", {uid: voucher.uid}) }}" title="{{'Generate'|trans}}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="table-icon text-yellow-600 hover:text-yellow-700 dark:text-yellow-500 dark:hover:text-yellow-400">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" />
|
||||
</svg>
|
||||
</a>
|
||||
{# Bearbeiten - GRÜN #}
|
||||
<a href="{{ path("psc_shop_voucher_backend_edit", {uid: voucher.uid}) }}" title="{{'edit'|trans}}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="table-icon text-green-600 hover:text-green-700 dark:text-green-500 dark:hover:text-green-400">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
|
||||
</svg>
|
||||
</a>
|
||||
{# Löschen - ROT #}
|
||||
<a href="{{ path("psc_shop_voucher_backend_delete", {uid: voucher.uid}) }}" title="{{'delete'|trans}}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="table-icon text-red-600 hover:text-red-700 dark:text-red-500 dark:hover:text-red-400">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
{{ knp_pagination_render(pagination, 'tailwind_pagination.html.twig', {}, {
|
||||
'sortableTemplate': 'tailwind_sortable.html.twig'
|
||||
}) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Table(name="gutschein_codes")
|
||||
* @ORM\Entity(repositoryClass="Plugin\Custom\PSC\Gutschein\Repository\GutscheinCodeRepository")
|
||||
*/
|
||||
class GutscheinCode
|
||||
{
|
||||
/**
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||
*/
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="code", type="string", length=30, unique=true)
|
||||
*/
|
||||
private string $code;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="order_position_id", type="integer")
|
||||
*/
|
||||
private int $orderPositionId;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="amount", type="decimal", precision=10, scale=2)
|
||||
*/
|
||||
private float $amount;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="expiration_date", type="datetime")
|
||||
*/
|
||||
private \DateTime $expirationDate;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="created_at", type="datetime")
|
||||
*/
|
||||
private \DateTime $createdAt;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="used", type="boolean")
|
||||
*/
|
||||
private bool $used = false;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="used_at", type="datetime", nullable=true)
|
||||
*/
|
||||
private ?\DateTime $usedAt = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="used_in_order_id", type="integer", nullable=true)
|
||||
*/
|
||||
private ?int $usedInOrderId = null;
|
||||
|
||||
// Getters and Setters
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getCode(): string
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setCode(string $code): void
|
||||
{
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
public function getOrderPositionId(): int
|
||||
{
|
||||
return $this->orderPositionId;
|
||||
}
|
||||
|
||||
public function setOrderPositionId(int $orderPositionId): void
|
||||
{
|
||||
$this->orderPositionId = $orderPositionId;
|
||||
}
|
||||
|
||||
public function getAmount(): float
|
||||
{
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
public function setAmount(float $amount): void
|
||||
{
|
||||
$this->amount = $amount;
|
||||
}
|
||||
|
||||
public function getExpirationDate(): \DateTime
|
||||
{
|
||||
return $this->expirationDate;
|
||||
}
|
||||
|
||||
public function setExpirationDate(\DateTime $expirationDate): void
|
||||
{
|
||||
$this->expirationDate = $expirationDate;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTime
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt(\DateTime $createdAt): void
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
}
|
||||
|
||||
public function isUsed(): bool
|
||||
{
|
||||
return $this->used;
|
||||
}
|
||||
|
||||
public function setUsed(bool $used): void
|
||||
{
|
||||
$this->used = $used;
|
||||
}
|
||||
|
||||
public function getUsedAt(): ?\DateTime
|
||||
{
|
||||
return $this->usedAt;
|
||||
}
|
||||
|
||||
public function setUsedAt(?\DateTime $usedAt): void
|
||||
{
|
||||
$this->usedAt = $usedAt;
|
||||
}
|
||||
|
||||
public function getUsedInOrderId(): ?int
|
||||
{
|
||||
return $this->usedInOrderId;
|
||||
}
|
||||
|
||||
public function setUsedInOrderId(?int $usedInOrderId): void
|
||||
{
|
||||
$this->usedInOrderId = $usedInOrderId;
|
||||
}
|
||||
|
||||
public function isValid(): bool
|
||||
{
|
||||
return !$this->used && $this->expirationDate > new \DateTime();
|
||||
}
|
||||
}
|
||||
87
src/new/var/plugins/Custom/PSC/Gutschein/Form/Field/Calc.php
Normal file
87
src/new/var/plugins/Custom/PSC/Gutschein/Form/Field/Calc.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Form\Field;
|
||||
|
||||
use PSC\Shop\EntityBundle\Entity\Product;
|
||||
use PSC\System\PluginBundle\Form\Interfaces\Field;
|
||||
use PSC\System\SettingsBundle\Service\General;
|
||||
use PSC\System\SettingsBundle\Service\Tax;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
|
||||
class Calc implements Field
|
||||
{
|
||||
public function __construct(
|
||||
protected General $generalService,
|
||||
protected Tax $taxService,
|
||||
) {}
|
||||
|
||||
public function getTemplate()
|
||||
{
|
||||
return '@PluginCustomPSCGutschein/form/field/calc.html.twig';
|
||||
}
|
||||
|
||||
public function getModule()
|
||||
{
|
||||
return Field::Product;
|
||||
}
|
||||
|
||||
public function formPreSubmit(FormEvent $event)
|
||||
{
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$product = $options['product'];
|
||||
|
||||
$builder->add('minAmount', MoneyType::class, [
|
||||
'required' => false,
|
||||
'label' => 'Minimaler Gutscheinwert',
|
||||
'data' => 10.00,
|
||||
])->add('maxAmount', MoneyType::class, [
|
||||
'required' => false,
|
||||
'label' => 'Maximaler Gutscheinwert',
|
||||
'data' => 500.00,
|
||||
])->add('defaultAmount', MoneyType::class, [
|
||||
'required' => false,
|
||||
'label' => 'Voreingestellter Wert',
|
||||
'data' => 50.00,
|
||||
])->add('validityMonths', IntegerType::class, [
|
||||
'required' => false,
|
||||
'label' => 'Gültigkeit (Monate)',
|
||||
'data' => 12,
|
||||
]);
|
||||
|
||||
if ($product) {
|
||||
$builder->get('defaultAmount')->setData($product->gutschein['defaultAmount'] ?? null);
|
||||
$builder->get('minAmount')->setData($product->gutschein['minAmount'] ?? null);
|
||||
$builder->get('maxAmount')->setData($product->gutschein['maxAmount'] ?? null);
|
||||
$builder->get('validityMonths')->setData($product->gutschein['validityMonths'] ?? null);
|
||||
}
|
||||
return $builder;
|
||||
}
|
||||
|
||||
public function getGroup()
|
||||
{
|
||||
return \Plugin\Custom\PSC\Gutschein\Form\Group\Calc::GROUP_ID;
|
||||
}
|
||||
|
||||
public function formPostSetData(FormEvent $event)
|
||||
{
|
||||
}
|
||||
|
||||
public function formPostSubmit(FormEvent $event)
|
||||
{
|
||||
}
|
||||
|
||||
public function formPreSetData(FormEvent $event)
|
||||
{
|
||||
}
|
||||
|
||||
public function formSubmit(FormEvent $event)
|
||||
{
|
||||
}
|
||||
}
|
||||
26
src/new/var/plugins/Custom/PSC/Gutschein/Form/Group/Calc.php
Normal file
26
src/new/var/plugins/Custom/PSC/Gutschein/Form/Group/Calc.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Form\Group;
|
||||
|
||||
use PSC\System\PluginBundle\Form\Group;
|
||||
use PSC\System\PluginBundle\Form\Interfaces\Field;
|
||||
|
||||
class Calc extends Group
|
||||
{
|
||||
const GROUP_ID = 'gutschein';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->title = 'Gutschein-Einstellungen';
|
||||
}
|
||||
|
||||
public function getModule()
|
||||
{
|
||||
return Field::Product;
|
||||
}
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return self::GROUP_ID;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Model;
|
||||
|
||||
use PSC\Shop\OrderBundle\Model\Order\Position\IProductTypeObject;
|
||||
|
||||
class ProductSpecialObject implements IProductTypeObject
|
||||
{
|
||||
private int $taxClass = 1900; // 19% VAT
|
||||
private array $params = [];
|
||||
|
||||
// Backend configuration (set by admin)
|
||||
private float $minAmount = 10.00;
|
||||
private float $maxAmount = 500.00;
|
||||
private ?float $defaultAmount = 50.00;
|
||||
private int $validityMonths = 12;
|
||||
|
||||
// Customer-entered data
|
||||
private float $voucherAmount = 0;
|
||||
private string $recipientName = '';
|
||||
private string $greetingMessage = '';
|
||||
private string $deliveryMethod = 'digital';
|
||||
|
||||
// Generated data
|
||||
private string $voucherCode = '';
|
||||
private ?\DateTime $expirationDate = null;
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'Gutscheinprodukt';
|
||||
}
|
||||
|
||||
public function getTyp(): int
|
||||
{
|
||||
return 9; // Product Type ID
|
||||
}
|
||||
|
||||
public function getPositionData(): array
|
||||
{
|
||||
return [
|
||||
'params' => $this->params,
|
||||
'voucherAmount' => $this->voucherAmount,
|
||||
'recipientName' => $this->recipientName,
|
||||
'greetingMessage' => $this->greetingMessage,
|
||||
'deliveryMethod' => $this->deliveryMethod,
|
||||
'voucherCode' => $this->voucherCode,
|
||||
'expirationDate' => $this->expirationDate?->format('Y-m-d H:i:s'),
|
||||
'validityMonths' => $this->validityMonths,
|
||||
];
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public function getTaxClass(): int
|
||||
{
|
||||
return $this->taxClass;
|
||||
}
|
||||
|
||||
public function setTaxClass(int $taxClass): void
|
||||
{
|
||||
$this->taxClass = $taxClass;
|
||||
}
|
||||
|
||||
public function getParams(): array
|
||||
{
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
public function setParams(array $params): void
|
||||
{
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
public function getMinAmount(): float
|
||||
{
|
||||
return $this->minAmount;
|
||||
}
|
||||
|
||||
public function setMinAmount(float $minAmount): void
|
||||
{
|
||||
$this->minAmount = $minAmount;
|
||||
}
|
||||
|
||||
public function getMaxAmount(): float
|
||||
{
|
||||
return $this->maxAmount;
|
||||
}
|
||||
|
||||
public function setMaxAmount(float $maxAmount): void
|
||||
{
|
||||
$this->maxAmount = $maxAmount;
|
||||
}
|
||||
|
||||
public function getDefaultAmount(): ?float
|
||||
{
|
||||
return $this->defaultAmount;
|
||||
}
|
||||
|
||||
public function setDefaultAmount(?float $defaultAmount): void
|
||||
{
|
||||
$this->defaultAmount = $defaultAmount;
|
||||
}
|
||||
|
||||
public function getValidityMonths(): int
|
||||
{
|
||||
return $this->validityMonths;
|
||||
}
|
||||
|
||||
public function setValidityMonths(int $validityMonths): void
|
||||
{
|
||||
$this->validityMonths = $validityMonths;
|
||||
}
|
||||
|
||||
public function getVoucherAmount(): float
|
||||
{
|
||||
return $this->voucherAmount;
|
||||
}
|
||||
|
||||
public function setVoucherAmount(float $voucherAmount): void
|
||||
{
|
||||
$this->voucherAmount = $voucherAmount;
|
||||
}
|
||||
|
||||
public function getRecipientName(): string
|
||||
{
|
||||
return $this->recipientName;
|
||||
}
|
||||
|
||||
public function setRecipientName(string $recipientName): void
|
||||
{
|
||||
$this->recipientName = $recipientName;
|
||||
}
|
||||
|
||||
public function getGreetingMessage(): string
|
||||
{
|
||||
return $this->greetingMessage;
|
||||
}
|
||||
|
||||
public function setGreetingMessage(string $greetingMessage): void
|
||||
{
|
||||
$this->greetingMessage = $greetingMessage;
|
||||
}
|
||||
|
||||
public function getDeliveryMethod(): string
|
||||
{
|
||||
return $this->deliveryMethod;
|
||||
}
|
||||
|
||||
public function setDeliveryMethod(string $deliveryMethod): void
|
||||
{
|
||||
$this->deliveryMethod = $deliveryMethod;
|
||||
}
|
||||
|
||||
public function getVoucherCode(): string
|
||||
{
|
||||
return $this->voucherCode;
|
||||
}
|
||||
|
||||
public function setVoucherCode(string $voucherCode): void
|
||||
{
|
||||
$this->voucherCode = $voucherCode;
|
||||
}
|
||||
|
||||
public function getExpirationDate(): ?\DateTime
|
||||
{
|
||||
return $this->expirationDate;
|
||||
}
|
||||
|
||||
public function setExpirationDate(?\DateTime $expirationDate): void
|
||||
{
|
||||
$this->expirationDate = $expirationDate;
|
||||
}
|
||||
}
|
||||
40
src/new/var/plugins/Custom/PSC/Gutschein/Plugin.php
Normal file
40
src/new/var/plugins/Custom/PSC/Gutschein/Plugin.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein;
|
||||
|
||||
use PSC\System\PluginBundle\Plugin\Base;
|
||||
|
||||
class Plugin extends Base implements \PSC\System\PluginBundle\Interfaces\Plugin
|
||||
{
|
||||
protected $name = 'Gutschein Produkt';
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return self::ProductType;
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Gutscheine mit variablem Wert, Personalisierung und Gültigkeitsdauer';
|
||||
}
|
||||
|
||||
public function getVersion(): string
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getIdentifier(): string
|
||||
{
|
||||
return 'gutschein';
|
||||
}
|
||||
|
||||
public function getInstallClass(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getDeInstallClass(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
202
src/new/var/plugins/Custom/PSC/Gutschein/Producer/Producer.php
Normal file
202
src/new/var/plugins/Custom/PSC/Gutschein/Producer/Producer.php
Normal file
@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Producer;
|
||||
|
||||
use Brick\Math\RoundingMode;
|
||||
use Brick\Money\Money;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Plugin\Custom\PSC\Gutschein\Model\ProductSpecialObject;
|
||||
use Plugin\Custom\PSC\Gutschein\Service\CodeGenerator;
|
||||
use PSC\Shop\OrderBundle\Model\Order\Position;
|
||||
use PSC\Shop\OrderBundle\Model\Order\Position\Price;
|
||||
use PSC\Shop\OrderBundle\Model\Order\Tax;
|
||||
use PSC\Shop\OrderBundle\Model\Order\TaxEnum;
|
||||
use PSC\Shop\ProductBundle\Interfaces\IProducer;
|
||||
use PSC\Shop\ProductBundle\Interfaces\IProducerHydrateModel;
|
||||
use PSC\Shop\ProductBundle\Interfaces\IProductTransformer;
|
||||
use PSC\Shop\ProductBundle\Interfaces\IUiProducer;
|
||||
use PSC\Shop\ProductBundle\Model\Product;
|
||||
|
||||
class Producer implements IUiProducer, IProducerHydrateModel
|
||||
{
|
||||
private Product $product;
|
||||
private float $voucherAmount = 0; // Customer-entered amount
|
||||
private int $count = 1;
|
||||
private string $recipientName = '';
|
||||
private string $greetingMessage = '';
|
||||
private string $deliveryMethod = 'digital'; // 'digital' or 'physical'
|
||||
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly CodeGenerator $codeGenerator,
|
||||
) {}
|
||||
|
||||
public function setProduct(Product $product): void
|
||||
{
|
||||
$this->product = $product;
|
||||
$this->process();
|
||||
}
|
||||
|
||||
public function getPrice(): Price
|
||||
{
|
||||
/** @var ProductSpecialObject $specProd */
|
||||
$specProd = $this->product->getSpecialProductTypeObject();
|
||||
|
||||
// CRITICAL: Voucher amount is customer-defined, not from product entity
|
||||
$priceObj = Money::ofMinor($this->voucherAmount * 100, 'EUR');
|
||||
|
||||
$price = new Price();
|
||||
$price->setNet($priceObj->getMinorAmount()->toInt());
|
||||
$price->setVat(
|
||||
$priceObj
|
||||
->toRational()
|
||||
->dividedBy(100)
|
||||
->multipliedBy($specProd->getTaxClass() / 100)
|
||||
->to($priceObj->getContext(), RoundingMode::UP)
|
||||
->getMinorAmount()
|
||||
->toInt(),
|
||||
);
|
||||
$price->setGross($price->getNet() + $price->getVat());
|
||||
$price->setCount($this->count);
|
||||
$price->setAllNet($price->getNet() * $this->count);
|
||||
$price->setAllVat($price->getVat() * $this->count);
|
||||
$price->setAllGross($price->getGross() * $this->count);
|
||||
$price->tax = new Tax($specProd->getTaxClass(), $price->getAllNet(), $price->getAllVat(), TaxEnum::POSITION);
|
||||
|
||||
return $price;
|
||||
}
|
||||
|
||||
public function getJsonForm(): array
|
||||
{
|
||||
/** @var ProductSpecialObject $specProd */
|
||||
$specProd = $this->product->getSpecialProductTypeObject();
|
||||
|
||||
return [
|
||||
'title' => $this->product->getTitle(),
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'voucherAmount' => [
|
||||
'type' => 'number',
|
||||
'title' => 'Gutscheinwert (€)',
|
||||
'minimum' => $specProd->getMinAmount(),
|
||||
'maximum' => $specProd->getMaxAmount(),
|
||||
'default' => $specProd->getDefaultAmount() ?? 50.00,
|
||||
],
|
||||
'recipientName' => [
|
||||
'type' => 'string',
|
||||
'title' => 'Name des Empfängers',
|
||||
'maxLength' => 100,
|
||||
],
|
||||
'greetingMessage' => [
|
||||
'type' => 'string',
|
||||
'title' => 'Grußtext (optional)',
|
||||
'maxLength' => 500,
|
||||
],
|
||||
'deliveryMethod' => [
|
||||
'type' => 'string',
|
||||
'title' => 'Versandart',
|
||||
'enum' => ['digital', 'physical'],
|
||||
'enumNames' => ['Digital (E-Mail)', 'Gedruckt (Postversand)'],
|
||||
'default' => 'digital',
|
||||
],
|
||||
'count' => [
|
||||
'type' => 'integer',
|
||||
'title' => 'Anzahl',
|
||||
'minimum' => 1,
|
||||
'default' => 1,
|
||||
],
|
||||
],
|
||||
'required' => ['voucherAmount', 'recipientName', 'deliveryMethod'],
|
||||
];
|
||||
}
|
||||
|
||||
public function setParams(array $params): void
|
||||
{
|
||||
if (isset($params['voucherAmount'])) {
|
||||
$this->voucherAmount = (float) $params['voucherAmount'];
|
||||
}
|
||||
if (isset($params['recipientName'])) {
|
||||
$this->recipientName = $params['recipientName'];
|
||||
}
|
||||
if (isset($params['greetingMessage'])) {
|
||||
$this->greetingMessage = $params['greetingMessage'];
|
||||
}
|
||||
if (isset($params['deliveryMethod'])) {
|
||||
$this->deliveryMethod = $params['deliveryMethod'];
|
||||
}
|
||||
if (isset($params['count'])) {
|
||||
$this->count = (int) $params['count'];
|
||||
}
|
||||
}
|
||||
|
||||
public function getCount(): int
|
||||
{
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
public function calcPriceForOrderPosition(Position $position): void
|
||||
{
|
||||
// Generate unique voucher code for this order position
|
||||
$voucherCode = $this->codeGenerator->generate();
|
||||
|
||||
/** @var ProductSpecialObject $specProd */
|
||||
$specProd = $position->getProduct()->getSpecialProductTypeObject();
|
||||
$specProd->setVoucherCode($voucherCode);
|
||||
$specProd->setVoucherAmount($this->voucherAmount);
|
||||
$specProd->setRecipientName($this->recipientName);
|
||||
$specProd->setGreetingMessage($this->greetingMessage);
|
||||
$specProd->setDeliveryMethod($this->deliveryMethod);
|
||||
|
||||
// Calculate expiration date
|
||||
$validityMonths = $specProd->getValidityMonths() ?? 12;
|
||||
$expirationDate = new \DateTime();
|
||||
$expirationDate->modify("+{$validityMonths} months");
|
||||
$specProd->setExpirationDate($expirationDate);
|
||||
|
||||
$position->setPrice($this->getPrice());
|
||||
}
|
||||
|
||||
public function getProductTransformer(): IProductTransformer
|
||||
{
|
||||
return new \Plugin\Custom\PSC\Gutschein\Transformer\Product();
|
||||
}
|
||||
|
||||
public function getUiJsonForm(): array
|
||||
{
|
||||
/** @var ProductSpecialObject $specProd */
|
||||
$specProd = $this->product->getSpecialProductTypeObject();
|
||||
|
||||
$minAmount = $specProd->getMinAmount();
|
||||
$maxAmount = $specProd->getMaxAmount();
|
||||
|
||||
return [
|
||||
'ui:submitButtonOptions' => [
|
||||
'submitText' => 'In den Warenkorb',
|
||||
'norender' => true,
|
||||
'props' => [
|
||||
'disabled' => false,
|
||||
'className' => 'btn btn-primary btn-lg',
|
||||
],
|
||||
],
|
||||
'voucherAmount' => [
|
||||
'ui:widget' => 'updown',
|
||||
'ui:help' => "Wählen Sie einen Betrag zwischen {$minAmount}€ und {$maxAmount}€",
|
||||
],
|
||||
'greetingMessage' => [
|
||||
'ui:widget' => 'textarea',
|
||||
'ui:options' => [
|
||||
'rows' => 5,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
private function process(): void
|
||||
{
|
||||
// Load existing params from product if available
|
||||
if (!empty($this->product->getSpecialProductTypeObject()->getParams())) {
|
||||
$params = $this->product->getSpecialProductTypeObject()->getParams();
|
||||
$this->setParams($params);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Plugin\Custom\PSC\Gutschein\Entity\GutscheinCode;
|
||||
|
||||
class GutscheinCodeRepository extends EntityRepository
|
||||
{
|
||||
public function findValidCode(string $code): ?GutscheinCode
|
||||
{
|
||||
$qb = $this->createQueryBuilder('gc');
|
||||
|
||||
return $qb
|
||||
->where('gc.code = :code')
|
||||
->andWhere('gc.used = :used')
|
||||
->andWhere('gc.expirationDate > :now')
|
||||
->setParameter('code', $code)
|
||||
->setParameter('used', false)
|
||||
->setParameter('now', new \DateTime())
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
|
||||
public function findByOrderPosition(int $orderPositionId): array
|
||||
{
|
||||
return $this->findBy(['orderPositionId' => $orderPositionId]);
|
||||
}
|
||||
|
||||
public function getUsageStats(): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('gc');
|
||||
|
||||
$total = (clone $qb)
|
||||
->select('COUNT(gc.id)')
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
|
||||
$used = (clone $qb)
|
||||
->select('COUNT(gc.id)')
|
||||
->where('gc.used = :used')
|
||||
->setParameter('used', true)
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
|
||||
$expired = (clone $qb)
|
||||
->select('COUNT(gc.id)')
|
||||
->where('gc.expirationDate < :now')
|
||||
->andWhere('gc.used = :used')
|
||||
->setParameter('now', new \DateTime())
|
||||
->setParameter('used', false)
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
|
||||
return [
|
||||
'total' => $total,
|
||||
'used' => $used,
|
||||
'expired' => $expired,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Plugin\Custom\PSC\Gutschein\:
|
||||
resource: '../../*/*'
|
||||
|
||||
Plugin\Custom\PSC\Gutschein\Service\ProductType:
|
||||
tags:
|
||||
- { name: psc.product.type }
|
||||
|
||||
Plugin\Custom\PSC\Gutschein\Form\Group\Calc:
|
||||
tags:
|
||||
- { name: psc.backend.custom.groups, productType: 9 }
|
||||
|
||||
Plugin\Custom\PSC\Gutschein\Form\Field\Calc:
|
||||
tags:
|
||||
- { name: psc.backend.custom.fields, productType: 9 }
|
||||
@ -0,0 +1,44 @@
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h5>Gutschein-Konfiguration</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
{{ form_label(form.gutschein.validityMonths) }}
|
||||
{{ form_widget(form.gutschein.validityMonths) }}
|
||||
<small class="form-text text-muted">Gültigkeitsdauer ab Kaufdatum</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
{{ form_label(form.gutschein.minAmount) }}
|
||||
{{ form_widget(form.gutschein.minAmount) }}
|
||||
<small class="form-text text-muted">Mindestbetrag</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
{{ form_label(form.gutschein.defaultAmount) }}
|
||||
{{ form_widget(form.gutschein.defaultAmount) }}
|
||||
<small class="form-text text-muted">Vorauswahl</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
{{ form_label(form.gutschein.maxAmount) }}
|
||||
{{ form_widget(form.gutschein.maxAmount) }}
|
||||
<small class="form-text text-muted">Maximalbetrag</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<strong>Hinweis:</strong> Kunden können beim Kauf einen beliebigen Betrag zwischen Minimal- und Maximalbetrag wählen.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Service;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Plugin\Custom\PSC\Gutschein\Entity\GutscheinCode;
|
||||
|
||||
class CodeGenerator
|
||||
{
|
||||
private const CODE_LENGTH = 16;
|
||||
private const CODE_PREFIX = 'GS';
|
||||
private const MAX_ATTEMPTS = 10;
|
||||
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager
|
||||
) {
|
||||
}
|
||||
|
||||
public function generate(): string
|
||||
{
|
||||
$attempts = 0;
|
||||
|
||||
do {
|
||||
$code = $this->generateCode();
|
||||
$exists = $this->codeExists($code);
|
||||
$attempts++;
|
||||
|
||||
if ($attempts >= self::MAX_ATTEMPTS) {
|
||||
throw new \RuntimeException('Could not generate unique voucher code after ' . self::MAX_ATTEMPTS . ' attempts');
|
||||
}
|
||||
} while ($exists);
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
private function generateCode(): string
|
||||
{
|
||||
// Format: GS-XXXX-XXXX-XXXX-XXXX
|
||||
$segments = [];
|
||||
for ($i = 0; $i < 4; $i++) {
|
||||
$segments[] = $this->randomSegment(4);
|
||||
}
|
||||
|
||||
return self::CODE_PREFIX . '-' . implode('-', $segments);
|
||||
}
|
||||
|
||||
private function randomSegment(int $length): string
|
||||
{
|
||||
$characters = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ'; // Exclude I, O to avoid confusion
|
||||
$segment = '';
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$segment .= $characters[random_int(0, strlen($characters) - 1)];
|
||||
}
|
||||
|
||||
return $segment;
|
||||
}
|
||||
|
||||
private function codeExists(string $code): bool
|
||||
{
|
||||
$existing = $this->entityManager
|
||||
->getRepository(GutscheinCode::class)
|
||||
->findOneBy(['code' => $code]);
|
||||
|
||||
return $existing !== null;
|
||||
}
|
||||
|
||||
public function saveCode(string $code, int $orderPositionId, float $amount, \DateTime $expirationDate): GutscheinCode
|
||||
{
|
||||
$gutscheinCode = new GutscheinCode();
|
||||
$gutscheinCode->setCode($code);
|
||||
$gutscheinCode->setOrderPositionId($orderPositionId);
|
||||
$gutscheinCode->setAmount($amount);
|
||||
$gutscheinCode->setExpirationDate($expirationDate);
|
||||
$gutscheinCode->setCreatedAt(new \DateTime());
|
||||
$gutscheinCode->setUsed(false);
|
||||
|
||||
$this->entityManager->persist($gutscheinCode);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $gutscheinCode;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Service;
|
||||
|
||||
use Plugin\Custom\PSC\Gutschein\Model\ProductSpecialObject;
|
||||
use Plugin\Custom\PSC\Gutschein\Producer\Producer;
|
||||
use Plugin\Custom\PSC\Gutschein\Transformer\Position;
|
||||
use PSC\Shop\OrderBundle\Model\Order\Position\IProductTypeObject;
|
||||
use PSC\Shop\OrderBundle\Transformer\Order\Position\IPositionTransformer;
|
||||
use PSC\Shop\ProductBundle\Interfaces\IProducer;
|
||||
|
||||
class ProductType implements \PSC\System\PluginBundle\Product\Type
|
||||
{
|
||||
private Position $productTransformer;
|
||||
private Producer $producer;
|
||||
|
||||
public function __construct(Position $positionTransformer, Producer $producer)
|
||||
{
|
||||
$this->productTransformer = $positionTransformer;
|
||||
$this->producer = $producer;
|
||||
}
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return 9; // NEW UNIQUE ID
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'Gutscheinprodukt';
|
||||
}
|
||||
|
||||
public function getPositionProductTransformer(): IPositionTransformer
|
||||
{
|
||||
return $this->productTransformer;
|
||||
}
|
||||
|
||||
public function getProducer(): IProducer
|
||||
{
|
||||
return $this->producer;
|
||||
}
|
||||
|
||||
public function getProductTypeObject(): IProductTypeObject
|
||||
{
|
||||
return new ProductSpecialObject();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Transformer;
|
||||
|
||||
use PSC\Shop\EntityBundle\Entity\Orderpos;
|
||||
use PSC\Shop\OrderBundle\Transformer\Order\Position\IPositionTransformer;
|
||||
use Plugin\Custom\PSC\Gutschein\Model\ProductSpecialObject;
|
||||
|
||||
class Position implements IPositionTransformer
|
||||
{
|
||||
public function fromDb(
|
||||
\PSC\Shop\OrderBundle\Model\Order\Position $position,
|
||||
Orderpos $posEntity,
|
||||
\PSC\Shop\EntityBundle\Document\Position $posDoc
|
||||
) {
|
||||
$obj = new ProductSpecialObject();
|
||||
|
||||
$data = $posDoc->getSpecialProductTypeObject();
|
||||
|
||||
if (isset($data['params'])) {
|
||||
$obj->setParams($data['params']);
|
||||
}
|
||||
if (isset($data['voucherAmount'])) {
|
||||
$obj->setVoucherAmount($data['voucherAmount']);
|
||||
}
|
||||
if (isset($data['recipientName'])) {
|
||||
$obj->setRecipientName($data['recipientName']);
|
||||
}
|
||||
if (isset($data['greetingMessage'])) {
|
||||
$obj->setGreetingMessage($data['greetingMessage']);
|
||||
}
|
||||
if (isset($data['deliveryMethod'])) {
|
||||
$obj->setDeliveryMethod($data['deliveryMethod']);
|
||||
}
|
||||
if (isset($data['voucherCode'])) {
|
||||
$obj->setVoucherCode($data['voucherCode']);
|
||||
}
|
||||
if (isset($data['expirationDate'])) {
|
||||
$obj->setExpirationDate(new \DateTime($data['expirationDate']));
|
||||
}
|
||||
if (isset($data['validityMonths'])) {
|
||||
$obj->setValidityMonths($data['validityMonths']);
|
||||
}
|
||||
|
||||
$position->getProduct()->setSpecialProductTypeObject($obj);
|
||||
}
|
||||
|
||||
public function toDb(
|
||||
\PSC\Shop\OrderBundle\Model\Order\Position $position,
|
||||
Orderpos $posEntity,
|
||||
\PSC\Shop\EntityBundle\Document\Position $posDoc
|
||||
) {
|
||||
// Position data is stored via getPositionData() in ProductSpecialObject
|
||||
// No additional transformation needed here
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Gutschein\Transformer;
|
||||
|
||||
use Plugin\Custom\PSC\Gutschein\Model\ProductSpecialObject;
|
||||
use PSC\Shop\ProductBundle\Interfaces\IProductTransformer;
|
||||
|
||||
class Product implements IProductTransformer
|
||||
{
|
||||
public function fromDb(
|
||||
\PSC\Shop\ProductBundle\Model\Product $productModel,
|
||||
\PSC\Shop\EntityBundle\Entity\Product $productEntity,
|
||||
\PSC\Shop\EntityBundle\Document\Product $productDoc
|
||||
): void {
|
||||
if ($productModel->getSpecialProductTypeObject() == null) {
|
||||
$productModel->setSpecialProductTypeObject(new ProductSpecialObject());
|
||||
}
|
||||
|
||||
/** @var ProductSpecialObject $prodSpec */
|
||||
$prodSpec = $productModel->getSpecialProductTypeObject();
|
||||
|
||||
// Load backend configuration from product entity
|
||||
$prodSpec->setTaxClass($productEntity->getMwert() * 100);
|
||||
|
||||
// Load custom fields from MongoDB document (if stored there)
|
||||
if ($productDoc->getCustom1()) {
|
||||
$prodSpec->setMinAmount((float)$productDoc->getCustom1());
|
||||
}
|
||||
if ($productDoc->getCustom2()) {
|
||||
$prodSpec->setMaxAmount((float)$productDoc->getCustom2());
|
||||
}
|
||||
if ($productDoc->getCustom3()) {
|
||||
$prodSpec->setDefaultAmount((float)$productDoc->getCustom3());
|
||||
}
|
||||
if ($productDoc->getCustom4()) {
|
||||
$prodSpec->setValidityMonths((int)$productDoc->getCustom4());
|
||||
}
|
||||
}
|
||||
|
||||
public function toDb(
|
||||
\PSC\Shop\ProductBundle\Model\Product $productModel,
|
||||
\PSC\Shop\EntityBundle\Entity\Product $productEntity,
|
||||
\PSC\Shop\EntityBundle\Document\Product $productDoc
|
||||
): void {
|
||||
/** @var ProductSpecialObject $prodSpec */
|
||||
$prodSpec = $productModel->getSpecialProductTypeObject();
|
||||
|
||||
// Save configuration to MongoDB custom fields
|
||||
$productDoc->setCustom1((string)$prodSpec->getMinAmount());
|
||||
$productDoc->setCustom2((string)$prodSpec->getMaxAmount());
|
||||
$productDoc->setCustom3((string)$prodSpec->getDefaultAmount());
|
||||
$productDoc->setCustom4((string)$prodSpec->getValidityMonths());
|
||||
}
|
||||
}
|
||||
@ -67,6 +67,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-6 text-right">
|
||||
<a class="bg-yellow-500 hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 rounded shadow" href="/article/show/uuid/{{ product.uuid }}">Abbrechen & Zurück</a>
|
||||
<button class="px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:bg-gray-300 disabled:cursor-not-allowed" id="nextToStep2" disabled>Weiter zu Schritt 2</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -799,7 +800,19 @@
|
||||
title="Berechneter Wert: ${tabInfo}"
|
||||
onchange="updateTabNumber(${index}, this.value)" />
|
||||
</td>
|
||||
<td class="px-4 py-3 whitespace-nowrap text-center">
|
||||
<td class="px-4 py-3 whitespace-nowrap text-center" onclick="event.stopPropagation()">
|
||||
<select class="px-2 py-1 border border-gray-300 rounded focus:outline-none focus:border-blue-500"
|
||||
id="color-select-${index}"
|
||||
onchange="updateColor(${index}, this.value)"
|
||||
style="color: ${pdf.color || 'black'};">
|
||||
<option value="black" ${(!pdf.color || pdf.color === 'black') ? 'selected' : ''} style="color: black;">Schwarz</option>
|
||||
<option value="red" ${pdf.color === 'red' ? 'selected' : ''} style="color: red;">Rot</option>
|
||||
<option value="green" ${pdf.color === 'green' ? 'selected' : ''} style="color: green;">Grün</option>
|
||||
<option value="blue" ${pdf.color === 'blue' ? 'selected' : ''} style="color: blue;">Blau</option>
|
||||
<option value="yellow" ${pdf.color === 'yellow' ? 'selected' : ''} style="color: #997700;">Gelb</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="px-4 py-3 whitespace-nowrap text-center">
|
||||
${ocrPreviewHtml}
|
||||
</td>
|
||||
<td class="px-4 py-3 whitespace-nowrap text-center" onclick="event.stopPropagation()">
|
||||
|
||||
@ -1,81 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Pitchprint\Form\Field;
|
||||
|
||||
use Plugin\Custom\PSC\Pitchprint\Form\Group\Pitchprint;
|
||||
use PSC\Shop\EntityBundle\Document\Shop;
|
||||
use PSC\System\PluginBundle\Form\Interfaces\Field;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
|
||||
class ShopSettings implements Field
|
||||
{
|
||||
|
||||
public function getTemplate()
|
||||
{
|
||||
return '@PluginCustomPSCPitchprint/form/field/ShopSettings.html.twig';
|
||||
}
|
||||
|
||||
public function getModule()
|
||||
{
|
||||
return Field::Shop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
<?php
|
||||
|
||||
namespace Plugin\Custom\PSC\Pitchprint\Form\Field;
|
||||
|
||||
use Plugin\Custom\PSC\Pitchprint\Form\Group\Pitchprint;
|
||||
use PSC\Shop\EntityBundle\Document\Shop;
|
||||
use PSC\System\PluginBundle\Form\Interfaces\Field;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
|
||||
class ShopSettings implements Field
|
||||
{
|
||||
public function getTemplate()
|
||||
{
|
||||
return '@PluginCustomPSCPitchprint/form/field/ShopSettings.html.twig';
|
||||
}
|
||||
|
||||
public function getModule()
|
||||
{
|
||||
return Field::Shop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function formPostSubmit(FormEvent $event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function formPostSetData(FormEvent $event)
|
||||
{
|
||||
/** @var Shop $data */
|
||||
$data = $event->getData();
|
||||
$event->getForm()->get('Pitchprint')->get('publicKey')->setData($data->getPluginSettingModule('pitchprint', 'publicKey'));
|
||||
$event->getForm()->get('Pitchprint')->get('secretKey')->setData($data->getPluginSettingModule('pitchprint', 'secretKey'));
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('publicKey', TextType::class, array(
|
||||
'label' => 'API Key',
|
||||
'required' => false,
|
||||
'mapped'=> false
|
||||
));
|
||||
$builder->add('secretKey', TextType::class, array(
|
||||
'label' => 'API Secret Key',
|
||||
'required' => false,
|
||||
'mapped'=> false
|
||||
));
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
public function getGroup()
|
||||
{
|
||||
return Pitchprint::GROUP_ID;
|
||||
}
|
||||
|
||||
public function formPreSubmit(FormEvent $event)
|
||||
{
|
||||
// TODO: Implement formPreSubmit() method.
|
||||
}
|
||||
|
||||
public function formPreSetData(FormEvent $event)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public function formPostSetData(FormEvent $event)
|
||||
{
|
||||
/** @var Shop $data */
|
||||
$data = $event->getData();
|
||||
$event
|
||||
->getForm()
|
||||
->get('Pitchprint')
|
||||
->get('publicKey')
|
||||
->setData($data->getPluginSettingModule('pitchprint', 'publicKey'));
|
||||
$event
|
||||
->getForm()
|
||||
->get('Pitchprint')
|
||||
->get('secretKey')
|
||||
->setData($data->getPluginSettingModule('pitchprint', 'secretKey'));
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('publicKey', TextType::class, array(
|
||||
'label' => 'API Key',
|
||||
'required' => false,
|
||||
'mapped' => false,
|
||||
));
|
||||
$builder->add('secretKey', TextType::class, array(
|
||||
'label' => 'API Secret Key',
|
||||
'required' => false,
|
||||
'mapped' => false,
|
||||
));
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
public function getGroup()
|
||||
{
|
||||
return Pitchprint::GROUP_ID;
|
||||
}
|
||||
|
||||
public function formPreSubmit(FormEvent $event)
|
||||
{
|
||||
// TODO: Implement formPreSubmit() method.
|
||||
}
|
||||
|
||||
public function formPreSetData(FormEvent $event)
|
||||
{
|
||||
}
|
||||
|
||||
public function formSubmit(FormEvent $event)
|
||||
{
|
||||
/** @var Shop $data */
|
||||
$data = $event->getData();
|
||||
$data->setPluginSettingModule('pitchprint', 'publicKey', $event->getForm()->get('Pitchprint')->get('publicKey')->getData());
|
||||
$data->setPluginSettingModule('pitchprint', 'secretKey', $event->getForm()->get('Pitchprint')->get('secretKey')->getData());
|
||||
|
||||
{
|
||||
/** @var Shop $data */
|
||||
$data = $event->getData();
|
||||
$data->setPluginSettingModule(
|
||||
'pitchprint',
|
||||
'publicKey',
|
||||
$event->getForm()->get('Pitchprint')->get('publicKey')->getData(),
|
||||
);
|
||||
$data->setPluginSettingModule(
|
||||
'pitchprint',
|
||||
'secretKey',
|
||||
$event->getForm()->get('Pitchprint')->get('secretKey')->getData(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,20 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Plugin\System\PSC\Invoice\Controller\Backend;
|
||||
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
|
||||
use Symfony\Bridge\Twig\Attribute\Template;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route('/index')]
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
#[Template('@PluginSystemPSCInvoiceControllerBackend/index/index.html.twig')]
|
||||
#[Template('@PluginSystemPSCInvoice/backend/index/index.html.twig')]
|
||||
#[IsGranted('ROLE_USER')]
|
||||
#[Route(path: '/create', name: 'psc_backend_invoice_index_create')]
|
||||
public function indexAction(JWTTokenManagerInterface $jwtManager)
|
||||
{
|
||||
return array('jwt' => $jwtManager->create($this->getUser()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
class OrderController extends AbstractController
|
||||
{
|
||||
#[Template('@PluginSystemPSCInvoice/backend/order/index.html.twig')]
|
||||
public function indexAction(null|\PSC\Shop\EntityBundle\Entity\Order $order, null|Order $orderDoc)
|
||||
public function indexAction(?\PSC\Shop\EntityBundle\Entity\Order $order, ?Order $orderDoc)
|
||||
{
|
||||
return ['uuid' => $order ? $order->getUuid() : false];
|
||||
}
|
||||
|
||||
@ -922,10 +922,6 @@ html {
|
||||
grid-column: span 2 / span 2;
|
||||
}
|
||||
|
||||
.col-span-3{
|
||||
grid-column: span 3 / span 3;
|
||||
}
|
||||
|
||||
.col-span-4{
|
||||
grid-column: span 4 / span 4;
|
||||
}
|
||||
@ -1863,6 +1859,11 @@ html {
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-red-600{
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-slate-100{
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(241 245 249 / var(--tw-bg-opacity));
|
||||
@ -2781,6 +2782,11 @@ html {
|
||||
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-red-700:hover{
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(185 28 28 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-white:hover{
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
@ -2831,6 +2837,11 @@ html {
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.hover\:text-yellow-700:hover{
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(161 98 7 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.hover\:underline:hover{
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
@ -3190,6 +3201,11 @@ html {
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
:is(.dark .dark\:text-yellow-500){
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(234 179 8 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder{
|
||||
--tw-placeholder-opacity: 1;
|
||||
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
|
||||
@ -3247,6 +3263,11 @@ html {
|
||||
background-color: rgb(88 25 19 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
:is(.dark .dark\:hover\:text-blue-400:hover){
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(96 165 250 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
:is(.dark .dark\:hover\:text-blue-500:hover){
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(59 130 246 / var(--tw-text-opacity));
|
||||
@ -3277,6 +3298,11 @@ html {
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
:is(.dark .dark\:hover\:text-yellow-400:hover){
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(250 204 21 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
:is(.dark .dark\:focus\:border-blue-500:focus){
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||
@ -3407,6 +3433,10 @@ html {
|
||||
width: 41.666667%;
|
||||
}
|
||||
|
||||
.md\:w-9\/12{
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.md\:w-fit{
|
||||
width: -moz-fit-content;
|
||||
width: fit-content;
|
||||
@ -3484,6 +3514,10 @@ html {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.lg\:grid-cols-3{
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.lg\:gap-8{
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user