update two-step ui/fix Warranty plugin bugs
This commit is contained in:
parent
d3bd560e36
commit
dd78e12a7a
|
@ -23,6 +23,7 @@ use App\Service\PluginService;
|
||||||
use App\Service\SMS;
|
use App\Service\SMS;
|
||||||
use App\Service\registryMGR;
|
use App\Service\registryMGR;
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
use App\Entity\StoreroomTicket;
|
||||||
|
|
||||||
class PlugWarrantyController extends AbstractController
|
class PlugWarrantyController extends AbstractController
|
||||||
{
|
{
|
||||||
|
@ -39,6 +40,66 @@ class PlugWarrantyController extends AbstractController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/api/plugins/warranty/serials/by-storeroom-ticket/{code}', name: 'plugin_warranty_serials_by_storeroom_ticket', methods: ['GET'])]
|
||||||
|
public function plugin_warranty_serials_by_storeroom_ticket(string $code, Request $request, Access $access, EntityManagerInterface $entityManager, PluginService $pluginService): JsonResponse
|
||||||
|
{
|
||||||
|
$acc = $access->hasRole('store');
|
||||||
|
if (!$acc) {
|
||||||
|
throw $this->createAccessDeniedException();
|
||||||
|
}
|
||||||
|
if (!$pluginService->isActive('warranty', $acc['bid'])) {
|
||||||
|
return $this->json(['success' => false, 'message' => 'افزونه گارانتی فعال نیست'], 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var StoreroomTicket|null $ticket */
|
||||||
|
$ticket = $entityManager->getRepository(StoreroomTicket::class)->findOneBy([
|
||||||
|
'bid' => $acc['bid'],
|
||||||
|
'code' => $code,
|
||||||
|
]);
|
||||||
|
if (!$ticket) {
|
||||||
|
return $this->json(['success' => false, 'message' => 'حواله یافت نشد'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$doc = $ticket->getDoc();
|
||||||
|
if (!$doc) {
|
||||||
|
return $this->json([
|
||||||
|
'success' => true,
|
||||||
|
'ticketActivationCode' => $ticket->getActivationCode(),
|
||||||
|
'items' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$serials = $entityManager->getRepository(PlugWarrantySerial::class)->createQueryBuilder('s')
|
||||||
|
->andWhere('s.business = :bid')
|
||||||
|
->andWhere('s.allocatedToDocumentId = :docId')
|
||||||
|
->setParameter('bid', $acc['bid'])
|
||||||
|
->setParameter('docId', $doc->getId())
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
$items = array_map(function (PlugWarrantySerial $s) use ($entityManager) {
|
||||||
|
$commodity = $s->getCommodity();
|
||||||
|
return [
|
||||||
|
'serialNumber' => $s->getSerialNumber(),
|
||||||
|
'commodity' => $commodity ? [
|
||||||
|
'id' => $commodity->getId(),
|
||||||
|
'name' => $commodity->getName(),
|
||||||
|
'code' => $commodity->getCode(),
|
||||||
|
] : null,
|
||||||
|
'status' => $s->getStatus(),
|
||||||
|
'activation' => $s->getActivation(),
|
||||||
|
'activationTicketCode' => $s->getActivationTicketCode(),
|
||||||
|
'warrantyEndDate' => $s->getWarrantyEndDate()?->format('Y-m-d'),
|
||||||
|
];
|
||||||
|
}, $serials);
|
||||||
|
|
||||||
|
return $this->json([
|
||||||
|
'success' => true,
|
||||||
|
'ticketActivationCode' => $ticket->getActivationCode(),
|
||||||
|
'items' => $items
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
private function expiredFlag(?\DateTimeImmutable $end): bool
|
private function expiredFlag(?\DateTimeImmutable $end): bool
|
||||||
{
|
{
|
||||||
return $end !== null && $end < new \DateTimeImmutable('today');
|
return $end !== null && $end < new \DateTimeImmutable('today');
|
||||||
|
@ -938,16 +999,18 @@ class PlugWarrantyController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/api/plugins/warranty/settings/get', name: 'plugin_warranty_settings_get', methods: ['GET'])]
|
#[Route('/api/plugins/warranty/settings/get', name: 'plugin_warranty_settings_get', methods: ['GET'])]
|
||||||
public function plugin_warranty_settings_get(Access $access, registryMGR $registryMGR): JsonResponse
|
public function plugin_warranty_settings_get(Access $access, registryMGR $registryMGR, EntityManagerInterface $entityManager): JsonResponse
|
||||||
{
|
{
|
||||||
$acc = $access->hasRole('plugWarrantyManager');
|
$acc = $access->hasRole('plugWarrantyManager');
|
||||||
if (!$acc) {
|
if (!$acc) {
|
||||||
throw $this->createAccessDeniedException();
|
throw $this->createAccessDeniedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$require = filter_var($registryMGR->get('warranty', 'requireWarrantyOnDelivery'), FILTER_VALIDATE_BOOLEAN);
|
$business = $entityManager->getRepository(Business::class)->find($acc['bid']);
|
||||||
$grace = (int) ($registryMGR->get('warranty', 'activationGraceDays') ?? 7);
|
|
||||||
$match = filter_var($registryMGR->get('warranty', 'matchWarrantyToSerial'), FILTER_VALIDATE_BOOLEAN);
|
$require = filter_var($business->getRequireWarrantyOnDelivery(), FILTER_VALIDATE_BOOLEAN);
|
||||||
|
$grace = (int) ($business->getActivationGraceDays() ?? 7);
|
||||||
|
$match = filter_var($business->getMatchWarrantyToSerial(), FILTER_VALIDATE_BOOLEAN);
|
||||||
return $this->json([
|
return $this->json([
|
||||||
'requireWarrantyOnDelivery' => (bool) $require,
|
'requireWarrantyOnDelivery' => (bool) $require,
|
||||||
'activationGraceDays' => max(0, $grace),
|
'activationGraceDays' => max(0, $grace),
|
||||||
|
@ -956,22 +1019,27 @@ class PlugWarrantyController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/api/plugins/warranty/settings/save', name: 'plugin_warranty_settings_save', methods: ['POST'])]
|
#[Route('/api/plugins/warranty/settings/save', name: 'plugin_warranty_settings_save', methods: ['POST'])]
|
||||||
public function plugin_warranty_settings_save(Request $request, Access $access, registryMGR $registryMGR): JsonResponse
|
public function plugin_warranty_settings_save(Request $request, Access $access, registryMGR $registryMGR, EntityManagerInterface $entityManager): JsonResponse
|
||||||
{
|
{
|
||||||
$acc = $access->hasRole('plugWarrantyManager');
|
$acc = $access->hasRole('plugWarrantyManager');
|
||||||
if (!$acc) {
|
if (!$acc) {
|
||||||
throw $this->createAccessDeniedException();
|
throw $this->createAccessDeniedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$business = $entityManager->getRepository(Business::class)->find($acc['bid']);
|
||||||
|
|
||||||
$params = json_decode($request->getContent() ?: '{}', true);
|
$params = json_decode($request->getContent() ?: '{}', true);
|
||||||
$require = isset($params['requireWarrantyOnDelivery']) && ($params['requireWarrantyOnDelivery'] === true || $params['requireWarrantyOnDelivery'] === '1' || $params['requireWarrantyOnDelivery'] === 1 || $params['requireWarrantyOnDelivery'] === 'true');
|
$require = isset($params['requireWarrantyOnDelivery']) && ($params['requireWarrantyOnDelivery'] === true || $params['requireWarrantyOnDelivery'] === '1' || $params['requireWarrantyOnDelivery'] === 1 || $params['requireWarrantyOnDelivery'] === 'true');
|
||||||
$graceDays = isset($params['activationGraceDays']) ? (int) $params['activationGraceDays'] : 7;
|
$graceDays = isset($params['activationGraceDays']) ? (int) $params['activationGraceDays'] : 7;
|
||||||
if ($graceDays < 0) { $graceDays = 0; }
|
if ($graceDays < 0) { $graceDays = 0; }
|
||||||
$match = isset($params['matchWarrantyToSerial']) && ($params['matchWarrantyToSerial'] === true || $params['matchWarrantyToSerial'] === '1' || $params['matchWarrantyToSerial'] === 1 || $params['matchWarrantyToSerial'] === 'true');
|
$match = isset($params['matchWarrantyToSerial']) && ($params['matchWarrantyToSerial'] === true || $params['matchWarrantyToSerial'] === '1' || $params['matchWarrantyToSerial'] === 1 || $params['matchWarrantyToSerial'] === 'true');
|
||||||
|
|
||||||
$registryMGR->update('warranty', 'requireWarrantyOnDelivery', $require ? '1' : '0');
|
$business->setRequireWarrantyOnDelivery($require);
|
||||||
$registryMGR->update('warranty', 'activationGraceDays', (string) $graceDays);
|
$business->setActivationGraceDays($graceDays);
|
||||||
$registryMGR->update('warranty', 'matchWarrantyToSerial', $match ? '1' : '0');
|
$business->setMatchWarrantyToSerial($match);
|
||||||
|
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
return $this->json(['success' => true]);
|
return $this->json(['success' => true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -325,6 +325,15 @@ class Business
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
private ?string $financialApprover = null;
|
private ?string $financialApprover = null;
|
||||||
|
|
||||||
|
#[ORM\Column(nullable: true)]
|
||||||
|
private ?bool $requireWarrantyOnDelivery = null;
|
||||||
|
|
||||||
|
#[ORM\Column(nullable: true)]
|
||||||
|
private ?int $activationGraceDays = null;
|
||||||
|
|
||||||
|
#[ORM\Column(nullable: true)]
|
||||||
|
private ?bool $matchWarrantyToSerial = null;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->logs = new ArrayCollection();
|
$this->logs = new ArrayCollection();
|
||||||
|
@ -2254,4 +2263,37 @@ class Business
|
||||||
$this->financialApprover = $financialApprover;
|
$this->financialApprover = $financialApprover;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public function getRequireWarrantyOnDelivery(): ?bool
|
||||||
|
{
|
||||||
|
return $this->requireWarrantyOnDelivery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRequireWarrantyOnDelivery(?bool $requireWarrantyOnDelivery): static
|
||||||
|
{
|
||||||
|
$this->requireWarrantyOnDelivery = $requireWarrantyOnDelivery;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getActivationGraceDays(): ?int
|
||||||
|
{
|
||||||
|
return $this->activationGraceDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setActivationGraceDays(?int $activationGraceDays): static
|
||||||
|
{
|
||||||
|
$this->activationGraceDays = $activationGraceDays;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMatchWarrantyToSerial(): ?bool
|
||||||
|
{
|
||||||
|
return $this->matchWarrantyToSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMatchWarrantyToSerial(?bool $matchWarrantyToSerial): static
|
||||||
|
{
|
||||||
|
$this->matchWarrantyToSerial = $matchWarrantyToSerial;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -310,142 +310,126 @@
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
<!-- بخش کالا و خدمات -->
|
<!-- تایید دومرحلهای -->
|
||||||
|
<v-card v-if="isPluginActive('accpro')" variant="outlined" class="mb-6">
|
||||||
<h3 class="text-primary mt-4" v-if="isPluginActive('accpro')">تایید دومرحلهای</h3>
|
<v-card-title class="text-h6 text-primary">
|
||||||
<v-row v-if="isPluginActive('accpro')">
|
<v-icon icon="mdi-shield-check" class="mr-2"></v-icon>
|
||||||
<v-col cols="12">
|
تایید دومرحلهای
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
<v-switch
|
<v-switch
|
||||||
v-model="content.requireTwoStepApproval"
|
v-model="content.requireTwoStepApproval"
|
||||||
label="فعالسازی تایید دومرحلهای برای اسناد"
|
label="فعالسازی تایید دومرحلهای برای اسناد"
|
||||||
color="primary"
|
color="primary"
|
||||||
hide-details
|
hide-details
|
||||||
|
class="mb-2"
|
||||||
></v-switch>
|
></v-switch>
|
||||||
<div class="text-caption text-medium-emphasis mt-1">
|
<div class="text-body-2 text-medium-emphasis mb-2">
|
||||||
با فعالسازی این گزینه، تمام فاکتورها، حوالههای انبار، دریافتها و پرداختها نیاز به تایید مدیر خواهند داشت.
|
با فعالسازی این گزینه، تمام فاکتورها، حوالههای انبار، دریافتها و پرداختها نیاز به تایید مدیر خواهند داشت.
|
||||||
</div>
|
</div>
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<!-- تنظیمات تاییدکنندگان -->
|
<v-expand-transition>
|
||||||
<v-row v-if="content.requireTwoStepApproval && isPluginActive('accpro')">
|
<div v-if="content.requireTwoStepApproval">
|
||||||
<v-col cols="12">
|
<v-divider class="my-4"></v-divider>
|
||||||
<v-card variant="outlined" class="pa-4">
|
<h4 class="text-subtitle-1 mb-3">تعیین تاییدکنندگان</h4>
|
||||||
<h4 class="text-subtitle-1 mb-3">تعیین تاییدکنندگان</h4>
|
<v-row>
|
||||||
|
<v-col cols="12">
|
||||||
<!-- تاییدکننده فاکتور فروش -->
|
<v-select
|
||||||
<div class="mb-4">
|
v-model="content.invoiceApprover"
|
||||||
<v-select
|
:items="users"
|
||||||
v-model="content.invoiceApprover"
|
item-title="name"
|
||||||
:items="users"
|
item-value="email"
|
||||||
item-title="name"
|
label="تاییدکننده فاکتور فروش"
|
||||||
item-value="email"
|
variant="outlined"
|
||||||
label="تاییدکننده فاکتور فروش"
|
density="compact"
|
||||||
variant="outlined"
|
clearable
|
||||||
density="compact"
|
hint="کاربری که میتواند فاکتورهای فروش را تایید کند"
|
||||||
clearable
|
persistent-hint
|
||||||
hint="کاربری که میتواند فاکتورهای فروش را تایید کند"
|
>
|
||||||
persistent-hint
|
<template v-slot:item="{ item, props }">
|
||||||
>
|
<v-list-item v-bind="props">
|
||||||
<template v-slot:item="{ item, props }">
|
<template v-slot:prepend>
|
||||||
<v-list-item v-bind="props">
|
<v-icon
|
||||||
<template v-slot:prepend>
|
:color="item.owner ? 'success' : 'primary'"
|
||||||
<v-icon
|
size="small"
|
||||||
:color="item.owner ? 'success' : 'primary'"
|
>
|
||||||
size="small"
|
{{ item.owner ? 'mdi-crown' : 'mdi-account' }}
|
||||||
>
|
</v-icon>
|
||||||
{{ item.owner ? 'mdi-crown' : 'mdi-account' }}
|
</template>
|
||||||
</v-icon>
|
<v-list-item-title>{{ item.name }}</v-list-item-title>
|
||||||
|
<v-list-item-subtitle>{{ item.email }}</v-list-item-subtitle>
|
||||||
|
</v-list-item>
|
||||||
</template>
|
</template>
|
||||||
<v-list-item-title>{{ item.name }}</v-list-item-title>
|
</v-select>
|
||||||
<v-list-item-subtitle>{{ item.email }}</v-list-item-subtitle>
|
<div class="text-caption text-medium-emphasis mt-1">
|
||||||
</v-list-item>
|
این کاربر افزون بر مدیر کسب و کار میتواند فاکتورهای فروش را تایید کند
|
||||||
</template>
|
</div>
|
||||||
</v-select>
|
</v-col>
|
||||||
<div class="text-caption text-medium-emphasis mt-1">
|
|
||||||
این کاربر افزون بر مدیر کسب و کار میتواند فاکتورهای فروش را تایید کند
|
<v-col cols="12">
|
||||||
|
<v-select
|
||||||
|
v-model="content.warehouseApprover"
|
||||||
|
:items="users"
|
||||||
|
item-title="name"
|
||||||
|
item-value="email"
|
||||||
|
label="تاییدکننده حواله انبار"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
clearable
|
||||||
|
hint="کاربری که میتواند حوالههای انبار را تایید کند"
|
||||||
|
persistent-hint
|
||||||
|
>
|
||||||
|
<template v-slot:item="{ item, props }">
|
||||||
|
<v-list-item v-bind="props">
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<v-icon
|
||||||
|
:color="item.owner ? 'success' : 'primary'"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
{{ item.owner ? 'mdi-crown' : 'mdi-account' }}
|
||||||
|
</v-icon>
|
||||||
|
</template>
|
||||||
|
<v-list-item-title>{{ item.name }}</v-list-item-title>
|
||||||
|
<v-list-item-subtitle>{{ item.email }}</v-list-item-subtitle>
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
</v-select>
|
||||||
|
<div class="text-caption text-medium-emphasis mt-1">
|
||||||
|
این کاربر افزون بر مدیر کسب و کار میتواند حوالههای انبار را تایید کند
|
||||||
|
</div>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<!-- تاییدکننده دریافت و پرداخت مالی (غیرفعال فعلاً) -->
|
||||||
|
<!--
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-select
|
||||||
|
v-model="content.financialApprover"
|
||||||
|
:items="users"
|
||||||
|
item-title="name"
|
||||||
|
item-value="email"
|
||||||
|
label="تاییدکننده دریافت و پرداخت مالی"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
clearable
|
||||||
|
hint="کاربری که میتواند دریافتها و پرداختها را تایید کند"
|
||||||
|
persistent-hint
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
-->
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<div class="text-caption text-medium-emphasis">
|
||||||
|
<v-icon size="small" color="info" class="me-1">mdi-information</v-icon>
|
||||||
|
در صورت عدم انتخاب تاییدکننده، فقط مدیر کسب و کار میتواند اسناد را تایید کند
|
||||||
|
</div>
|
||||||
|
<div class="text-caption text-medium-emphasis mt-2">
|
||||||
|
<v-icon size="small" color="success" class="me-1">mdi-check-circle</v-icon>
|
||||||
|
<strong>نکته:</strong> صاحب کسب و کار همیشه میتواند تمام اسناد را تأیید کند و نیازی به تعیین مجدد ندارد
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</v-expand-transition>
|
||||||
<!-- تاییدکننده حواله انبار -->
|
</v-card-text>
|
||||||
<div class="mb-4">
|
</v-card>
|
||||||
<v-select
|
|
||||||
v-model="content.warehouseApprover"
|
|
||||||
:items="users"
|
|
||||||
item-title="name"
|
|
||||||
item-value="email"
|
|
||||||
label="تاییدکننده حواله انبار"
|
|
||||||
variant="outlined"
|
|
||||||
density="compact"
|
|
||||||
clearable
|
|
||||||
hint="کاربری که میتواند حوالههای انبار را تایید کند"
|
|
||||||
persistent-hint
|
|
||||||
>
|
|
||||||
<template v-slot:item="{ item, props }">
|
|
||||||
<v-list-item v-bind="props">
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<v-icon
|
|
||||||
:color="item.owner ? 'success' : 'primary'"
|
|
||||||
size="small"
|
|
||||||
>
|
|
||||||
{{ item.owner ? 'mdi-crown' : 'mdi-account' }}
|
|
||||||
</v-icon>
|
|
||||||
</template>
|
|
||||||
<v-list-item-title>{{ item.name }}</v-list-item-title>
|
|
||||||
<v-list-item-subtitle>{{ item.email }}</v-list-item-subtitle>
|
|
||||||
</v-list-item>
|
|
||||||
</template>
|
|
||||||
</v-select>
|
|
||||||
<div class="text-caption text-medium-emphasis mt-1">
|
|
||||||
این کاربر افزون بر مدیر کسب و کار میتواند حوالههای انبار را تایید کند
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- تاییدکننده دریافت و پرداخت مالی -->
|
|
||||||
<!-- <div class="mb-4">
|
|
||||||
<v-select
|
|
||||||
v-model="content.financialApprover"
|
|
||||||
:items="users"
|
|
||||||
item-title="name"
|
|
||||||
item-value="email"
|
|
||||||
label="تاییدکننده دریافت و پرداخت مالی"
|
|
||||||
variant="outlined"
|
|
||||||
density="compact"
|
|
||||||
clearable
|
|
||||||
hint="کاربری که میتواند دریافتها و پرداختها را تایید کند"
|
|
||||||
persistent-hint
|
|
||||||
>
|
|
||||||
<template v-slot:item="{ item, props }">
|
|
||||||
<v-list-item v-bind="props">
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<v-icon
|
|
||||||
:color="item.owner ? 'success' : 'primary'"
|
|
||||||
size="small"
|
|
||||||
>
|
|
||||||
{{ item.owner ? 'mdi-crown' : 'mdi-account' }}
|
|
||||||
</v-icon>
|
|
||||||
</template>
|
|
||||||
<v-list-item-title>{{ item.name }}</v-list-item-title>
|
|
||||||
<v-list-item-subtitle>{{ item.email }}</v-list-item-subtitle>
|
|
||||||
</v-list-item>
|
|
||||||
</template>
|
|
||||||
</v-select>
|
|
||||||
<div class="text-caption text-medium-emphasis mt-1">
|
|
||||||
این کاربر افزون بر مدیر کسب و کار میتواند دریافتها و پرداختها را تایید کند
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<div class="text-caption text-medium-emphasis">
|
|
||||||
<v-icon size="small" color="info" class="me-1">mdi-information</v-icon>
|
|
||||||
در صورت عدم انتخاب تاییدکننده، فقط مدیر کسب و کار میتواند اسناد را تایید کند
|
|
||||||
</div>
|
|
||||||
<div class="text-caption text-medium-emphasis mt-2">
|
|
||||||
<v-icon size="small" color="success" class="me-1">mdi-check-circle</v-icon>
|
|
||||||
<strong>نکته:</strong> صاحب کسب و کار همیشه میتواند تمام اسناد را تأیید کند و نیازی به تعیین مجدد ندارد
|
|
||||||
</div>
|
|
||||||
</v-card>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<v-card variant="outlined">
|
<v-card variant="outlined">
|
||||||
<v-card-title class="text-h6 text-primary">
|
<v-card-title class="text-h6 text-primary">
|
||||||
|
|
|
@ -63,6 +63,8 @@ interface Item {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const bid = ref<Business>({ legal_name: '' })
|
const bid = ref<Business>({ legal_name: '' })
|
||||||
|
const warrantySerials = ref<any[]>([])
|
||||||
|
const ticketActivationCode = ref<string | null>(null)
|
||||||
const item = ref<Item>({
|
const item = ref<Item>({
|
||||||
ticket: {
|
ticket: {
|
||||||
id: 0,
|
id: 0,
|
||||||
|
@ -103,9 +105,10 @@ const headers = [
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const [ticketResponse, businessResponse] = await Promise.all([
|
const [ticketResponse, businessResponse, warrantyResponse] = await Promise.all([
|
||||||
axios.post(`/api/storeroom/tickets/info/${router.currentRoute.value.params.id}`),
|
axios.post(`/api/storeroom/tickets/info/${router.currentRoute.value.params.id}`),
|
||||||
axios.post(`/api/business/get/info/${localStorage.getItem('activeBid')}`)
|
axios.post(`/api/business/get/info/${localStorage.getItem('activeBid')}`),
|
||||||
|
axios.get(`/api/plugins/warranty/serials/by-storeroom-ticket/${router.currentRoute.value.params.id}`)
|
||||||
])
|
])
|
||||||
|
|
||||||
item.value.ticket = ticketResponse.data.ticket
|
item.value.ticket = ticketResponse.data.ticket
|
||||||
|
@ -114,6 +117,10 @@ const loadData = async () => {
|
||||||
item.value.rows = ticketResponse.data.commodities
|
item.value.rows = ticketResponse.data.commodities
|
||||||
|
|
||||||
bid.value = businessResponse.data
|
bid.value = businessResponse.data
|
||||||
|
|
||||||
|
// warranty data
|
||||||
|
warrantySerials.value = (warrantyResponse.data && warrantyResponse.data.items) ? warrantyResponse.data.items : []
|
||||||
|
ticketActivationCode.value = warrantyResponse.data ? (warrantyResponse.data.ticketActivationCode || null) : null
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading data:', error)
|
console.error('Error loading data:', error)
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -133,6 +140,50 @@ const printInvoice = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getStatusColor = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'available': return 'success'
|
||||||
|
case 'allocated': return 'info'
|
||||||
|
case 'verified': return 'primary'
|
||||||
|
case 'bound': return 'warning'
|
||||||
|
case 'consumed': return 'teal'
|
||||||
|
case 'void': return 'grey'
|
||||||
|
case 'active': return 'success'
|
||||||
|
case 'deactive': return 'error'
|
||||||
|
default: return 'grey'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusText = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'available': return 'آزاد'
|
||||||
|
case 'allocated': return 'تخصیص یافته'
|
||||||
|
case 'verified': return 'تأیید شده'
|
||||||
|
case 'bound': return 'متصل'
|
||||||
|
case 'consumed': return 'مصرف شده'
|
||||||
|
case 'void': return 'باطل'
|
||||||
|
case 'active': return 'فعال'
|
||||||
|
case 'deactive': return 'فعال نشده'
|
||||||
|
default: return 'نامشخص'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatDate = (dateVal: any) => {
|
||||||
|
if (!dateVal) return '-'
|
||||||
|
try {
|
||||||
|
const d = typeof dateVal === 'string' ? new Date(dateVal) : dateVal
|
||||||
|
const valid = d instanceof Date && !isNaN(d.getTime())
|
||||||
|
if (!valid) return '-'
|
||||||
|
const j = moment(d)
|
||||||
|
const y = j.jYear()
|
||||||
|
const m = j.jMonth() + 1
|
||||||
|
const day = j.jDate()
|
||||||
|
return `${y}/${String(m).padStart(2, '0')}/${String(day).padStart(2, '0')}`
|
||||||
|
} catch {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attachments
|
// Attachments
|
||||||
const attachments = ref<any[]>([])
|
const attachments = ref<any[]>([])
|
||||||
const loadingAttachments = ref(false)
|
const loadingAttachments = ref(false)
|
||||||
|
@ -417,8 +468,8 @@ onMounted(() => {
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:items="item.rows"
|
:items="item.rows"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
class="elevation-1 text-center"
|
class="elevation-1 text-center"
|
||||||
:header-props="{ class: 'custom-header' }"
|
:header-props="{ class: 'custom-header' }"
|
||||||
density="compact"
|
density="compact"
|
||||||
show-expand
|
show-expand
|
||||||
>
|
>
|
||||||
|
@ -442,6 +493,59 @@ onMounted(() => {
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
|
<!-- Warranty Section -->
|
||||||
|
<v-card variant="outlined" class="mt-4">
|
||||||
|
<v-card-title class="text-subtitle-1 font-weight-bold">
|
||||||
|
<v-icon start>mdi-shield-check</v-icon>
|
||||||
|
گارانتیهای حواله و کد فعالسازی
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-row class="mb-2">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
:model-value="ticketActivationCode || '—'"
|
||||||
|
label="کد فعالسازی حواله"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
readonly
|
||||||
|
prepend-inner-icon="mdi-key-variant"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-data-table
|
||||||
|
:headers="[
|
||||||
|
{ title: 'سریال گارانتی', key: 'serialNumber' },
|
||||||
|
{ title: 'کالا', key: 'commodity' },
|
||||||
|
{ title: 'وضعیت', key: 'status' },
|
||||||
|
{ title: 'فعالسازی', key: 'activation' },
|
||||||
|
// { title: 'کد فعالسازی', key: 'activationTicketCode' },
|
||||||
|
{ title: 'اتمام گارانتی', key: 'warrantyEndDate' }
|
||||||
|
]"
|
||||||
|
:items="warrantySerials"
|
||||||
|
density="compact"
|
||||||
|
class="elevation-1"
|
||||||
|
:loading="loading"
|
||||||
|
>
|
||||||
|
<template #item.commodity="{ item }">
|
||||||
|
<span v-if="item.commodity">{{ item.commodity.code }} {{ item.commodity.name }}</span>
|
||||||
|
<span v-else>—</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #item.status="{ item }">
|
||||||
|
<v-chip :color="getStatusColor(item.status)" size="small">{{ getStatusText(item.status) }}</v-chip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #item.activation="{ item }">
|
||||||
|
<v-chip :color="getStatusColor(item.activation)" size="small">{{ getStatusText(item.activation) }}</v-chip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #item.warrantyEndDate="{ item }">
|
||||||
|
<span>{{ formatDate(item.warrantyEndDate) }}</span>
|
||||||
|
</template>
|
||||||
|
</v-data-table>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
<v-card variant="outlined" class="mt-4" :class="{ 'opacity-50': isAttachmentsDisabled }">
|
<v-card variant="outlined" class="mt-4" :class="{ 'opacity-50': isAttachmentsDisabled }">
|
||||||
<v-card-title class="text-subtitle-1 font-weight-bold">
|
<v-card-title class="text-subtitle-1 font-weight-bold">
|
||||||
<v-icon start>mdi-paperclip</v-icon>
|
<v-icon start>mdi-paperclip</v-icon>
|
||||||
|
|
Loading…
Reference in a new issue