almost finish preinvoice and cheque parts
This commit is contained in:
parent
9bc3a27ce2
commit
c630bc7dca
|
@ -92,3 +92,6 @@ services:
|
||||||
Printers:
|
Printers:
|
||||||
class: App\Service\Printers
|
class: App\Service\Printers
|
||||||
arguments: [ '@doctrine.orm.entity_manager' ]
|
arguments: [ '@doctrine.orm.entity_manager' ]
|
||||||
|
|
||||||
|
App\Twig\NumberFormatExtension:
|
||||||
|
tags: ['twig.extension']
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Entity\PreInvoiceDoc;
|
|
||||||
use App\Service\Log;
|
use App\Service\Log;
|
||||||
use App\Service\Access;
|
use App\Service\Access;
|
||||||
use App\Service\Explore;
|
use App\Service\Explore;
|
||||||
|
@ -10,8 +9,8 @@ use App\Entity\Commodity;
|
||||||
use App\Service\PluginService;
|
use App\Service\PluginService;
|
||||||
use App\Service\Provider;
|
use App\Service\Provider;
|
||||||
use App\Service\Extractor;
|
use App\Service\Extractor;
|
||||||
use App\Entity\HesabdariDoc;
|
use App\Entity\PreInvoiceDoc;
|
||||||
use App\Entity\HesabdariRow;
|
use App\Entity\PreInvoiceItem;
|
||||||
use App\Entity\HesabdariTable;
|
use App\Entity\HesabdariTable;
|
||||||
use App\Entity\InvoiceType;
|
use App\Entity\InvoiceType;
|
||||||
use App\Entity\Person;
|
use App\Entity\Person;
|
||||||
|
@ -29,524 +28,282 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
|
||||||
class PreinvoiceController extends AbstractController
|
class PreinvoiceController extends AbstractController
|
||||||
{
|
{
|
||||||
|
|
||||||
#[Route('/api/presell/get/info/{code}', name: 'app_sell_get_info')]
|
private $access;
|
||||||
public function app_sell_get_info(Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, string $code): JsonResponse
|
private $extractor;
|
||||||
|
|
||||||
|
public function __construct(Access $access, Extractor $extractor)
|
||||||
{
|
{
|
||||||
$acc = $access->hasRole('sell');
|
$this->access = $access;
|
||||||
if (!$acc)
|
$this->extractor = $extractor;
|
||||||
throw $this->createAccessDeniedException();
|
|
||||||
$doc = $entityManager->getRepository(PreInvoiceDoc::class)->findOneBy([
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'code' => $code,
|
|
||||||
'money'=> $acc['money']
|
|
||||||
]);
|
|
||||||
if (!$doc)
|
|
||||||
throw $this->createNotFoundException();
|
|
||||||
$result = Explore::ExploreSellDoc($doc);
|
|
||||||
$profit = 0;
|
|
||||||
//calculate profit
|
|
||||||
foreach ($doc->getHesabdariRows() as $item) {
|
|
||||||
if ($item->getCommodity() && $item->getCommdityCount()) {
|
|
||||||
if ($acc['bid']->getProfitCalctype() == 'simple') {
|
|
||||||
$profit = $profit + (($item->getCommodity()->getPriceSell() - $item->getCommodity()->getPriceSell()) * $item->getCommdityCount());
|
|
||||||
}
|
|
||||||
elseif ($acc['bid']->getProfitCalctype() == 'lis') {
|
|
||||||
$last = $entityManager->getRepository(HesabdariRow::class)->findOneBy([
|
|
||||||
'commodity' => $item->getCommodity(),
|
|
||||||
'bs' => 0
|
|
||||||
], [
|
|
||||||
'id' => 'DESC'
|
|
||||||
]);
|
|
||||||
if ($last) {
|
|
||||||
$price = $last->getBd() / $last->getCommdityCount();
|
|
||||||
$profit = $profit + ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount());
|
|
||||||
} else {
|
|
||||||
$profit = $profit + $item->getBs();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$lasts = $entityManager->getRepository(HesabdariRow::class)->findBy([
|
|
||||||
'commodity' => $item->getCommodity(),
|
|
||||||
'bs' => 0
|
|
||||||
], [
|
|
||||||
'id' => 'DESC'
|
|
||||||
]);
|
|
||||||
$avg = 0;
|
|
||||||
$count = 0;
|
|
||||||
foreach ($lasts as $last) {
|
|
||||||
$avg = $avg + $last->getBd();
|
|
||||||
$count = $count + $last->getCommdityCount();
|
|
||||||
}
|
|
||||||
if ($count != 0) {
|
|
||||||
$price = $avg / $count;
|
|
||||||
$profit = $profit + ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
$profit = $profit + $item->getBs();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//round output
|
|
||||||
$profit = round($profit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$result['profit'] = $profit;
|
|
||||||
return $this->json($result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/api/presell/mod', name: 'app_sell_mod')]
|
|
||||||
public function app_sell_mod(registryMGR $registryMGR, PluginService $pluginService, SMS $SMS, Provider $provider, Extractor $extractor, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager): JsonResponse
|
#[Route('/api/preinvoice/get/{id}', name: 'app_preinvoice_get')]
|
||||||
|
public function getPreinvoice(EntityManagerInterface $entityManager, int $id): JsonResponse
|
||||||
{
|
{
|
||||||
$params = [];
|
$acc = $this->access->hasRole('preinvoice');
|
||||||
if ($content = $request->getContent()) {
|
if (!$acc) {
|
||||||
$params = json_decode($content, true);
|
return new JsonResponse($this->extractor->operationFail('دسترسی ندارید'), 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
$acc = $access->hasRole('sell');
|
$preinvoice = $entityManager->getRepository(PreInvoiceDoc::class)->findOneBy(['code' => $id, 'bid' => $acc['bid'], 'year' => $acc['year']]);
|
||||||
if (!$acc)
|
if (!$preinvoice) {
|
||||||
throw $this->createAccessDeniedException();
|
return new JsonResponse(['error' => 'پیش فاکتور یافت نشد'], 404);
|
||||||
|
|
||||||
if (!array_key_exists('update', $params)) {
|
|
||||||
return $this->json($extractor->paramsNotSend());
|
|
||||||
}
|
}
|
||||||
if ($params['update'] != '') {
|
|
||||||
$doc = $entityManager->getRepository(HesabdariDoc::class)->findOneBy([
|
$data = [
|
||||||
'bid' => $acc['bid'],
|
'id' => $preinvoice->getId(),
|
||||||
'year' => $acc['year'],
|
'code' => $preinvoice->getCode(),
|
||||||
'code' => $params['update'],
|
'date' => $preinvoice->getDate(),
|
||||||
'money'=> $acc['money']
|
'des' => $preinvoice->getDes(),
|
||||||
]);
|
'person' => Explore::ExplorePerson($preinvoice->getPerson()),
|
||||||
if (!$doc)
|
'amount' => $preinvoice->getAmount(),
|
||||||
return $this->json($extractor->notFound());
|
'taxPercent' => $preinvoice->getTaxPercent(),
|
||||||
|
'totalDiscount' => $preinvoice->getTotalDiscount(),
|
||||||
$rows = $doc->getHesabdariRows();
|
'totalDiscountPercent' => $preinvoice->getTotalDiscountPercent(),
|
||||||
foreach ($rows as $row)
|
'shippingCost' => $preinvoice->getShippingCost(),
|
||||||
$entityManager->remove($row);
|
'showPercentDiscount' => $preinvoice->isShowPercentDiscount(),
|
||||||
} else {
|
'showTotalPercentDiscount' => $preinvoice->isShowTotalPercentDiscount(),
|
||||||
$doc = new HesabdariDoc();
|
'items' => array_map(function($item) {
|
||||||
$doc->setBid($acc['bid']);
|
return [
|
||||||
$doc->setYear($acc['year']);
|
'id' => $item->getId(),
|
||||||
$doc->setDateSubmit(time());
|
'commodity' => [
|
||||||
$doc->setType('sell');
|
'id' => $item->getCommodity()->getId(),
|
||||||
$doc->setSubmitter($this->getUser());
|
'name' => $item->getCommodity()->getName()
|
||||||
$doc->setMoney($acc['money']);
|
],
|
||||||
$doc->setCode($provider->getAccountingCode($acc['bid'], 'accounting'));
|
'count' => $item->getCommodityCount(),
|
||||||
}
|
'price' => $item->getBs(),
|
||||||
if ($params['transferCost'] != 0) {
|
'discountPercent' => $item->getDiscountPercent(),
|
||||||
$hesabdariRow = new HesabdariRow();
|
'discountAmount' => $item->getDiscountAmount(),
|
||||||
$hesabdariRow->setDes('حمل و نقل کالا');
|
'description' => $item->getDes(),
|
||||||
$hesabdariRow->setBid($acc['bid']);
|
'showPercentDiscount' => $item->isShowPercentDiscount()
|
||||||
$hesabdariRow->setYear($acc['year']);
|
|
||||||
$hesabdariRow->setDoc($doc);
|
|
||||||
$hesabdariRow->setBs($params['transferCost']);
|
|
||||||
$hesabdariRow->setBd(0);
|
|
||||||
$ref = $entityManager->getRepository(HesabdariTable::class)->findOneBy([
|
|
||||||
'code' => '61' // transfer cost income
|
|
||||||
]);
|
|
||||||
$hesabdariRow->setRef($ref);
|
|
||||||
$entityManager->persist($hesabdariRow);
|
|
||||||
}
|
|
||||||
if ($params['discountAll'] != 0) {
|
|
||||||
$hesabdariRow = new HesabdariRow();
|
|
||||||
$hesabdariRow->setDes('تخفیف فاکتور');
|
|
||||||
$hesabdariRow->setBid($acc['bid']);
|
|
||||||
$hesabdariRow->setYear($acc['year']);
|
|
||||||
$hesabdariRow->setDoc($doc);
|
|
||||||
$hesabdariRow->setBs(0);
|
|
||||||
$hesabdariRow->setBd($params['discountAll']);
|
|
||||||
$ref = $entityManager->getRepository(HesabdariTable::class)->findOneBy([
|
|
||||||
'code' => '104' // سایر هزینه های پخش و فروش
|
|
||||||
]);
|
|
||||||
$hesabdariRow->setRef($ref);
|
|
||||||
$entityManager->persist($hesabdariRow);
|
|
||||||
}
|
|
||||||
$doc->setDes($params['des']);
|
|
||||||
$doc->setDate($params['date']);
|
|
||||||
$sumTax = 0;
|
|
||||||
$sumTotal = 0;
|
|
||||||
foreach ($params['rows'] as $row) {
|
|
||||||
$sumTax += $row['tax'];
|
|
||||||
$sumTotal += $row['sumWithoutTax'];
|
|
||||||
$hesabdariRow = new HesabdariRow();
|
|
||||||
$hesabdariRow->setDes($row['des']);
|
|
||||||
$hesabdariRow->setBid($acc['bid']);
|
|
||||||
$hesabdariRow->setYear($acc['year']);
|
|
||||||
$hesabdariRow->setDoc($doc);
|
|
||||||
$hesabdariRow->setBs($row['sumWithoutTax'] + $row['tax']);
|
|
||||||
$hesabdariRow->setBd(0);
|
|
||||||
$hesabdariRow->setDiscount($row['discount']);
|
|
||||||
$hesabdariRow->setTax($row['tax']);
|
|
||||||
$ref = $entityManager->getRepository(HesabdariTable::class)->findOneBy([
|
|
||||||
'code' => '53' // sell commodity
|
|
||||||
]);
|
|
||||||
$hesabdariRow->setRef($ref);
|
|
||||||
$row['count'] = str_replace(',', '', $row['count']);
|
|
||||||
$commodity = $entityManager->getRepository(Commodity::class)->findOneBy([
|
|
||||||
'id' => $row['commodity']['id'],
|
|
||||||
'bid' => $acc['bid']
|
|
||||||
]);
|
|
||||||
if (!$commodity)
|
|
||||||
return $this->json($extractor->paramsNotSend());
|
|
||||||
$hesabdariRow->setCommodity($commodity);
|
|
||||||
$hesabdariRow->setCommdityCount($row['count']);
|
|
||||||
$entityManager->persist($hesabdariRow);
|
|
||||||
|
|
||||||
//update commodity price for auto update price option
|
|
||||||
if ($acc['bid']->isCommodityUpdateSellPriceAuto() == true && $commodity->getPriceSell() != $row['price']) {
|
|
||||||
$commodity->setPriceSell($row['price']);
|
|
||||||
$entityManager->persist($commodity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//set amount of document
|
|
||||||
$doc->setAmount($sumTax + $sumTotal - $params['discountAll'] + $params['transferCost']);
|
|
||||||
//set person person
|
|
||||||
$hesabdariRow = new HesabdariRow();
|
|
||||||
$hesabdariRow->setDes('فاکتور فروش');
|
|
||||||
$hesabdariRow->setBid($acc['bid']);
|
|
||||||
$hesabdariRow->setYear($acc['year']);
|
|
||||||
$hesabdariRow->setDoc($doc);
|
|
||||||
$hesabdariRow->setBs(0);
|
|
||||||
$hesabdariRow->setBd($sumTax + $sumTotal + $params['transferCost'] - $params['discountAll']);
|
|
||||||
$ref = $entityManager->getRepository(HesabdariTable::class)->findOneBy([
|
|
||||||
'code' => '3' // persons
|
|
||||||
]);
|
|
||||||
$hesabdariRow->setRef($ref);
|
|
||||||
$person = $entityManager->getRepository(Person::class)->findOneBy([
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'code' => $params['person']['code']
|
|
||||||
]);
|
|
||||||
if (!$person)
|
|
||||||
return $this->json($extractor->paramsNotSend());
|
|
||||||
$hesabdariRow->setPerson($person);
|
|
||||||
$entityManager->persist($hesabdariRow);
|
|
||||||
|
|
||||||
//set tax info
|
|
||||||
|
|
||||||
$entityManager->persist($doc);
|
|
||||||
$entityManager->flush();
|
|
||||||
if(!$doc->getShortlink()){
|
|
||||||
$doc->setShortlink($provider->RandomString(8));
|
|
||||||
}
|
|
||||||
|
|
||||||
//add pair docs
|
|
||||||
if(array_key_exists('pair_docs',$params)){
|
|
||||||
foreach($params['pair_docs'] as $pairCode){
|
|
||||||
$pair = $entityManager->getRepository(HesabdariDoc::class)->findOneBy([
|
|
||||||
'bid'=>$acc['bid'],
|
|
||||||
'code'=>$pairCode,
|
|
||||||
'type'=>'buy'
|
|
||||||
]);
|
|
||||||
if($pair){
|
|
||||||
$doc->addPairDoc($pair);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$entityManager->persist($doc);
|
|
||||||
$entityManager->flush();
|
|
||||||
|
|
||||||
$log->insert(
|
|
||||||
'حسابداری',
|
|
||||||
'سند حسابداری شماره ' . $doc->getCode() . ' ثبت / ویرایش شد.',
|
|
||||||
$this->getUser(),
|
|
||||||
$request->headers->get('activeBid'),
|
|
||||||
$doc
|
|
||||||
);
|
|
||||||
//send sms to customer
|
|
||||||
if (array_key_exists('sms', $params)) {
|
|
||||||
if ($params['sms'] == true) {
|
|
||||||
if ($pluginService->isActive('accpro', $acc['bid']) && $person->getMobile() != '' && $acc['bid']->getTel()) {
|
|
||||||
return $this->json([
|
|
||||||
'result' =>
|
|
||||||
$SMS->sendByBalance(
|
|
||||||
[$person->getnikename(), 'sell/' . $acc['bid']->getId() . '/' . $doc->getId(), $acc['bid']->getName(), $acc['bid']->getTel()],
|
|
||||||
$registryMGR->get('sms', 'plugAccproSharefaktor'),
|
|
||||||
$person->getMobile(),
|
|
||||||
$acc['bid'],
|
|
||||||
$this->getUser(),
|
|
||||||
3
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
return $this->json([
|
|
||||||
'result' =>
|
|
||||||
$SMS->sendByBalance(
|
|
||||||
[$acc['bid']->getName(), 'sell/' . $acc['bid']->getId() . '/' . $doc->getId()],
|
|
||||||
$registryMGR->get('sms', 'sharefaktor'),
|
|
||||||
$person->getMobile(),
|
|
||||||
$acc['bid'],
|
|
||||||
$this->getUser(),
|
|
||||||
3
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this->json($extractor->operationSuccess());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/api/presell/label/change', name: 'app_sell_label_change')]
|
|
||||||
public function app_sell_label_change(Request $request, Access $access, Extractor $extractor, Log $log, EntityManagerInterface $entityManager): JsonResponse
|
|
||||||
{
|
|
||||||
$params = [];
|
|
||||||
if ($content = $request->getContent()) {
|
|
||||||
$params = json_decode($content, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$acc = $access->hasRole('sell');
|
|
||||||
if (!$acc)
|
|
||||||
throw $this->createAccessDeniedException();
|
|
||||||
if ($params['label'] != 'clear') {
|
|
||||||
$label = $entityManager->getRepository(InvoiceType::class)->findOneBy([
|
|
||||||
'code' => $params['label']['code'],
|
|
||||||
'type' => 'sell'
|
|
||||||
]);
|
|
||||||
if (!$label)
|
|
||||||
return $this->json($extractor->notFound());
|
|
||||||
}
|
|
||||||
foreach ($params['items'] as $item) {
|
|
||||||
$doc = $entityManager->getRepository(HesabdariDoc::class)->findOneBy([
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'year' => $acc['year'],
|
|
||||||
'code' => $item['code'],
|
|
||||||
'money'=> $acc['money']
|
|
||||||
]);
|
|
||||||
if (!$doc)
|
|
||||||
return $this->json($extractor->notFound());
|
|
||||||
if ($params['label'] != 'clear') {
|
|
||||||
$doc->setInvoiceLabel($label);
|
|
||||||
$entityManager->persist($doc);
|
|
||||||
$log->insert(
|
|
||||||
'حسابداری',
|
|
||||||
' تغییر برچسب فاکتور شماره ' . $doc->getCode() . ' به ' . $label->getLabel(),
|
|
||||||
$this->getUser(),
|
|
||||||
$acc['bid']->getId(),
|
|
||||||
$doc
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$doc->setInvoiceLabel(null);
|
|
||||||
$entityManager->persist($doc);
|
|
||||||
$log->insert(
|
|
||||||
'حسابداری',
|
|
||||||
' حذف برچسب فاکتور شماره ' . $doc->getCode(),
|
|
||||||
$this->getUser(),
|
|
||||||
$acc['bid']->getId(),
|
|
||||||
$doc
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$entityManager->flush();
|
|
||||||
return $this->json($extractor->operationSuccess());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/api/presell/docs/search', name: 'app_sell_docs_search')]
|
|
||||||
public function app_sell_docs_search(Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager): JsonResponse
|
|
||||||
{
|
|
||||||
$acc = $access->hasRole('sell');
|
|
||||||
if (!$acc)
|
|
||||||
throw $this->createAccessDeniedException();
|
|
||||||
|
|
||||||
$params = [];
|
|
||||||
if ($content = $request->getContent()) {
|
|
||||||
$params = json_decode($content, true);
|
|
||||||
}
|
|
||||||
$data = $entityManager->getRepository(HesabdariDoc::class)->findBy([
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'year' => $acc['year'],
|
|
||||||
'type' => 'sell',
|
|
||||||
'money'=> $acc['money']
|
|
||||||
], [
|
|
||||||
'id' => 'DESC'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$dataTemp = [];
|
|
||||||
foreach ($data as $item) {
|
|
||||||
$temp = [
|
|
||||||
'id' => $item->getId(),
|
|
||||||
'dateSubmit' => $item->getDateSubmit(),
|
|
||||||
'date' => $item->getDate(),
|
|
||||||
'type' => $item->getType(),
|
|
||||||
'code' => $item->getCode(),
|
|
||||||
'des' => $item->getDes(),
|
|
||||||
'amount' => $item->getAmount(),
|
|
||||||
'submitter' => $item->getSubmitter()->getFullName(),
|
|
||||||
];
|
|
||||||
$mainRow = $entityManager->getRepository(HesabdariRow::class)->getNotEqual($item, 'person');
|
|
||||||
$temp['person'] = '';
|
|
||||||
if ($mainRow)
|
|
||||||
$temp['person'] = Explore::ExplorePerson($mainRow->getPerson());
|
|
||||||
|
|
||||||
$temp['label'] = null;
|
|
||||||
if ($item->getInvoiceLabel()) {
|
|
||||||
$temp['label'] = [
|
|
||||||
'code' => $item->getInvoiceLabel()->getCode(),
|
|
||||||
'label' => $item->getInvoiceLabel()->getLabel()
|
|
||||||
];
|
];
|
||||||
}
|
}, $preinvoice->getPreInvoiceItems()->toArray())
|
||||||
|
];
|
||||||
|
|
||||||
$temp['relatedDocsCount'] = count($item->getRelatedDocs());
|
return new JsonResponse($data);
|
||||||
$pays = 0;
|
|
||||||
foreach ($item->getRelatedDocs() as $relatedDoc) {
|
|
||||||
$pays += $relatedDoc->getAmount();
|
|
||||||
}
|
|
||||||
$temp['relatedDocsPays'] = $pays;
|
|
||||||
// this variable is for store profit of invoice
|
|
||||||
$temp['profit'] = 0;
|
|
||||||
foreach ($item->getHesabdariRows() as $item) {
|
|
||||||
if ($item->getRef()->getCode() == '104') {
|
|
||||||
$temp['discountAll'] = $item->getBd();
|
|
||||||
} elseif ($item->getRef()->getCode() == '61') {
|
|
||||||
$temp['transferCost'] = $item->getBs();
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate profit
|
|
||||||
if ($item->getCommodity() && $item->getCommdityCount()) {
|
|
||||||
if ($acc['bid']->getProfitCalctype() == 'lis') {
|
|
||||||
$last = $entityManager->getRepository(HesabdariRow::class)->findOneBy([
|
|
||||||
'commodity' => $item->getCommodity(),
|
|
||||||
'bs' => 0
|
|
||||||
], [
|
|
||||||
'id' => 'DESC'
|
|
||||||
]);
|
|
||||||
if ($last) {
|
|
||||||
$price = $last->getBd() / $last->getCommdityCount();
|
|
||||||
$temp['profit'] = $temp['profit'] + ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount());
|
|
||||||
} else {
|
|
||||||
$temp['profit'] = $temp['profit'] + $item->getBs();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$lasts = $entityManager->getRepository(HesabdariRow::class)->findBy([
|
|
||||||
'commodity' => $item->getCommodity(),
|
|
||||||
'bs' => 0
|
|
||||||
], [
|
|
||||||
'id' => 'DESC'
|
|
||||||
]);
|
|
||||||
$avg = 0;
|
|
||||||
$count = 0;
|
|
||||||
foreach ($lasts as $last) {
|
|
||||||
$avg = $avg + $last->getBd();
|
|
||||||
$count = $count + $last->getCommdityCount();
|
|
||||||
}
|
|
||||||
if ($count != 0) {
|
|
||||||
$price = $avg / $count;
|
|
||||||
$temp['profit'] = $temp['profit'] + ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
$temp['profit'] = $temp['profit'] + $item->getBs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//round output
|
|
||||||
$temp['profit'] = round($temp['profit']);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (!array_key_exists('discountAll', $temp))
|
|
||||||
$temp['discountAll'] = 0;
|
|
||||||
if (!array_key_exists('transferCost', $temp))
|
|
||||||
$temp['transferCost'] = 0;
|
|
||||||
$dataTemp[] = $temp;
|
|
||||||
}
|
|
||||||
return $this->json($dataTemp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/api/presell/posprinter/invoice', name: 'app_sell_posprinter_invoice')]
|
#[Route('/api/preinvoice/save', name: 'app_preinvoice_save')]
|
||||||
public function app_sell_posprinter_invoice(Printers $printers, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager): JsonResponse
|
public function savePreinvoice(Access $access,Provider $provider, Log $log, EntityManagerInterface $entityManager, Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
$acc = $access->hasRole('preinvoice');
|
||||||
|
if (!$acc) {
|
||||||
|
return new JsonResponse($this->extractor->operationFail('دسترسی ندارید'), 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode($request->getContent(), true);
|
||||||
|
|
||||||
|
if (isset($data['id']) && $data['id']) {
|
||||||
|
$preinvoice = $entityManager->getRepository(PreInvoiceDoc::class)->findOneBy(['code' => $data['id'], 'bid' => $acc['bid'], 'year' => $acc['year']]);
|
||||||
|
if (!$preinvoice) {
|
||||||
|
return new JsonResponse(['error' => 'پیش فاکتور یافت نشد'], 404);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$preinvoice = new PreInvoiceDoc();
|
||||||
|
$preinvoice->setCode($this->generateCode($entityManager));
|
||||||
|
$preinvoice->setSubmitter($this->getUser());
|
||||||
|
$preinvoice->setYear($acc['year']);
|
||||||
|
$preinvoice->setBid($acc['bid']);
|
||||||
|
$preinvoice->setMoney($acc['money']);
|
||||||
|
$preinvoice->setStatus(1);
|
||||||
|
|
||||||
|
$preinvoice->setCode($provider->getAccountingCode($acc['bid'], 'accounting'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$person = $entityManager->getRepository(Person::class)->find($data['person']);
|
||||||
|
if (!$person) {
|
||||||
|
return new JsonResponse(['error' => 'شخص یافت نشد'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$preinvoice->setPerson($person);
|
||||||
|
$preinvoice->setDate($data['date']);
|
||||||
|
$preinvoice->setDes($data['des']);
|
||||||
|
$preinvoice->setAmount($data['amount']);
|
||||||
|
$preinvoice->setTaxPercent($data['taxPercent']);
|
||||||
|
$preinvoice->setTotalDiscount($data['totalDiscount']);
|
||||||
|
$preinvoice->setTotalDiscountPercent($data['totalDiscountPercent']);
|
||||||
|
$preinvoice->setShippingCost($data['shippingCost']);
|
||||||
|
$preinvoice->setShowPercentDiscount($data['showPercentDiscount']);
|
||||||
|
$preinvoice->setShowTotalPercentDiscount($data['showTotalPercentDiscount']);
|
||||||
|
|
||||||
|
$entityManager->persist($preinvoice);
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
// حذف آیتمهای قبلی
|
||||||
|
if (isset($data['id']) && $data['id']) {
|
||||||
|
foreach ($preinvoice->getPreInvoiceItems() as $oldItem) {
|
||||||
|
$entityManager->remove($oldItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// اضافه کردن آیتمهای جدید
|
||||||
|
foreach ($data['items'] as $itemData) {
|
||||||
|
$item = new PreInvoiceItem();
|
||||||
|
$commodity = $entityManager->getRepository(Commodity::class)->find($itemData['commodity']);
|
||||||
|
if (!$commodity) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->setCommodity($commodity);
|
||||||
|
$item->setCommodityCount($itemData['count']);
|
||||||
|
$item->setBs($itemData['price']);
|
||||||
|
$item->setDiscountPercent($itemData['discountPercent']);
|
||||||
|
$item->setDiscountAmount($itemData['discountAmount']);
|
||||||
|
$item->setDes($itemData['description']);
|
||||||
|
$item->setShowPercentDiscount($itemData['showPercentDiscount']);
|
||||||
|
$item->setDoc($preinvoice);
|
||||||
|
$entityManager->persist($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entityManager->flush();
|
||||||
|
$log->insert(
|
||||||
|
'پیش فاکتور',
|
||||||
|
'پیش فاکتور شماره ' . $preinvoice->getCode() . ' ثبت / ویرایش شد.',
|
||||||
|
$this->getUser(),
|
||||||
|
$acc['bid'],
|
||||||
|
);
|
||||||
|
return new JsonResponse(['id' => $preinvoice->getId()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/api/preinvoice/delete/{id}', name: 'app_preinvoice_delete')]
|
||||||
|
public function deletePreinvoice(Access $access, Log $log, EntityManagerInterface $entityManager, int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$acc = $access->hasRole('preinvoice');
|
||||||
|
if (!$acc) {
|
||||||
|
return new JsonResponse($this->extractor->operationFail('دسترسی ندارید'), 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$preinvoice = $entityManager->getRepository(PreInvoiceDoc::class)->findOneBy(['code' => $id, 'bid' => $acc['bid'], 'year' => $acc['year']] );
|
||||||
|
if (!$preinvoice) {
|
||||||
|
return new JsonResponse(['error' => 'پیش فاکتور یافت نشد'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($preinvoice->getPreInvoiceItems() as $item) {
|
||||||
|
$entityManager->remove($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entityManager->remove($preinvoice);
|
||||||
|
$entityManager->flush();
|
||||||
|
$log->insert(
|
||||||
|
'پیش فاکتور',
|
||||||
|
'پیش فاکتور شماره ' . $preinvoice->getCode() . ' حذف شد.',
|
||||||
|
$this->getUser(),
|
||||||
|
$acc['bid'],
|
||||||
|
);
|
||||||
|
return new JsonResponse(['message' => 'پیش فاکتور با موفقیت حذف شد']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateCode(EntityManagerInterface $entityManager): string
|
||||||
|
{
|
||||||
|
$lastPreinvoice = $entityManager->getRepository(PreInvoiceDoc::class)
|
||||||
|
->findOneBy([], ['id' => 'DESC']);
|
||||||
|
|
||||||
|
$lastNumber = $lastPreinvoice ? (int)substr($lastPreinvoice->getCode(), 1) : 0;
|
||||||
|
return 'P' . str_pad($lastNumber + 1, 6, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/api/preinvoice/docs/search', name: 'app_presell_search')]
|
||||||
|
public function searchPreinvoices(Access $access, EntityManagerInterface $entityManager): JsonResponse
|
||||||
|
{
|
||||||
|
$acc = $access->hasRole('preinvoice');
|
||||||
|
if (!$acc) {
|
||||||
|
return new JsonResponse($this->extractor->operationFail('دسترسی ندارید'), 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$preinvoices = $entityManager->getRepository(PreInvoiceDoc::class)
|
||||||
|
->findBy(['bid' => $acc['bid'], 'year' => $acc['year']], ['id' => 'DESC']);
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($preinvoices as $preinvoice) {
|
||||||
|
$totalAmount = $preinvoice->getAmount() - $preinvoice->getTotalDiscount() + $preinvoice->getShippingCost();
|
||||||
|
|
||||||
|
$result[] = [
|
||||||
|
'code' => $preinvoice->getCode(),
|
||||||
|
'date' => $preinvoice->getDate(),
|
||||||
|
'des' => $preinvoice->getDes(),
|
||||||
|
'person' => [
|
||||||
|
'code' => $preinvoice->getPerson()->getId(),
|
||||||
|
'nikename' => $preinvoice->getPerson()->getNikename()
|
||||||
|
],
|
||||||
|
'amount' => $preinvoice->getAmount(),
|
||||||
|
'discountAll' => $preinvoice->getTotalDiscount(),
|
||||||
|
'transferCost' => $preinvoice->getShippingCost(),
|
||||||
|
'totalAmount' => $totalAmount,
|
||||||
|
'label' => $preinvoice->getInvoiceLabel() ? [
|
||||||
|
'code' => $preinvoice->getInvoiceLabel()->getCode(),
|
||||||
|
'label' => $preinvoice->getInvoiceLabel()->getLabel()
|
||||||
|
] : null
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JsonResponse($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/api/preinvoice/remove/group', name: 'app_presell_delete_group')]
|
||||||
|
public function deletePreinvoiceGroup(Log $log, Access $access, EntityManagerInterface $entityManager, Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
$acc = $access->hasRole('preinvoice');
|
||||||
|
if (!$acc) {
|
||||||
|
return new JsonResponse($this->extractor->operationFail('دسترسی ندارید'), 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode($request->getContent(), true);
|
||||||
|
$items = $data['items'] ?? [];
|
||||||
|
|
||||||
|
if (empty($items)) {
|
||||||
|
return new JsonResponse(['result' => 2, 'message' => 'هیچ موردی انتخاب نشده است']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($items as $itemCode) {
|
||||||
|
$preinvoice = $entityManager->getRepository(PreInvoiceDoc::class)
|
||||||
|
->findOneBy(['code' => $itemCode['code'], 'bid' => $acc['bid'], 'year' => $acc['year']]);
|
||||||
|
|
||||||
|
if ($preinvoice) {
|
||||||
|
// حذف آیتمهای پیش فاکتور
|
||||||
|
foreach ($preinvoice->getPreInvoiceItems() as $item) {
|
||||||
|
$entityManager->remove($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entityManager->remove($preinvoice);
|
||||||
|
}
|
||||||
|
$log->insert(
|
||||||
|
'پیش فاکتور',
|
||||||
|
'پیش فاکتور شماره ' . $preinvoice->getCode() . ' حذف شد.',
|
||||||
|
$this->getUser(),
|
||||||
|
$acc['bid'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
return new JsonResponse(['result' => 1, 'message' => 'پیش فاکتورها با موفقیت حذف شدند']);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/api/preinvoice/print/invoice', name: 'app_preinvoice_print_invoice')]
|
||||||
|
public function printPreinvoice(Printers $printers, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager): JsonResponse
|
||||||
{
|
{
|
||||||
$params = [];
|
$params = [];
|
||||||
if ($content = $request->getContent()) {
|
if ($content = $request->getContent()) {
|
||||||
$params = json_decode($content, true);
|
$params = json_decode($content, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$acc = $access->hasRole('sell');
|
$acc = $access->hasRole('preinvoice');
|
||||||
if (!$acc)
|
if (!$acc) {
|
||||||
throw $this->createAccessDeniedException();
|
throw $this->createAccessDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
$doc = $entityManager->getRepository(HesabdariDoc::class)->findOneBy([
|
$preinvoice = $entityManager->getRepository(PreInvoiceDoc::class)->findOneBy([
|
||||||
'bid' => $acc['bid'],
|
'bid' => $acc['bid'],
|
||||||
'code' => $params['code'],
|
'code' => $params['code'],
|
||||||
'money'=> $acc['money']
|
'year' => $acc['year']
|
||||||
]);
|
]);
|
||||||
if (!$doc)
|
|
||||||
|
if (!$preinvoice) {
|
||||||
throw $this->createNotFoundException();
|
throw $this->createNotFoundException();
|
||||||
$pdfPid = 0;
|
|
||||||
if ($params['pdf']) {
|
|
||||||
$pdfPid = $provider->createPrint(
|
|
||||||
$acc['bid'],
|
|
||||||
$this->getUser(),
|
|
||||||
$this->renderView('pdf/posPrinters/presell.html.twig', [
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'doc' => $doc,
|
|
||||||
'rows' => $doc->getHesabdariRows(),
|
|
||||||
'printInvoice' => $params['posPrint'],
|
|
||||||
'printcashdeskRecp' => $params['posPrintRecp'],
|
|
||||||
]),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($params['posPrint'] == true) {
|
|
||||||
$pid = $provider->createPrint(
|
|
||||||
$acc['bid'],
|
|
||||||
$this->getUser(),
|
|
||||||
$this->renderView('pdf/posPrinters/justSell.html.twig', [
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'doc' => $doc,
|
|
||||||
'rows' => $doc->getHesabdariRows(),
|
|
||||||
]),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
$printers->addFile($pid, $acc, "fastSellInvoice");
|
|
||||||
}
|
|
||||||
if ($params['posPrintRecp'] == true) {
|
|
||||||
$pid = $provider->createPrint(
|
|
||||||
$acc['bid'],
|
|
||||||
$this->getUser(),
|
|
||||||
$this->renderView('pdf/posPrinters/cashdesk.html.twig', [
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'doc' => $doc,
|
|
||||||
'rows' => $doc->getHesabdariRows(),
|
|
||||||
]),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
$printers->addFile($pid, $acc, "fastSellCashdesk");
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->json(['id' => $pdfPid]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/api/presell/print/invoice', name: 'app_sell_print_invoice')]
|
|
||||||
public function app_sell_print_invoice(Printers $printers, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager): JsonResponse
|
|
||||||
{
|
|
||||||
$params = [];
|
|
||||||
if ($content = $request->getContent()) {
|
|
||||||
$params = json_decode($content, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$acc = $access->hasRole('sell');
|
|
||||||
if (!$acc)
|
|
||||||
throw $this->createAccessDeniedException();
|
|
||||||
|
|
||||||
$doc = $entityManager->getRepository(HesabdariDoc::class)->findOneBy([
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'code' => $params['code'],
|
|
||||||
'money'=> $acc['money']
|
|
||||||
]);
|
|
||||||
if (!$doc)
|
|
||||||
throw $this->createNotFoundException();
|
|
||||||
$person = null;
|
|
||||||
$discount = 0;
|
|
||||||
$transfer = 0;
|
|
||||||
foreach ($doc->getHesabdariRows() as $item) {
|
|
||||||
if ($item->getPerson()) {
|
|
||||||
$person = $item->getPerson();
|
|
||||||
} elseif ($item->getRef()->getCode() == 104) {
|
|
||||||
$discount = $item->getBd();
|
|
||||||
} elseif ($item->getRef()->getCode() == 61) {
|
|
||||||
$transfer = $item->getBs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$pdfPid = 0;
|
$pdfPid = 0;
|
||||||
if ($params['pdf']) {
|
if ($params['pdf']) {
|
||||||
$printOptions = [
|
$printOptions = [
|
||||||
|
@ -557,6 +314,7 @@ class PreinvoiceController extends AbstractController
|
||||||
'note' => true,
|
'note' => true,
|
||||||
'paper' => 'A4-L'
|
'paper' => 'A4-L'
|
||||||
];
|
];
|
||||||
|
|
||||||
if (array_key_exists('printOptions', $params)) {
|
if (array_key_exists('printOptions', $params)) {
|
||||||
if (array_key_exists('bidInfo', $params['printOptions'])) {
|
if (array_key_exists('bidInfo', $params['printOptions'])) {
|
||||||
$printOptions['bidInfo'] = $params['printOptions']['bidInfo'];
|
$printOptions['bidInfo'] = $params['printOptions']['bidInfo'];
|
||||||
|
@ -577,22 +335,24 @@ class PreinvoiceController extends AbstractController
|
||||||
$printOptions['paper'] = $params['printOptions']['paper'];
|
$printOptions['paper'] = $params['printOptions']['paper'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$note = '';
|
$note = '';
|
||||||
$printSettings = $entityManager->getRepository(PrintOptions::class)->findOneBy(['bid' => $acc['bid']]);
|
$printSettings = $entityManager->getRepository(PrintOptions::class)->findOneBy(['bid' => $acc['bid']]);
|
||||||
if ($printSettings) {
|
if ($printSettings) {
|
||||||
$note = $printSettings->getSellNoteString();
|
$note = $printSettings->getSellNoteString();
|
||||||
}
|
}
|
||||||
|
|
||||||
$pdfPid = $provider->createPrint(
|
$pdfPid = $provider->createPrint(
|
||||||
$acc['bid'],
|
$acc['bid'],
|
||||||
$this->getUser(),
|
$this->getUser(),
|
||||||
$this->renderView('pdf/printers/presell.html.twig', [
|
$this->renderView('pdf/printers/preinvoice.html.twig', [
|
||||||
'bid' => $acc['bid'],
|
'bid' => $acc['bid'],
|
||||||
'doc' => $doc,
|
'doc' => $preinvoice,
|
||||||
'rows' => $doc->getHesabdariRows(),
|
'items' => $preinvoice->getPreInvoiceItems(),
|
||||||
'person' => $person,
|
'person' => $preinvoice->getPerson(),
|
||||||
'printInvoice' => $params['printers'],
|
'printInvoice' => $params['printers'],
|
||||||
'discount' => $discount,
|
'discount' => $preinvoice->getTotalDiscount(),
|
||||||
'transfer' => $transfer,
|
'transfer' => $preinvoice->getShippingCost(),
|
||||||
'printOptions' => $printOptions,
|
'printOptions' => $printOptions,
|
||||||
'note' => $note
|
'note' => $note
|
||||||
]),
|
]),
|
||||||
|
@ -600,19 +360,21 @@ class PreinvoiceController extends AbstractController
|
||||||
$printOptions['paper']
|
$printOptions['paper']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($params['printers'] == true) {
|
if ($params['printers'] == true) {
|
||||||
$pid = $provider->createPrint(
|
$pid = $provider->createPrint(
|
||||||
$acc['bid'],
|
$acc['bid'],
|
||||||
$this->getUser(),
|
$this->getUser(),
|
||||||
$this->renderView('pdf/posPrinters/justSell.html.twig', [
|
$this->renderView('pdf/posPrinters/justPreinvoice.html.twig', [
|
||||||
'bid' => $acc['bid'],
|
'bid' => $acc['bid'],
|
||||||
'doc' => $doc,
|
'doc' => $preinvoice,
|
||||||
'rows' => $doc->getHesabdariRows(),
|
'items' => $preinvoice->getPreInvoiceItems(),
|
||||||
]),
|
]),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
$printers->addFile($pid, $acc, "fastSellInvoice");
|
$printers->addFile($pid, $acc, "fastPreinvoice");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->json(['id' => $pdfPid]);
|
return $this->json(['id' => $pdfPid]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
|
||||||
class YearController extends AbstractController
|
class YearController extends AbstractController
|
||||||
{
|
{
|
||||||
|
@ -46,7 +47,7 @@ class YearController extends AbstractController
|
||||||
//no year created create first year
|
//no year created create first year
|
||||||
$years = [$this->createDefaultYear($business,$entityManager)];
|
$years = [$this->createDefaultYear($business,$entityManager)];
|
||||||
}
|
}
|
||||||
return $this->json($years);
|
return $this->json($years, 200, [], ['groups' => ['year:read']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/api/year/get', name: 'app_year_get')]
|
#[Route('/api/year/get', name: 'app_year_get')]
|
||||||
|
@ -65,7 +66,8 @@ class YearController extends AbstractController
|
||||||
$yearLoad->setStart($jdate->jdate('Y/m/d', $yearLoad->getStart()));
|
$yearLoad->setStart($jdate->jdate('Y/m/d', $yearLoad->getStart()));
|
||||||
$yearLoad->setEnd($jdate->jdate('Y/m/d', $yearLoad->getEnd()));
|
$yearLoad->setEnd($jdate->jdate('Y/m/d', $yearLoad->getEnd()));
|
||||||
$yearLoad->setNow($jdate->jdate('Y/m/d', time()));
|
$yearLoad->setNow($jdate->jdate('Y/m/d', time()));
|
||||||
return $this->json($yearLoad);
|
|
||||||
|
return $this->json($yearLoad, 200, [], ['groups' => ['year:read']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/api/year/lastyear/info', name: 'app_year_last_year_info')]
|
#[Route('/api/year/lastyear/info', name: 'app_year_last_year_info')]
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
use App\Repository\PreInvoiceDocRepository;
|
use App\Repository\PreInvoiceDocRepository;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: PreInvoiceDocRepository::class)]
|
#[ORM\Entity(repositoryClass: PreInvoiceDocRepository::class)]
|
||||||
|
@ -45,6 +47,24 @@ class PreInvoiceDoc
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
private ?string $amount = null;
|
private ?string $amount = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
|
private ?string $taxPercent = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
|
private ?string $totalDiscount = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
|
private ?string $totalDiscountPercent = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
|
private ?string $shippingCost = null;
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'boolean', nullable: true)]
|
||||||
|
private ?bool $showPercentDiscount = null;
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'boolean', nullable: true)]
|
||||||
|
private ?bool $showTotalPercentDiscount = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
private ?string $mdate = null;
|
private ?string $mdate = null;
|
||||||
|
|
||||||
|
@ -66,6 +86,17 @@ class PreInvoiceDoc
|
||||||
#[ORM\ManyToOne(inversedBy: 'preinvoiceDocsSalemans')]
|
#[ORM\ManyToOne(inversedBy: 'preinvoiceDocsSalemans')]
|
||||||
private ?Person $salesman = null;
|
private ?Person $salesman = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Collection<int, PreInvoiceItem>
|
||||||
|
*/
|
||||||
|
#[ORM\OneToMany(mappedBy: 'doc', targetEntity: PreInvoiceItem::class, orphanRemoval: true)]
|
||||||
|
private Collection $preInvoiceItems;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->preInvoiceItems = new ArrayCollection();
|
||||||
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
|
@ -179,6 +210,72 @@ class PreInvoiceDoc
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTaxPercent(): ?string
|
||||||
|
{
|
||||||
|
return $this->taxPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTaxPercent(?string $taxPercent): static
|
||||||
|
{
|
||||||
|
$this->taxPercent = $taxPercent;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotalDiscount(): ?string
|
||||||
|
{
|
||||||
|
return $this->totalDiscount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTotalDiscount(?string $totalDiscount): static
|
||||||
|
{
|
||||||
|
$this->totalDiscount = $totalDiscount;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotalDiscountPercent(): ?string
|
||||||
|
{
|
||||||
|
return $this->totalDiscountPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTotalDiscountPercent(?string $totalDiscountPercent): static
|
||||||
|
{
|
||||||
|
$this->totalDiscountPercent = $totalDiscountPercent;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShippingCost(): ?string
|
||||||
|
{
|
||||||
|
return $this->shippingCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setShippingCost(?string $shippingCost): static
|
||||||
|
{
|
||||||
|
$this->shippingCost = $shippingCost;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isShowPercentDiscount(): ?bool
|
||||||
|
{
|
||||||
|
return $this->showPercentDiscount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setShowPercentDiscount(?bool $showPercentDiscount): static
|
||||||
|
{
|
||||||
|
$this->showPercentDiscount = $showPercentDiscount;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isShowTotalPercentDiscount(): ?bool
|
||||||
|
{
|
||||||
|
return $this->showTotalPercentDiscount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setShowTotalPercentDiscount(?bool $showTotalPercentDiscount): static
|
||||||
|
{
|
||||||
|
$this->showTotalPercentDiscount = $showTotalPercentDiscount;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function getMdate(): ?string
|
public function getMdate(): ?string
|
||||||
{
|
{
|
||||||
return $this->mdate;
|
return $this->mdate;
|
||||||
|
@ -262,4 +359,34 @@ class PreInvoiceDoc
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection<int, PreInvoiceItem>
|
||||||
|
*/
|
||||||
|
public function getPreInvoiceItems(): Collection
|
||||||
|
{
|
||||||
|
return $this->preInvoiceItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addPreInvoiceItem(PreInvoiceItem $preInvoiceItem): static
|
||||||
|
{
|
||||||
|
if (!$this->preInvoiceItems->contains($preInvoiceItem)) {
|
||||||
|
$this->preInvoiceItems->add($preInvoiceItem);
|
||||||
|
$preInvoiceItem->setDoc($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removePreInvoiceItem(PreInvoiceItem $preInvoiceItem): static
|
||||||
|
{
|
||||||
|
if ($this->preInvoiceItems->removeElement($preInvoiceItem)) {
|
||||||
|
// set the owning side to null (unless already changed)
|
||||||
|
if ($preInvoiceItem->getDoc() === $this) {
|
||||||
|
$preInvoiceItem->setDoc(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,38 +26,27 @@ class PreInvoiceItem
|
||||||
#[ORM\Column(length: 100, nullable: true)]
|
#[ORM\Column(length: 100, nullable: true)]
|
||||||
private ?string $bd = null;
|
private ?string $bd = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 100, nullable: true)]
|
||||||
|
private ?string $discountPercent = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 100, nullable: true)]
|
||||||
|
private ?string $discountAmount = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
private ?string $des = null;
|
private ?string $des = null;
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
|
||||||
private ?Person $person = null;
|
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
|
||||||
private ?BankAccount $bank = null;
|
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
|
||||||
private ?Cashdesk $cashdesk = null;
|
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
|
||||||
private ?Salary $salary = null;
|
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'preInvoiceItems')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
|
||||||
private ?Business $bid = null;
|
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
|
||||||
private ?Year $year = null;
|
|
||||||
|
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
private ?string $discount = null;
|
private ?string $discount = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
private ?string $tax = null;
|
private ?string $tax = null;
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
#[ORM\Column(type: 'boolean', nullable: true)]
|
||||||
|
private ?bool $showPercentDiscount = null;
|
||||||
|
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'preInvoiceItems')]
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
private ?HesabdariTable $refID = null;
|
private ?PreInvoiceDoc $doc = null;
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
|
@ -112,6 +101,28 @@ class PreInvoiceItem
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDiscountPercent(): ?string
|
||||||
|
{
|
||||||
|
return $this->discountPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDiscountPercent(?string $discountPercent): static
|
||||||
|
{
|
||||||
|
$this->discountPercent = $discountPercent;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDiscountAmount(): ?string
|
||||||
|
{
|
||||||
|
return $this->discountAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDiscountAmount(?string $discountAmount): static
|
||||||
|
{
|
||||||
|
$this->discountAmount = $discountAmount;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function getDes(): ?string
|
public function getDes(): ?string
|
||||||
{
|
{
|
||||||
return $this->des;
|
return $this->des;
|
||||||
|
@ -124,78 +135,6 @@ class PreInvoiceItem
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPerson(): ?Person
|
|
||||||
{
|
|
||||||
return $this->person;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setPerson(?Person $person): static
|
|
||||||
{
|
|
||||||
$this->person = $person;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBank(): ?BankAccount
|
|
||||||
{
|
|
||||||
return $this->bank;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBank(?BankAccount $bank): static
|
|
||||||
{
|
|
||||||
$this->bank = $bank;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCashdesk(): ?Cashdesk
|
|
||||||
{
|
|
||||||
return $this->cashdesk;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCashdesk(?Cashdesk $cashdesk): static
|
|
||||||
{
|
|
||||||
$this->cashdesk = $cashdesk;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSalary(): ?Salary
|
|
||||||
{
|
|
||||||
return $this->salary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setSalary(?Salary $salary): static
|
|
||||||
{
|
|
||||||
$this->salary = $salary;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBid(): ?Business
|
|
||||||
{
|
|
||||||
return $this->bid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBid(?Business $bid): static
|
|
||||||
{
|
|
||||||
$this->bid = $bid;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getYear(): ?Year
|
|
||||||
{
|
|
||||||
return $this->year;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setYear(?Year $year): static
|
|
||||||
{
|
|
||||||
$this->year = $year;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDiscount(): ?string
|
public function getDiscount(): ?string
|
||||||
{
|
{
|
||||||
return $this->discount;
|
return $this->discount;
|
||||||
|
@ -220,14 +159,25 @@ class PreInvoiceItem
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRefID(): ?HesabdariTable
|
public function isShowPercentDiscount(): ?bool
|
||||||
{
|
{
|
||||||
return $this->refID;
|
return $this->showPercentDiscount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setRefID(?HesabdariTable $refID): static
|
public function setShowPercentDiscount(?bool $showPercentDiscount): static
|
||||||
{
|
{
|
||||||
$this->refID = $refID;
|
$this->showPercentDiscount = $showPercentDiscount;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDoc(): ?PreInvoiceDoc
|
||||||
|
{
|
||||||
|
return $this->doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDoc(?PreInvoiceDoc $doc): static
|
||||||
|
{
|
||||||
|
$this->doc = $doc;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use App\Repository\YearRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
use Symfony\Component\Serializer\Annotation\Ignore;
|
use Symfony\Component\Serializer\Annotation\Ignore;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: YearRepository::class)]
|
#[ORM\Entity(repositoryClass: YearRepository::class)]
|
||||||
|
@ -14,9 +15,11 @@ class Year
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
#[ORM\GeneratedValue]
|
#[ORM\GeneratedValue]
|
||||||
#[ORM\Column]
|
#[ORM\Column]
|
||||||
|
#[Groups(['year:read'])]
|
||||||
private ?int $id = null;
|
private ?int $id = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
#[ORM\Column(length: 255)]
|
||||||
|
#[Groups(['year:read'])]
|
||||||
private ?string $label = null;
|
private ?string $label = null;
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'years')]
|
#[ORM\ManyToOne(inversedBy: 'years')]
|
||||||
|
@ -25,6 +28,7 @@ class Year
|
||||||
private ?Business $bid = null;
|
private ?Business $bid = null;
|
||||||
|
|
||||||
#[ORM\Column(nullable: true)]
|
#[ORM\Column(nullable: true)]
|
||||||
|
#[Groups(['year:read'])]
|
||||||
private ?bool $head = null;
|
private ?bool $head = null;
|
||||||
|
|
||||||
#[ORM\OneToMany(mappedBy: 'year', targetEntity: HesabdariDoc::class, orphanRemoval: true)]
|
#[ORM\OneToMany(mappedBy: 'year', targetEntity: HesabdariDoc::class, orphanRemoval: true)]
|
||||||
|
@ -32,12 +36,15 @@ class Year
|
||||||
private Collection $hesabdariDocs;
|
private Collection $hesabdariDocs;
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
#[ORM\Column(length: 255)]
|
||||||
|
#[Groups(['year:read'])]
|
||||||
private ?string $start = null;
|
private ?string $start = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
#[ORM\Column(length: 255)]
|
||||||
|
#[Groups(['year:read'])]
|
||||||
private ?string $end = null;
|
private ?string $end = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
|
#[Groups(['year:read'])]
|
||||||
private ?string $now = null;
|
private ?string $now = null;
|
||||||
|
|
||||||
#[ORM\OneToMany(mappedBy: 'year', targetEntity: HesabdariRow::class, orphanRemoval: true)]
|
#[ORM\OneToMany(mappedBy: 'year', targetEntity: HesabdariRow::class, orphanRemoval: true)]
|
||||||
|
|
25
hesabixCore/src/Twig/NumberFormatExtension.php
Normal file
25
hesabixCore/src/Twig/NumberFormatExtension.php
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Twig;
|
||||||
|
|
||||||
|
use Twig\Extension\AbstractExtension;
|
||||||
|
use Twig\TwigFilter;
|
||||||
|
|
||||||
|
class NumberFormatExtension extends AbstractExtension
|
||||||
|
{
|
||||||
|
public function getFilters()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new TwigFilter('number_format', [$this, 'formatNumber']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function formatNumber($number, $decimals = 0, $decPoint = '.', $thousandsSep = ',', $currency = null)
|
||||||
|
{
|
||||||
|
$formatted = number_format($number, $decimals, $decPoint, $thousandsSep);
|
||||||
|
if ($currency) {
|
||||||
|
$formatted .= ' ' . $currency;
|
||||||
|
}
|
||||||
|
return $formatted;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>پیش فاکتور {{ doc.code }}</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'B Nazanin', Arial, sans-serif;
|
||||||
|
direction: rtl;
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.items {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.items table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
.items th, .items td {
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid #000;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.summary {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.summary table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
.summary td {
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="header">
|
||||||
|
<h2>پیش فاکتور فروش</h2>
|
||||||
|
<p>شماره: {{ doc.code }}</p>
|
||||||
|
<p>تاریخ: {{ doc.date }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="items">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>نام کالا</th>
|
||||||
|
<th>تعداد</th>
|
||||||
|
<th>قیمت</th>
|
||||||
|
<th>جمع</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for item in items %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ item.commodity.name }}</td>
|
||||||
|
<td>{{ item.commodityCount }}</td>
|
||||||
|
<td>{{ item.bs|number_format }}</td>
|
||||||
|
<td>{{ (item.bs * item.commodityCount)|number_format }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="summary">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>جمع کل:</td>
|
||||||
|
<td>{{ doc.amount|number_format }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>تخفیف:</td>
|
||||||
|
<td>{{ doc.totalDiscount|number_format }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>مالیات:</td>
|
||||||
|
<td>{{ (doc.amount * doc.taxPercent / 100)|number_format }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>هزینه حمل:</td>
|
||||||
|
<td>{{ doc.shippingCost|number_format }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>قابل پرداخت:</td>
|
||||||
|
<td>{{ (doc.amount - doc.totalDiscount + doc.shippingCost + (doc.amount * doc.taxPercent / 100))|number_format }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
278
hesabixCore/templates/pdf/printers/preinvoice.html.twig
Normal file
278
hesabixCore/templates/pdf/printers/preinvoice.html.twig
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fa" direction="rtl">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.text-white {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.stimol td,
|
||||||
|
.stimol th {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="direction:rtl; width:100%">
|
||||||
|
<div class="block-content pt-1 pb-3 d-none d-sm-block">
|
||||||
|
<div class="c-print container-xl">
|
||||||
|
<div class="tg-wrap" style="width:100%; border:1px solid black;border-radius: 8px;">
|
||||||
|
<table class="rounded" style="width:100%;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td style="width:20%">
|
||||||
|
<img src="{{ url('front_avatar_file_get', {id: bid.id}) }}" width="65"/>
|
||||||
|
</td>
|
||||||
|
<td style="width:60%; text-align:center">
|
||||||
|
<h3 class="">پیش فاکتور فروش کالا و خدمات</h3>
|
||||||
|
</td>
|
||||||
|
<td style="width:20%">
|
||||||
|
<h4>
|
||||||
|
<b>تاریخ:</b>
|
||||||
|
{{ doc.date }}</h4>
|
||||||
|
<br/>
|
||||||
|
<h4>
|
||||||
|
<b>شماره:</b>
|
||||||
|
{{ doc.code }}</h4>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if printOptions.bidInfo %}
|
||||||
|
<div style="width:100%; border:1px solid black;border-radius: 8px;margin-top:5px;text-align:center;">
|
||||||
|
<div class="tg-wrap" style="width:100%;border-radius: 8px 8px 0px 0px;text-align:center;background-color:gray">
|
||||||
|
<b style="color:white;">فروشنده</b>
|
||||||
|
</div>
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr style="text-align:center;">
|
||||||
|
<td class="">
|
||||||
|
<p>
|
||||||
|
<b>نام: </b>
|
||||||
|
{{ bid.legalName }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="center">
|
||||||
|
<p>
|
||||||
|
<b>شناسه ملی: </b>
|
||||||
|
{{ bid.shenasemeli }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="center">
|
||||||
|
<p>
|
||||||
|
<b>شماره ثبت: </b>
|
||||||
|
{{ bid.shomaresabt }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="center">
|
||||||
|
<p>
|
||||||
|
<b>شماره اقتصادی: </b>
|
||||||
|
{{ bid.codeeghtesadi }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="center">
|
||||||
|
<p>
|
||||||
|
<b>تلفن / نمابر:</b>
|
||||||
|
{{ bid.tel }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="" colspan="1">
|
||||||
|
<p>
|
||||||
|
<b>کد پستی:</b>
|
||||||
|
{{ bid.postalcode }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="" colspan="3">
|
||||||
|
<p>
|
||||||
|
<b>آدرس: </b>
|
||||||
|
استان {{ bid.ostan }}، شهر {{ bid.shahrestan }}، {{ bid.address }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div style="width:100%; border:1px solid black;border-radius: 8px;margin-top:5px;text-align:center;">
|
||||||
|
<div class="tg-wrap" style="width:100%;border-radius: 8px 8px 0px 0px;text-align:center;background-color:gray">
|
||||||
|
<b style="color:white;">خریدار</b>
|
||||||
|
</div>
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr style="text-align:center;">
|
||||||
|
<td class="">
|
||||||
|
<p>
|
||||||
|
<b>نام: </b>
|
||||||
|
{% if person.prelabel is not null %}{{ person.prelabel.label }}{% endif %}
|
||||||
|
{{ person.nikename }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="center">
|
||||||
|
<p>
|
||||||
|
<b>شناسه ملی: </b>
|
||||||
|
{{ person.shenasemeli }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="center">
|
||||||
|
<p>
|
||||||
|
<b>شماره ثبت: </b>
|
||||||
|
{{ person.sabt }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="center">
|
||||||
|
<p>
|
||||||
|
<b>شماره اقتصادی: </b>
|
||||||
|
{{ person.codeeghtesadi }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="center">
|
||||||
|
<p>
|
||||||
|
<b>تلفن / نمابر:</b>
|
||||||
|
{{ person.tel }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="" colspan="1">
|
||||||
|
<p>
|
||||||
|
<b>کد پستی:</b>
|
||||||
|
{{ person.postalcode }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td class="" colspan="3">
|
||||||
|
<p>
|
||||||
|
<b>آدرس: </b>
|
||||||
|
استان {{ person.ostan }}، شهر {{ person.shahr }}، {{ person.address }}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="width:100%;margin-top:5px;text-align:center;">
|
||||||
|
<table style="width:100%;">
|
||||||
|
<thead>
|
||||||
|
<tr class="stimol" style="background-color:gray;">
|
||||||
|
<th class="text-white" style="width:80px">ردیف</th>
|
||||||
|
<th class="text-white">کالا/خدمات</th>
|
||||||
|
<th class="text-white">شرح</th>
|
||||||
|
<th class="text-white">تعداد / مقدار</th>
|
||||||
|
<th class="text-white">مبلغ واحد</th>
|
||||||
|
{% if printOptions.discountInfo %}
|
||||||
|
<th class="text-white">تخفیف</th>
|
||||||
|
{% endif %}
|
||||||
|
{% if printOptions.taxInfo %}
|
||||||
|
<th class="text-white">مالیات</th>
|
||||||
|
{% endif %}
|
||||||
|
<th class="text-white">مبلغ کل</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% set taxAll = 0 %}
|
||||||
|
{% set rowIndex = 0 %}
|
||||||
|
{% for item in items %}
|
||||||
|
{% if doc.taxPercent %}
|
||||||
|
{% set itemTax = (item.bs * item.commodityCount * doc.taxPercent / 100) | round %}
|
||||||
|
{% else %}
|
||||||
|
{% set itemTax = item.tax %}
|
||||||
|
{% endif %}
|
||||||
|
{% set taxAll = taxAll + itemTax %}
|
||||||
|
{% set rowIndex = rowIndex + 1 %}
|
||||||
|
<tr class="stimol">
|
||||||
|
<td class="center item">{{ rowIndex }}</td>
|
||||||
|
<td class="center item">
|
||||||
|
{{ item.commodity.code }} - {{ item.commodity.name }}
|
||||||
|
</td>
|
||||||
|
<td class="center item">{{ item.des }}</td>
|
||||||
|
<td class="center item">
|
||||||
|
{{ item.commodityCount }} {{ item.commodity.unit.name }}
|
||||||
|
</td>
|
||||||
|
<td class="center item">{{ item.bs|number_format(0, '.', ',', doc.money.shortName) }}</td>
|
||||||
|
{% if printOptions.discountInfo %}
|
||||||
|
<td class="center item">
|
||||||
|
{% if item.showPercentDiscount %}
|
||||||
|
{{ item.discountPercent }}%
|
||||||
|
({{ (item.bs * item.commodityCount * item.discountPercent / 100)|round|number_format(0, '.', ',', doc.money.shortName) }})
|
||||||
|
{% else %}
|
||||||
|
{{ item.discountAmount|number_format(0, '.', ',', doc.money.shortName) }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
{% if printOptions.taxInfo %}
|
||||||
|
<td class="center item">
|
||||||
|
{{ itemTax|number_format(0, '.', ',', doc.money.shortName) }}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
<td class="center item">
|
||||||
|
{% if item.showPercentDiscount %}
|
||||||
|
{{ (item.bs * item.commodityCount - (item.bs * item.commodityCount * item.discountPercent / 100)|round)|number_format(0, '.', ',', doc.money.shortName) }}
|
||||||
|
{% else %}
|
||||||
|
{{ (item.bs * item.commodityCount - item.discountAmount)|number_format(0, '.', ',', doc.money.shortName) }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="width:100%;margin-top:0px;text-align:center;">
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr class="stimol">
|
||||||
|
<td class="item" style="width:70%;padding:1%">
|
||||||
|
<h4>
|
||||||
|
توضیحات: {{ doc.des }}
|
||||||
|
<br>
|
||||||
|
{% if printOptions.note == true %}
|
||||||
|
<h4 class="">یادداشت:</h4>
|
||||||
|
<ul class="">
|
||||||
|
<li class="">{{ note }}</li>
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</h4>
|
||||||
|
</td>
|
||||||
|
<td class="item" style="width:15%;padding:1%">
|
||||||
|
{% set totalDiscount = doc.showTotalPercentDiscount ? (doc.amount * doc.totalDiscountPercent / 100) | round : doc.totalDiscount %}
|
||||||
|
<h4>تخفیف: {{ totalDiscount|number_format(0, '.', ',', doc.money.shortName) }}</h4>
|
||||||
|
<h4>مالیات: {{ taxAll|number_format(0, '.', ',', doc.money.shortName) }}</h4>
|
||||||
|
<h4>حمل و نقل: {{ doc.shippingCost|number_format(0, '.', ',', doc.money.shortName) }}</h4>
|
||||||
|
<h4>جمع کل: {{ doc.amount|number_format(0, '.', ',', doc.money.shortName) }}</h4>
|
||||||
|
<h4>جمع کل نهایی: {{ (doc.amount + taxAll - totalDiscount + doc.shippingCost)|number_format(0, '.', ',', doc.money.shortName) }}</h4>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="width:40%;margin-top:0px;text-align:center;float:left;">
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr class="">
|
||||||
|
<td class="center" style="height:90px">
|
||||||
|
<h4>مهر و امضا خریدار</h4>
|
||||||
|
</td>
|
||||||
|
<td class="center" style="height:90px">
|
||||||
|
<h4>مهر و امضا فروشنده:</h4>
|
||||||
|
<br>
|
||||||
|
<img src="{{ url('front_seal_file_get', {id: bid.id}) }}" width="160"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
527
webUI/src/components/forms/Hcommoditysearch.vue
Normal file
527
webUI/src/components/forms/Hcommoditysearch.vue
Normal file
|
@ -0,0 +1,527 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<v-menu v-model="menu" :close-on-content-click="false">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-text-field
|
||||||
|
v-bind="props"
|
||||||
|
v-model="displayValue"
|
||||||
|
variant="outlined"
|
||||||
|
:error-messages="errorMessages"
|
||||||
|
:rules="combinedRules"
|
||||||
|
:label="label"
|
||||||
|
class=""
|
||||||
|
prepend-inner-icon="mdi-package-variant"
|
||||||
|
clearable
|
||||||
|
@click:clear="clearSelection"
|
||||||
|
:loading="loading"
|
||||||
|
@keydown.enter="handleEnter"
|
||||||
|
hide-details="auto"
|
||||||
|
>
|
||||||
|
<template v-slot:append-inner>
|
||||||
|
<v-icon>{{ menu ? 'mdi-chevron-up' : 'mdi-chevron-down' }}</v-icon>
|
||||||
|
</template>
|
||||||
|
</v-text-field>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<v-card min-width="300" max-width="400">
|
||||||
|
<v-card-text class="pa-2">
|
||||||
|
<template v-if="!loading">
|
||||||
|
<v-list density="compact" class="list-container">
|
||||||
|
<template v-if="filteredItems.length > 0">
|
||||||
|
<v-list-item
|
||||||
|
v-for="item in filteredItems"
|
||||||
|
:key="item.id"
|
||||||
|
@click="selectItem(item)"
|
||||||
|
class="mb-1"
|
||||||
|
>
|
||||||
|
<v-list-item-title class="text-right">{{ item.name }}</v-list-item-title>
|
||||||
|
<v-list-item-subtitle class="text-right">{{ item.code }}</v-list-item-subtitle>
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<v-list-item>
|
||||||
|
<v-list-item-title class="text-center text-grey">
|
||||||
|
نتیجهای یافت نشد
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
</v-list>
|
||||||
|
<v-btn
|
||||||
|
v-if="filteredItems.length === 0"
|
||||||
|
block
|
||||||
|
color="primary"
|
||||||
|
class="mt-2"
|
||||||
|
@click="showAddDialog = true"
|
||||||
|
>
|
||||||
|
افزودن کالا/خدمت جدید
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-progress-circular
|
||||||
|
v-else
|
||||||
|
indeterminate
|
||||||
|
color="primary"
|
||||||
|
class="d-flex mx-auto my-4"
|
||||||
|
></v-progress-circular>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-menu>
|
||||||
|
|
||||||
|
<v-dialog v-model="showAddDialog" :fullscreen="$vuetify.display.mobile" max-width="800">
|
||||||
|
<v-card>
|
||||||
|
<v-toolbar color="primary" density="compact" class="sticky-toolbar">
|
||||||
|
<v-toolbar-title>افزودن کالا/خدمت جدید</v-toolbar-title>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-tooltip text="بستن">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-close"
|
||||||
|
v-bind="props"
|
||||||
|
@click="showAddDialog = false"
|
||||||
|
></v-btn>
|
||||||
|
</template>
|
||||||
|
</v-tooltip>
|
||||||
|
<v-tooltip text="ذخیره">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-content-save"
|
||||||
|
v-bind="props"
|
||||||
|
@click="saveCommodity"
|
||||||
|
:loading="saving"
|
||||||
|
></v-btn>
|
||||||
|
</template>
|
||||||
|
</v-tooltip>
|
||||||
|
</v-toolbar>
|
||||||
|
|
||||||
|
<v-tabs
|
||||||
|
v-model="tabs"
|
||||||
|
color="primary"
|
||||||
|
show-arrows
|
||||||
|
class="sticky-tabs"
|
||||||
|
>
|
||||||
|
<v-tab value="basic" class="flex-grow-1">اطلاعات پایه</v-tab>
|
||||||
|
<v-tab value="details" class="flex-grow-1">جزئیات</v-tab>
|
||||||
|
<v-tab value="pricing" class="flex-grow-1">قیمتگذاری</v-tab>
|
||||||
|
</v-tabs>
|
||||||
|
|
||||||
|
<v-card-text class="content-container">
|
||||||
|
<v-window v-model="tabs">
|
||||||
|
<v-window-item value="basic">
|
||||||
|
<v-form @submit.prevent="saveCommodity">
|
||||||
|
<v-row class="mt-4">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.name"
|
||||||
|
label="نام کالا/خدمت *"
|
||||||
|
required
|
||||||
|
:error-messages="nameErrors"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.code"
|
||||||
|
label="کد"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-select
|
||||||
|
v-model="newCommodity.type"
|
||||||
|
:items="commodityTypes"
|
||||||
|
label="نوع *"
|
||||||
|
required
|
||||||
|
:error-messages="typeErrors"
|
||||||
|
></v-select>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-select
|
||||||
|
v-model="newCommodity.unit"
|
||||||
|
:items="units"
|
||||||
|
label="واحد اندازهگیری *"
|
||||||
|
required
|
||||||
|
:error-messages="unitErrors"
|
||||||
|
></v-select>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-textarea
|
||||||
|
v-model="newCommodity.description"
|
||||||
|
label="توضیحات"
|
||||||
|
rows="3"
|
||||||
|
></v-textarea>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-form>
|
||||||
|
</v-window-item>
|
||||||
|
|
||||||
|
<v-window-item value="details">
|
||||||
|
<v-row class="mt-4">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.brand"
|
||||||
|
label="برند"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.model"
|
||||||
|
label="مدل"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.barcode"
|
||||||
|
label="بارکد"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.serial"
|
||||||
|
label="سریال"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-switch
|
||||||
|
v-model="newCommodity.isService"
|
||||||
|
label="خدمت"
|
||||||
|
color="primary"
|
||||||
|
></v-switch>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-window-item>
|
||||||
|
|
||||||
|
<v-window-item value="pricing">
|
||||||
|
<v-row class="mt-4">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.basePrice"
|
||||||
|
label="قیمت پایه"
|
||||||
|
type="number"
|
||||||
|
prefix="ریال"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.salePrice"
|
||||||
|
label="قیمت فروش"
|
||||||
|
type="number"
|
||||||
|
prefix="ریال"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.minStock"
|
||||||
|
label="حداقل موجودی"
|
||||||
|
type="number"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newCommodity.maxStock"
|
||||||
|
label="حداکثر موجودی"
|
||||||
|
type="number"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-window-item>
|
||||||
|
</v-window>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
|
||||||
|
<v-snackbar
|
||||||
|
v-model="snackbar.show"
|
||||||
|
:color="snackbar.color"
|
||||||
|
:timeout="3000"
|
||||||
|
>
|
||||||
|
{{ snackbar.text }}
|
||||||
|
<template v-slot:actions>
|
||||||
|
<v-btn
|
||||||
|
color="white"
|
||||||
|
variant="text"
|
||||||
|
@click="snackbar.show = false"
|
||||||
|
>
|
||||||
|
بستن
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Hcommoditysearch',
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: [Object, Number],
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: 'کالا/خدمت'
|
||||||
|
},
|
||||||
|
returnObject: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedItem: null,
|
||||||
|
items: [],
|
||||||
|
loading: false,
|
||||||
|
menu: false,
|
||||||
|
searchQuery: '',
|
||||||
|
totalItems: 0,
|
||||||
|
currentPage: 1,
|
||||||
|
itemsPerPage: 10,
|
||||||
|
searchTimeout: null,
|
||||||
|
showAddDialog: false,
|
||||||
|
tabs: 'basic',
|
||||||
|
saving: false,
|
||||||
|
commodityTypes: ['کالا', 'خدمت'],
|
||||||
|
units: ['عدد', 'کیلوگرم', 'گرم', 'متر', 'سانتیمتر', 'لیتر', 'متر مربع', 'متر مکعب'],
|
||||||
|
snackbar: {
|
||||||
|
show: false,
|
||||||
|
text: '',
|
||||||
|
color: 'success'
|
||||||
|
},
|
||||||
|
errorMessages: [],
|
||||||
|
newCommodity: {
|
||||||
|
name: '',
|
||||||
|
code: '',
|
||||||
|
type: '',
|
||||||
|
unit: '',
|
||||||
|
description: '',
|
||||||
|
brand: '',
|
||||||
|
model: '',
|
||||||
|
barcode: '',
|
||||||
|
serial: '',
|
||||||
|
isService: false,
|
||||||
|
basePrice: 0,
|
||||||
|
salePrice: 0,
|
||||||
|
minStock: 0,
|
||||||
|
maxStock: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
filteredItems() {
|
||||||
|
return Array.isArray(this.items) ? this.items : []
|
||||||
|
},
|
||||||
|
displayValue: {
|
||||||
|
get() {
|
||||||
|
if (this.menu) {
|
||||||
|
return this.searchQuery
|
||||||
|
}
|
||||||
|
return this.selectedItem ? this.selectedItem.name : this.searchQuery
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.searchQuery = value
|
||||||
|
if (!value) {
|
||||||
|
this.clearSelection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nameErrors() {
|
||||||
|
if (!this.newCommodity.name) return ['نام کالا/خدمت الزامی است']
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
typeErrors() {
|
||||||
|
if (!this.newCommodity.type) return ['نوع کالا/خدمت الزامی است']
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
unitErrors() {
|
||||||
|
if (!this.newCommodity.unit) return ['واحد اندازهگیری الزامی است']
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
combinedRules() {
|
||||||
|
return [
|
||||||
|
v => !!v || 'انتخاب کالا/خدمت الزامی است',
|
||||||
|
...this.rules
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
modelValue: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (this.returnObject) {
|
||||||
|
this.selectedItem = newVal
|
||||||
|
} else {
|
||||||
|
this.selectedItem = this.items.find(item => item.id === newVal)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
searchQuery: {
|
||||||
|
handler(newVal) {
|
||||||
|
this.currentPage = 1
|
||||||
|
if (this.searchTimeout) {
|
||||||
|
clearTimeout(this.searchTimeout)
|
||||||
|
}
|
||||||
|
this.searchTimeout = setTimeout(() => {
|
||||||
|
this.fetchData()
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showAddDialog: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.newCommodity.name = this.searchQuery
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showMessage(text: string, color = 'success') {
|
||||||
|
this.snackbar.text = text
|
||||||
|
this.snackbar.color = color
|
||||||
|
this.snackbar.show = true
|
||||||
|
},
|
||||||
|
async fetchData() {
|
||||||
|
this.loading = true
|
||||||
|
try {
|
||||||
|
const response = await axios.post('/api/commodity/list', {
|
||||||
|
page: this.currentPage,
|
||||||
|
itemsPerPage: this.itemsPerPage,
|
||||||
|
search: this.searchQuery,
|
||||||
|
sortBy: null
|
||||||
|
})
|
||||||
|
|
||||||
|
if (response.data && Array.isArray(response.data)) {
|
||||||
|
this.items = response.data
|
||||||
|
this.totalItems = response.data.length
|
||||||
|
} else if (response.data && response.data.items) {
|
||||||
|
this.items = response.data.items
|
||||||
|
this.totalItems = response.data.total || response.data.items.length
|
||||||
|
} else {
|
||||||
|
this.items = []
|
||||||
|
this.totalItems = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.modelValue) {
|
||||||
|
if (this.returnObject) {
|
||||||
|
this.selectedItem = this.modelValue
|
||||||
|
} else {
|
||||||
|
this.selectedItem = this.items.find(item => item.id === this.modelValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.showMessage('خطا در بارگذاری دادهها', 'error')
|
||||||
|
this.items = []
|
||||||
|
this.totalItems = 0
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async saveCommodity() {
|
||||||
|
if (!this.newCommodity.name) {
|
||||||
|
this.showMessage('نام کالا/خدمت الزامی است', 'error')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.newCommodity.type) {
|
||||||
|
this.showMessage('نوع کالا/خدمت الزامی است', 'error')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.newCommodity.unit) {
|
||||||
|
this.showMessage('واحد اندازهگیری الزامی است', 'error')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saving = true
|
||||||
|
try {
|
||||||
|
const response = await axios.post('/api/commodity/mod/' + this.newCommodity.code, this.newCommodity)
|
||||||
|
if (response.data.Success) {
|
||||||
|
if (response.data.result === 1) {
|
||||||
|
this.showMessage('کالا/خدمت با موفقیت ثبت شد')
|
||||||
|
this.showAddDialog = false
|
||||||
|
this.fetchData()
|
||||||
|
} else if (response.data.result === 2) {
|
||||||
|
this.showMessage('این کالا/خدمت قبلاً ثبت شده است', 'error')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.showMessage('خطا در ثبت کالا/خدمت', 'error')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('خطا در ثبت کالا/خدمت:', error)
|
||||||
|
this.showMessage('خطا در ثبت کالا/خدمت', 'error')
|
||||||
|
} finally {
|
||||||
|
this.saving = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectItem(item: any) {
|
||||||
|
this.selectedItem = item
|
||||||
|
this.searchQuery = item.name
|
||||||
|
this.$emit('update:modelValue', this.returnObject ? item : item.id)
|
||||||
|
this.menu = false
|
||||||
|
this.errorMessages = []
|
||||||
|
},
|
||||||
|
clearSelection() {
|
||||||
|
this.selectedItem = null
|
||||||
|
this.searchQuery = ''
|
||||||
|
this.$emit('update:modelValue', null)
|
||||||
|
this.errorMessages = ['انتخاب کالا/خدمت الزامی است']
|
||||||
|
},
|
||||||
|
handleEnter() {
|
||||||
|
if (!this.loading && this.filteredItems.length === 0) {
|
||||||
|
this.showAddDialog = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.fetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.list-container {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-container {
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky-toolbar {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky-tabs {
|
||||||
|
position: sticky;
|
||||||
|
top: 48px;
|
||||||
|
z-index: 1;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.v-menu__content) {
|
||||||
|
position: fixed !important;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
transform-origin: center top !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.v-overlay__content) {
|
||||||
|
position: fixed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.content-container {
|
||||||
|
max-height: calc(100vh - 120px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky-tabs {
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -9,7 +9,11 @@
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
dense
|
dense
|
||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
/>
|
>
|
||||||
|
<template v-for="(_, slot) in $slots" #[slot]="props">
|
||||||
|
<slot :name="slot" v-bind="props" />
|
||||||
|
</template>
|
||||||
|
</v-text-field>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -89,4 +93,9 @@ export default {
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.v-text-field .v-input__prepend-inner) {
|
||||||
|
padding-right: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -11,7 +11,10 @@ const en_lang = {
|
||||||
ok: "Ok",
|
ok: "Ok",
|
||||||
cancel: "Cancel",
|
cancel: "Cancel",
|
||||||
save: "Save",
|
save: "Save",
|
||||||
active_account:"Active Account"
|
active_account:"Active Account",
|
||||||
|
presell_info: "Presell Information",
|
||||||
|
financial_info: "Financial Information",
|
||||||
|
invoice_items: "Invoice Items",
|
||||||
},
|
},
|
||||||
app:{
|
app:{
|
||||||
name:"Hesabix",
|
name:"Hesabix",
|
||||||
|
@ -75,6 +78,14 @@ const en_lang = {
|
||||||
businesses: "Businesses",
|
businesses: "Businesses",
|
||||||
business_create: "Create Business",
|
business_create: "Create Business",
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
drawer:{
|
||||||
|
cheques: "Cheques",
|
||||||
|
cheque: "Cheque",
|
||||||
|
cheque_input: "Cheque Input",
|
||||||
|
cheque_output: "Cheque Output",
|
||||||
|
presells: "Presells",
|
||||||
|
presell_view: "View Presell",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default en_lang
|
export default en_lang
|
||||||
|
|
|
@ -113,6 +113,8 @@ const fa_lang = {
|
||||||
transfer: "انتقال",
|
transfer: "انتقال",
|
||||||
cheques: "چکها",
|
cheques: "چکها",
|
||||||
cheque: "چک",
|
cheque: "چک",
|
||||||
|
cheque_input: "دریافت چک",
|
||||||
|
cheque_output: "صدور چک",
|
||||||
commodity: "کالا و خدمات",
|
commodity: "کالا و خدمات",
|
||||||
commodity_list: "فهرست کالا و خدمات",
|
commodity_list: "فهرست کالا و خدمات",
|
||||||
docs: "اسناد حسابداری",
|
docs: "اسناد حسابداری",
|
||||||
|
@ -160,6 +162,7 @@ const fa_lang = {
|
||||||
accounting: "حسابداری",
|
accounting: "حسابداری",
|
||||||
accounting_table: "جدول حسابها",
|
accounting_table: "جدول حسابها",
|
||||||
presells: "پیش فاکتورها",
|
presells: "پیش فاکتورها",
|
||||||
|
presell_view: "مشاهده پیش فاکتور",
|
||||||
reports: "گزارشات",
|
reports: "گزارشات",
|
||||||
settings: "تنظیمات",
|
settings: "تنظیمات",
|
||||||
bid_settings: "تنظیمات کسبوکار",
|
bid_settings: "تنظیمات کسبوکار",
|
||||||
|
@ -465,6 +468,9 @@ const fa_lang = {
|
||||||
"manage_columns": "مدیریت ستونها",
|
"manage_columns": "مدیریت ستونها",
|
||||||
customize_columns: "شخصیسازی ستونها",
|
customize_columns: "شخصیسازی ستونها",
|
||||||
close_dialog: "بستن",
|
close_dialog: "بستن",
|
||||||
|
presell_info: "اطلاعات پیش فاکتور",
|
||||||
|
financial_info: "اطلاعات مالی",
|
||||||
|
invoice_items: "اقلام فاکتور",
|
||||||
},
|
},
|
||||||
app: {
|
app: {
|
||||||
loading: "در حال بارگذاری...",
|
loading: "در حال بارگذاری...",
|
||||||
|
|
|
@ -152,7 +152,7 @@ export default {
|
||||||
{ path: '/acc/costs/list', key: 'G', label: this.$t('drawer.costs'), ctrl: true, shift: true, permission: () => this.permissions.cost },
|
{ path: '/acc/costs/list', key: 'G', label: this.$t('drawer.costs'), ctrl: true, shift: true, permission: () => this.permissions.cost },
|
||||||
{ path: '/acc/sell/fast-mod', key: 'J', label: this.$t('drawer.fast_sell'), ctrl: true, shift: true, permission: () => this.permissions.sell },
|
{ path: '/acc/sell/fast-mod', key: 'J', label: this.$t('drawer.fast_sell'), ctrl: true, shift: true, permission: () => this.permissions.sell },
|
||||||
{ path: '/acc/sell/list', key: 'V', label: this.$t('drawer.sell_invoices'), ctrl: true, shift: true, permission: () => this.permissions.sell },
|
{ path: '/acc/sell/list', key: 'V', label: this.$t('drawer.sell_invoices'), ctrl: true, shift: true, permission: () => this.permissions.sell },
|
||||||
{ path: '/acc/presell/list', key: 'X', label: this.$t('drawer.presells'), ctrl: true, shift: true, permission: () => this.permissions.sell && this.isPluginActive('accpro') && (1 == 2) },
|
{ path: '/acc/presell/list', key: 'X', label: this.$t('drawer.presells'), ctrl: true, shift: true, permission: () => this.permissions.sell && this.isPluginActive('accpro') },
|
||||||
{ path: '/acc/rfsell/list', key: 'Z', label: this.$t('drawer.rfsell_invoices'), ctrl: true, shift: true, permission: () => this.permissions.plugAccproRfsell && this.isPluginActive('accpro') },
|
{ path: '/acc/rfsell/list', key: 'Z', label: this.$t('drawer.rfsell_invoices'), ctrl: true, shift: true, permission: () => this.permissions.plugAccproRfsell && this.isPluginActive('accpro') },
|
||||||
{ path: '/acc/incomes/list', key: 'A', label: this.$t('drawer.incomes'), ctrl: true, shift: true, permission: () => this.permissions.income },
|
{ path: '/acc/incomes/list', key: 'A', label: this.$t('drawer.incomes'), ctrl: true, shift: true, permission: () => this.permissions.income },
|
||||||
{ path: '/acc/accounting/list', key: '1', label: this.$t('drawer.accounting_docs'), ctrl: true, shift: true, permission: () => this.permissions.accounting },
|
{ path: '/acc/accounting/list', key: '1', label: this.$t('drawer.accounting_docs'), ctrl: true, shift: true, permission: () => this.permissions.accounting },
|
||||||
|
@ -468,6 +468,27 @@ export default {
|
||||||
{{ $t('drawer.cheques') }}
|
{{ $t('drawer.cheques') }}
|
||||||
<span v-if="isCtrlShiftPressed" class="shortcut-key">{{ getShortcutKey('/acc/cheque/list') }}</span>
|
<span v-if="isCtrlShiftPressed" class="shortcut-key">{{ getShortcutKey('/acc/cheque/list') }}</span>
|
||||||
</v-list-item-title>
|
</v-list-item-title>
|
||||||
|
<template v-slot:append>
|
||||||
|
<v-menu>
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn v-bind="props" icon="mdi-plus-box" variant="plain" @click.stop.prevent />
|
||||||
|
</template>
|
||||||
|
<v-list>
|
||||||
|
<v-list-item to="/acc/cheque/input">
|
||||||
|
<v-list-item-title>
|
||||||
|
<v-icon color="success" class="mr-2">mdi-arrow-down-bold</v-icon>
|
||||||
|
{{ $t('drawer.cheque_input') }}
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
<v-list-item to="/acc/cheque/output">
|
||||||
|
<v-list-item-title>
|
||||||
|
<v-icon color="error" class="mr-2">mdi-arrow-up-bold</v-icon>
|
||||||
|
{{ $t('drawer.cheque_output') }}
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-menu>
|
||||||
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item v-if="permissions.bankTransfer" to="/acc/transfer/list">
|
<v-list-item v-if="permissions.bankTransfer" to="/acc/transfer/list">
|
||||||
<v-list-item-title>
|
<v-list-item-title>
|
||||||
|
@ -600,7 +621,7 @@ export default {
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item v-if="this.isPluginActive('accpro') && permissions.sell && (1 == 2)" to="/acc/presell/list">
|
<v-list-item v-if="this.isPluginActive('accpro') && permissions.sell" to="/acc/presell/list">
|
||||||
<v-list-item-title>
|
<v-list-item-title>
|
||||||
{{ $t('drawer.presells') }}
|
{{ $t('drawer.presells') }}
|
||||||
<span v-if="isCtrlShiftPressed" class="shortcut-key">{{ getShortcutKey('/acc/presell/list') }}</span>
|
<span v-if="isCtrlShiftPressed" class="shortcut-key">{{ getShortcutKey('/acc/presell/list') }}</span>
|
||||||
|
@ -650,7 +671,7 @@ export default {
|
||||||
{{ $t('drawer.accounting_docs') }}
|
{{ $t('drawer.accounting_docs') }}
|
||||||
<span v-if="isCtrlShiftPressed" class="shortcut-key">{{ getShortcutKey('/acc/accounting/list') }}</span>
|
<span v-if="isCtrlShiftPressed" class="shortcut-key">{{ getShortcutKey('/acc/accounting/list') }}</span>
|
||||||
</v-list-item-title>
|
</v-list-item-title>
|
||||||
<template v-slot:append v-if="isPluginActive('accpro') && 1==2">
|
<template v-slot:append v-if="isPluginActive('accpro')">
|
||||||
<v-tooltip :text="$t('dialog.add_new')" location="end">
|
<v-tooltip :text="$t('dialog.add_new')" location="end">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<v-btn v-bind="props" icon="mdi-plus-box" variant="plain" to="/acc/accounting/mod/" />
|
<v-btn v-bind="props" icon="mdi-plus-box" variant="plain" to="/acc/accounting/mod/" />
|
||||||
|
|
|
@ -6,24 +6,49 @@ import { ref } from 'vue';
|
||||||
import Loading from 'vue-loading-overlay';
|
import Loading from 'vue-loading-overlay';
|
||||||
import 'vue-loading-overlay/dist/css/index.css';
|
import 'vue-loading-overlay/dist/css/index.css';
|
||||||
|
|
||||||
|
interface MostDesItem {
|
||||||
|
id: number;
|
||||||
|
des: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SubmitData {
|
||||||
|
id: number | null;
|
||||||
|
des: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "mostdes",
|
name: "mostdes",
|
||||||
components: {
|
components: {
|
||||||
Loading
|
Loading
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
submitData: Object,
|
submitData: {
|
||||||
type: String,
|
type: Object as () => SubmitData,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
emits: ['update:modelValue'],
|
||||||
watch: {
|
watch: {
|
||||||
search: {
|
search: {
|
||||||
handler: function (val, oldVal) {
|
handler: function (val: string, oldVal: string) {
|
||||||
if (val == '') {
|
if (val == '') {
|
||||||
this.items = this.orgItems;
|
this.items = this.orgItems;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const temp = [];
|
const temp: MostDesItem[] = [];
|
||||||
this.orgItems.forEach((item) => {
|
this.orgItems.forEach((item: MostDesItem) => {
|
||||||
if (item.des.includes(val)) {
|
if (item.des.includes(val)) {
|
||||||
temp.push(item);
|
temp.push(item);
|
||||||
}
|
}
|
||||||
|
@ -37,10 +62,10 @@ export default defineComponent({
|
||||||
data: () => {
|
data: () => {
|
||||||
return {
|
return {
|
||||||
loading: ref(false),
|
loading: ref(false),
|
||||||
items: [],
|
items: [] as MostDesItem[],
|
||||||
orgItems: [],
|
orgItems: [] as MostDesItem[],
|
||||||
des: '',
|
des: '',
|
||||||
selected: 0,
|
selected: null as MostDesItem | null,
|
||||||
search: '',
|
search: '',
|
||||||
dialog: false,
|
dialog: false,
|
||||||
}
|
}
|
||||||
|
@ -57,7 +82,7 @@ export default defineComponent({
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
remove(id: any) {
|
remove(id: number) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
axios.post('/api/mostdes/remove/' + id).then((response) => {
|
axios.post('/api/mostdes/remove/' + id).then((response) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
@ -95,12 +120,14 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
selectItem(item: any) {
|
selectItem(item: MostDesItem) {
|
||||||
this.selected = item;
|
this.selected = item;
|
||||||
this.$props.submitData.id = item.id;
|
if (this.$props.submitData) {
|
||||||
this.$props.submitData.des = item.des;
|
this.$props.submitData.id = item.id;
|
||||||
|
this.$props.submitData.des = item.des;
|
||||||
|
this.$emit('update:modelValue', item.des);
|
||||||
|
}
|
||||||
this.dialog = false;
|
this.dialog = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -118,7 +145,7 @@ export default defineComponent({
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<v-dialog v-model="dialog">
|
<v-dialog v-model="dialog">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-header>
|
<v-card-title>
|
||||||
<v-toolbar class="fixed-top" color="toolbar" :title="$t('dialog.most_des')">
|
<v-toolbar class="fixed-top" color="toolbar" :title="$t('dialog.most_des')">
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<v-tooltip :text="$t('dialog.close')" location="bottom">
|
<v-tooltip :text="$t('dialog.close')" location="bottom">
|
||||||
|
@ -129,7 +156,7 @@ export default defineComponent({
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</v-toolbar>
|
</v-toolbar>
|
||||||
</v-card-header>
|
</v-card-title>
|
||||||
<v-card-text class="mt-5">
|
<v-card-text class="mt-5">
|
||||||
<v-text-field class="mb-2" v-model="search" :loading="loading" prepend-inner-icon="mdi-magnify"
|
<v-text-field class="mb-2" v-model="search" :loading="loading" prepend-inner-icon="mdi-magnify"
|
||||||
:label="$t('dialog.search')" variant="outlined" hide-details single-line></v-text-field>
|
:label="$t('dialog.search')" variant="outlined" hide-details single-line></v-text-field>
|
||||||
|
|
|
@ -19,28 +19,6 @@
|
||||||
<v-btn v-bind="props" icon="mdi-delete" color="danger" @click="deleteItems()"></v-btn>
|
<v-btn v-bind="props" icon="mdi-delete" color="danger" @click="deleteItems()"></v-btn>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<v-menu>
|
|
||||||
<template v-slot:activator="{ props }">
|
|
||||||
<v-btn v-bind="props" icon="" color="green">
|
|
||||||
<v-tooltip activator="parent" :text="$t('dialog.change_labels')" location="bottom" />
|
|
||||||
<v-icon icon="mdi-dots-horizontal-circle"></v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
<v-list>
|
|
||||||
<v-list-subheader color="primary">{{ $t('dialog.change_labels') }}</v-list-subheader>
|
|
||||||
<v-list-item v-for="item in types" class="text-dark" :title="$t('dialog.change_to') + ' ' + item.label"
|
|
||||||
@click="changeLabel(item)">
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<v-icon color="green-darken-4" icon="mdi-label"></v-icon>
|
|
||||||
</template>
|
|
||||||
</v-list-item>
|
|
||||||
<v-list-item class="text-dark" :title="$t('dialog.delete_labels')" @click="changeLabel('clear')">
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<v-icon color="red" icon="mdi-undo"></v-icon>
|
|
||||||
</template>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-menu>
|
|
||||||
</v-toolbar>
|
</v-toolbar>
|
||||||
<v-row class="pa-1">
|
<v-row class="pa-1">
|
||||||
<v-col>
|
<v-col>
|
||||||
|
@ -53,30 +31,6 @@
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:append-inner>
|
|
||||||
<v-menu :close-on-content-click="false">
|
|
||||||
<template v-slot:activator="{ props }">
|
|
||||||
<v-icon size="sm" v-bind="props" icon="" color="primary">
|
|
||||||
<v-tooltip activator="parent" variant="plain" :text="$t('dialog.filters')" location="bottom" />
|
|
||||||
<v-icon icon="mdi-filter"></v-icon>
|
|
||||||
</v-icon>
|
|
||||||
</template>
|
|
||||||
<v-list>
|
|
||||||
<v-list-subheader color="primary">
|
|
||||||
<v-icon icon="mdi-filter"></v-icon>
|
|
||||||
{{ $t('dialog.filters') }}</v-list-subheader>
|
|
||||||
<v-list-item v-for="(item, index) in types" class="text-dark">
|
|
||||||
<template v-slot:title>
|
|
||||||
<div class="form-check form-check-inline mx-1">
|
|
||||||
<input @change="filterTable()" v-model="types[index].checked" checked="" class="form-check-input"
|
|
||||||
type="checkbox">
|
|
||||||
<label class="form-check-label">{{ item.label }}</label>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-menu>
|
|
||||||
</template>
|
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
<EasyDataTable table-class-name="customize-table" :table-class-name="tableClassName"
|
<EasyDataTable table-class-name="customize-table" :table-class-name="tableClassName"
|
||||||
v-model:items-selected="itemsSelected" multi-sort show-index alternating :search-value="searchValue"
|
v-model:items-selected="itemsSelected" multi-sort show-index alternating :search-value="searchValue"
|
||||||
|
@ -100,7 +54,7 @@
|
||||||
<v-icon icon="mdi-file-pdf-box"></v-icon>
|
<v-icon icon="mdi-file-pdf-box"></v-icon>
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item class="text-dark" :title="$t('dialog.edit')" @click="canEditItem(code)">
|
<v-list-item class="text-dark" :title="$t('dialog.edit')" :to="'/acc/presell/mod/' + code">
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<v-icon icon="mdi-file-edit"></v-icon>
|
<v-icon icon="mdi-file-edit"></v-icon>
|
||||||
</template>
|
</template>
|
||||||
|
@ -113,15 +67,8 @@
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
</template>
|
</template>
|
||||||
<template #item-label="{ label }">
|
|
||||||
<span v-if="label">
|
|
||||||
<span v-if="label.code == 'payed'" class="text-success">{{ label.label }}</span>
|
|
||||||
<span v-if="label.code == 'returned'" class="text-danger">{{ label.label }}</span>
|
|
||||||
<span v-if="label.code == 'accepted'" class="text-info">{{ label.label }}</span>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #item-des="{ des }">
|
<template #item-des="{ des }">
|
||||||
{{ des.replace("فاکتور فروش:", "") }}
|
{{ des.replace("پیش فاکتور فروش:", "") }}
|
||||||
</template>
|
</template>
|
||||||
<template #item-relatedDocsCount="{ relatedDocsCount, relatedDocsPays }">
|
<template #item-relatedDocsCount="{ relatedDocsCount, relatedDocsPays }">
|
||||||
<span v-if="relatedDocsCount != '0'" class="text-success"><i class="fa fa-money"></i>
|
<span v-if="relatedDocsCount != '0'" class="text-success"><i class="fa fa-money"></i>
|
||||||
|
@ -152,6 +99,11 @@
|
||||||
{{ $filters.formatNumber(discountAll) }}
|
{{ $filters.formatNumber(discountAll) }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template #item-totalAmount="{ totalAmount }">
|
||||||
|
<span class="text-dark">
|
||||||
|
{{ $filters.formatNumber(totalAmount) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<template #item-person="{ person }">
|
<template #item-person="{ person }">
|
||||||
<router-link :to="'/acc/persons/card/view/' + person.code">
|
<router-link :to="'/acc/persons/card/view/' + person.code">
|
||||||
{{ person.nikename }}
|
{{ person.nikename }}
|
||||||
|
@ -173,8 +125,6 @@
|
||||||
</v-select>
|
</v-select>
|
||||||
<v-switch inset v-model="printOptions.bidInfo" color="primary" :label="$t('dialog.bid_info_label')"
|
<v-switch inset v-model="printOptions.bidInfo" color="primary" :label="$t('dialog.bid_info_label')"
|
||||||
hide-details></v-switch>
|
hide-details></v-switch>
|
||||||
<v-switch inset v-model="printOptions.pays" color="primary" :label="$t('dialog.invoice_pays')"
|
|
||||||
hide-details></v-switch>
|
|
||||||
<v-switch inset v-model="printOptions.note" color="primary" :label="$t('dialog.invoice_footer_note')"
|
<v-switch inset v-model="printOptions.note" color="primary" :label="$t('dialog.invoice_footer_note')"
|
||||||
hide-details></v-switch>
|
hide-details></v-switch>
|
||||||
<v-switch inset v-model="printOptions.taxInfo" color="primary" :label="$t('dialog.tax_dexpo')"
|
<v-switch inset v-model="printOptions.taxInfo" color="primary" :label="$t('dialog.tax_dexpo')"
|
||||||
|
@ -192,12 +142,69 @@
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
<!-- End Print Modal -->
|
<!-- End Print Modal -->
|
||||||
|
<!-- Delete Dialog -->
|
||||||
|
<v-dialog v-model="deleteDialog" width="auto">
|
||||||
|
<v-card>
|
||||||
|
<v-card-title class="text-h5">
|
||||||
|
حذف فاکتور
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
آیا مطمئن هستید؟
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn color="primary" variant="text" @click="confirmDelete">
|
||||||
|
بله
|
||||||
|
</v-btn>
|
||||||
|
<v-btn color="error" variant="text" @click="deleteDialog = false">
|
||||||
|
خیر
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
|
||||||
|
<!-- Delete Group Dialog -->
|
||||||
|
<v-dialog v-model="deleteGroupDialog" width="auto">
|
||||||
|
<v-card>
|
||||||
|
<v-card-title class="text-h5">
|
||||||
|
حذف گروهی
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
آیا مطمئن هستید؟
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn color="primary" variant="text" @click="confirmDeleteGroup">
|
||||||
|
بله
|
||||||
|
</v-btn>
|
||||||
|
<v-btn color="error" variant="text" @click="deleteGroupDialog = false">
|
||||||
|
خیر
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
<!-- Snackbar -->
|
||||||
|
<v-snackbar
|
||||||
|
v-model="snackbar.show"
|
||||||
|
:color="snackbar.color"
|
||||||
|
:timeout="3000"
|
||||||
|
>
|
||||||
|
{{ snackbar.text }}
|
||||||
|
<template v-slot:actions>
|
||||||
|
<v-btn
|
||||||
|
color="white"
|
||||||
|
variant="text"
|
||||||
|
@click="snackbar.show = false"
|
||||||
|
>
|
||||||
|
بستن
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Swal from "sweetalert2";
|
import { ref, defineComponent } from "vue";
|
||||||
import { ref ,defineComponent } from "vue";
|
|
||||||
|
|
||||||
export default defineComponent ({
|
export default defineComponent ({
|
||||||
name: "list",
|
name: "list",
|
||||||
|
@ -224,7 +231,6 @@ export default defineComponent ({
|
||||||
],
|
],
|
||||||
modal: false,
|
modal: false,
|
||||||
printOptions: {
|
printOptions: {
|
||||||
pays: true,
|
|
||||||
note: true,
|
note: true,
|
||||||
bidInfo: true,
|
bidInfo: true,
|
||||||
taxInfo: true,
|
taxInfo: true,
|
||||||
|
@ -236,7 +242,6 @@ export default defineComponent ({
|
||||||
sumTotal: 0,
|
sumTotal: 0,
|
||||||
itemsSelected: [],
|
itemsSelected: [],
|
||||||
searchValue: '',
|
searchValue: '',
|
||||||
types: [],
|
|
||||||
loading: ref(true),
|
loading: ref(true),
|
||||||
items: [],
|
items: [],
|
||||||
orgItems: [],
|
orgItems: [],
|
||||||
|
@ -248,99 +253,26 @@ export default defineComponent ({
|
||||||
{ text: "تخفیف", value: "discountAll", sortable: true },
|
{ text: "تخفیف", value: "discountAll", sortable: true },
|
||||||
{ text: "حمل و نقل", value: "transferCost", sortable: true },
|
{ text: "حمل و نقل", value: "transferCost", sortable: true },
|
||||||
{ text: "مبلغ", value: "amount", sortable: true },
|
{ text: "مبلغ", value: "amount", sortable: true },
|
||||||
{ text: "سود فاکتور", value: "profit", sortable: true },
|
{ text: "مبلغ کل", value: "totalAmount", sortable: true },
|
||||||
{ text: "پرداختی", value: "relatedDocsCount", sortable: true },
|
|
||||||
{ text: "برچسب", value: "label", width: 100 },
|
|
||||||
{ text: "شرح", value: "des", sortable: true },
|
{ text: "شرح", value: "des", sortable: true },
|
||||||
]
|
],
|
||||||
|
deleteDialog: false,
|
||||||
|
deleteGroupDialog: false,
|
||||||
|
selectedCode: null,
|
||||||
|
snackbar: {
|
||||||
|
show: false,
|
||||||
|
text: '',
|
||||||
|
color: 'success'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changeLabel(label) {
|
|
||||||
if (this.itemsSelected.length == 0) {
|
|
||||||
Swal.fire({
|
|
||||||
text: 'هیچ موردی انتخاب نشده است.',
|
|
||||||
icon: 'warning',
|
|
||||||
confirmButtonText: 'قبول'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.loading = true;
|
|
||||||
axios.post('/api/presell/label/change', {
|
|
||||||
'items': this.itemsSelected,
|
|
||||||
'label': label
|
|
||||||
}
|
|
||||||
).then((response) => {
|
|
||||||
this.loading == false;
|
|
||||||
if (response.data.code == 0) {
|
|
||||||
Swal.fire({
|
|
||||||
text: 'فاکتورها با موفقیت ویرایش شد.',
|
|
||||||
icon: 'success',
|
|
||||||
confirmButtonText: 'قبول'
|
|
||||||
});
|
|
||||||
this.itemsSelected = [];
|
|
||||||
}
|
|
||||||
else if (response.data.result == 2) {
|
|
||||||
Swal.fire({
|
|
||||||
text: response.data.message,
|
|
||||||
icon: 'warning',
|
|
||||||
confirmButtonText: 'قبول'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.loadData();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
filterTable() {
|
|
||||||
this.loading = true;
|
|
||||||
let calcItems = [];
|
|
||||||
let isAll = true;
|
|
||||||
let selectedTypes = [];
|
|
||||||
this.types.forEach((item) => {
|
|
||||||
if (item.checked == true) {
|
|
||||||
isAll = false;
|
|
||||||
selectedTypes.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (isAll) {
|
|
||||||
this.items = this.orgItems;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.orgItems.forEach((item) => {
|
|
||||||
selectedTypes.forEach((st) => {
|
|
||||||
if (item.label) {
|
|
||||||
if (st.code == item.label.code) {
|
|
||||||
let existBefore = false;
|
|
||||||
calcItems.forEach((ri) => {
|
|
||||||
if (item.label.code == ri.code) {
|
|
||||||
existBefore = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (existBefore == false) {
|
|
||||||
calcItems.push(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.items = calcItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loading = false;
|
|
||||||
},
|
|
||||||
loadData() {
|
loadData() {
|
||||||
axios.post("/api/printers/options/info").then((response) => {
|
axios.post("/api/printers/options/info").then((response) => {
|
||||||
this.printOptions = response.data.sell;
|
this.printOptions = response.data.sell;
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.post('/api/invoice/types', {
|
axios.post('/api/preinvoice/docs/search')
|
||||||
type: 'sell'
|
|
||||||
}).then((response) => {
|
|
||||||
this.types = response.data;
|
|
||||||
});
|
|
||||||
|
|
||||||
axios.post('/api/presell/docs/search')
|
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.items = response.data;
|
this.items = response.data;
|
||||||
this.orgItems = response.data;
|
this.orgItems = response.data;
|
||||||
|
@ -350,53 +282,59 @@ export default defineComponent ({
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
showSnackbar(text, color = 'success') {
|
||||||
|
this.snackbar.text = text;
|
||||||
|
this.snackbar.color = color;
|
||||||
|
this.snackbar.show = true;
|
||||||
|
},
|
||||||
deleteItems() {
|
deleteItems() {
|
||||||
if (this.itemsSelected.length == 0) {
|
if (this.itemsSelected.length == 0) {
|
||||||
Swal.fire({
|
this.showSnackbar('لطفا حداقل یک پیش فاکتور را انتخاب کنید.', 'warning');
|
||||||
text: 'هیچ موردی انتخاب نشده است.',
|
return;
|
||||||
icon: 'warning',
|
|
||||||
confirmButtonText: 'قبول'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else {
|
this.deleteGroupDialog = true;
|
||||||
Swal.fire({
|
},
|
||||||
text: 'آیا برای حذف این مورد مطمئن هستید؟ تمامی اسناد پرداخت و حواله های انبار همراه فاکتور نیز حذف خواهند شد.',
|
confirmDeleteGroup() {
|
||||||
showCancelButton: true,
|
this.loading = true;
|
||||||
confirmButtonText: 'بله',
|
this.deleteGroupDialog = false;
|
||||||
cancelButtonText: `خیر`,
|
axios.post('/api/preinvoice/remove/group', {
|
||||||
icon: 'warning'
|
'items': this.itemsSelected
|
||||||
}).then((result) => {
|
}).then((response) => {
|
||||||
/* Read more about isConfirmed, isDenied below */
|
this.loading = false;
|
||||||
if (result.isConfirmed) {
|
if (response.data.result == 1) {
|
||||||
this.loading = true;
|
this.loadData();
|
||||||
axios.post('/api/accounting/remove/group', {
|
this.showSnackbar('فاکتورها با موفقیت حذف شد.', 'success');
|
||||||
'items': this.itemsSelected
|
}
|
||||||
|
else if (response.data.result == 2) {
|
||||||
|
this.showSnackbar(response.data.message, 'warning');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
deleteItem(code) {
|
||||||
|
this.selectedCode = code;
|
||||||
|
this.deleteDialog = true;
|
||||||
|
},
|
||||||
|
confirmDelete() {
|
||||||
|
this.deleteDialog = false;
|
||||||
|
axios.post('/api/preinvoice/delete/' + this.selectedCode).then((response) => {
|
||||||
|
if (response.data.result == 1) {
|
||||||
|
let index = 0;
|
||||||
|
for (let z = 0; z < this.items.length; z++) {
|
||||||
|
index++;
|
||||||
|
if (this.items[z]['code'] == this.selectedCode) {
|
||||||
|
this.items.splice(index - 1, 1);
|
||||||
}
|
}
|
||||||
).then((response) => {
|
|
||||||
this.loading = false;
|
|
||||||
if (response.data.result == 1) {
|
|
||||||
this.loadData();
|
|
||||||
Swal.fire({
|
|
||||||
text: 'فاکتور ها با موفقیت حذف شد.',
|
|
||||||
icon: 'success',
|
|
||||||
confirmButtonText: 'قبول'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (response.data.result == 2) {
|
|
||||||
Swal.fire({
|
|
||||||
text: response.data.message,
|
|
||||||
icon: 'warning',
|
|
||||||
confirmButtonText: 'قبول'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
this.showSnackbar('فاکتور با موفقیت حذف شد.', 'success');
|
||||||
}
|
}
|
||||||
|
else if (response.data.result == 2) {
|
||||||
|
this.showSnackbar(response.data.message, 'warning');
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
printInvoice(pdf = true, cloudePrinters = true) {
|
printInvoice(pdf = true, cloudePrinters = true) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
axios.post('/api/presell/print/invoice', {
|
axios.post('/api/preinvoice/print/invoice', {
|
||||||
'code': this.printOptions.selectedPrintCode,
|
'code': this.printOptions.selectedPrintCode,
|
||||||
'pdf': pdf,
|
'pdf': pdf,
|
||||||
'printers': cloudePrinters,
|
'printers': cloudePrinters,
|
||||||
|
@ -406,45 +344,10 @@ export default defineComponent ({
|
||||||
window.open(this.$API_URL + '/front/print/' + response.data.id, '_blank', 'noreferrer');
|
window.open(this.$API_URL + '/front/print/' + response.data.id, '_blank', 'noreferrer');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteItem(code) {
|
isNumeric(str) {
|
||||||
Swal.fire({
|
if (typeof str != "string") return false;
|
||||||
text: 'آیا برای حذف این مورد مطمئن هستید؟ تمامی اسناد پرداخت و حواله های انبار همراه فاکتور نیز حذف خواهند شد.',
|
return !isNaN(str) && !isNaN(parseFloat(str));
|
||||||
showCancelButton: true,
|
},
|
||||||
confirmButtonText: 'بله',
|
|
||||||
cancelButtonText: `خیر`,
|
|
||||||
icon: 'warning'
|
|
||||||
}).then((result) => {
|
|
||||||
/* Read more about isConfirmed, isDenied below */
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
axios.post('/api/accounting/remove', {
|
|
||||||
'code': code
|
|
||||||
}
|
|
||||||
).then((response) => {
|
|
||||||
if (response.data.result == 1) {
|
|
||||||
let index = 0;
|
|
||||||
for (let z = 0; z < this.items.length; z++) {
|
|
||||||
index++;
|
|
||||||
if (this.items[z]['code'] == code) {
|
|
||||||
this.items.splice(index - 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Swal.fire({
|
|
||||||
text: 'فاکتور فروش با موفقیت حذف شد.',
|
|
||||||
icon: 'success',
|
|
||||||
confirmButtonText: 'قبول'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (response.data.result == 2) {
|
|
||||||
Swal.fire({
|
|
||||||
text: response.data.message,
|
|
||||||
icon: 'warning',
|
|
||||||
confirmButtonText: 'قبول'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
this.loadData();
|
this.loadData();
|
||||||
|
@ -454,11 +357,11 @@ export default defineComponent ({
|
||||||
handler: function (val, oldVal) {
|
handler: function (val, oldVal) {
|
||||||
this.sumSelected = 0;
|
this.sumSelected = 0;
|
||||||
this.itemsSelected.forEach((item) => {
|
this.itemsSelected.forEach((item) => {
|
||||||
if (typeof item.amount.valueOf() === "string") {
|
if (typeof item.totalAmount.valueOf() === "string") {
|
||||||
this.sumSelected += parseInt(item.amount.replaceAll(",", ""))
|
this.sumSelected += parseInt(item.totalAmount.replaceAll(",", ""))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.sumSelected += item.amount;
|
this.sumSelected += item.totalAmount;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -470,26 +373,40 @@ export default defineComponent ({
|
||||||
this.items = this.orgItems;
|
this.items = this.orgItems;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
const searchTerm = this.searchValue.toLowerCase().replace(/,/g, '');
|
||||||
let temp = [];
|
let temp = [];
|
||||||
this.orgItems.forEach((item) => {
|
this.orgItems.forEach((item) => {
|
||||||
if (item.person.nikename.includes(this.searchValue)) {
|
// جستجو در فیلدهای متنی
|
||||||
temp.push(item)
|
const personFields = [
|
||||||
|
item.person?.nikename,
|
||||||
|
item.person?.name,
|
||||||
|
item.person?.family,
|
||||||
|
item.person?.mobile,
|
||||||
|
item.person?.phone,
|
||||||
|
item.person?.address
|
||||||
|
].filter(Boolean); // حذف مقادیر undefined
|
||||||
|
|
||||||
|
const hasPersonMatch = personFields.some(field =>
|
||||||
|
field.toLowerCase().includes(searchTerm)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasPersonMatch ||
|
||||||
|
item.des.toLowerCase().includes(searchTerm) ||
|
||||||
|
item.code.includes(searchTerm)) {
|
||||||
|
temp.push(item);
|
||||||
}
|
}
|
||||||
else if (item.date.includes(this.searchValue)) {
|
// جستجو در فیلدهای عددی
|
||||||
temp.push(item)
|
else if (this.isNumeric(searchTerm)) {
|
||||||
}
|
const searchNumber = parseFloat(searchTerm);
|
||||||
else if (item.amount.toString().includes(this.searchValue)) {
|
if (item.amount == searchNumber ||
|
||||||
temp.push(item)
|
item.totalAmount == searchNumber ||
|
||||||
}
|
item.discountAll == searchNumber ||
|
||||||
else if (item.des.includes(this.searchValue)) {
|
item.transferCost == searchNumber ||
|
||||||
temp.push(item)
|
item.amount.toString().includes(searchTerm) ||
|
||||||
}
|
item.totalAmount.toString().includes(searchTerm) ||
|
||||||
else if (item.code.includes(this.searchValue)) {
|
item.discountAll.toString().includes(searchTerm) ||
|
||||||
temp.push(item)
|
item.transferCost.toString().includes(searchTerm)) {
|
||||||
}
|
temp.push(item);
|
||||||
else if (item.label) {
|
|
||||||
if (item.label.label.includes(this.searchValue)) {
|
|
||||||
temp.push(item)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -502,4 +419,11 @@ export default defineComponent ({
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped>
|
||||||
|
.v-card {
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
.v-dialog {
|
||||||
|
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
</style>
|
File diff suppressed because it is too large
Load diff
170
webUI/src/views/acc/presell/view.vue
Normal file
170
webUI/src/views/acc/presell/view.vue
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<v-dialog v-model="dialog" fullscreen @update:model-value="handleDialogClose">
|
||||||
|
<v-card>
|
||||||
|
<v-toolbar color="toolbar" :title="$t('drawer.presell_view')">
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<v-tooltip :text="$t('dialog.back')" location="bottom">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn v-bind="props" @click="handleDialogClose(false)" class="d-none d-sm-flex" variant="text"
|
||||||
|
icon="mdi-arrow-right" />
|
||||||
|
</template>
|
||||||
|
</v-tooltip>
|
||||||
|
</template>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-tooltip :text="$t('dialog.export_pdf')" location="bottom">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn v-bind="props" icon="mdi-file-pdf-box" color="primary" @click="printInvoice()"></v-btn>
|
||||||
|
</template>
|
||||||
|
</v-tooltip>
|
||||||
|
</v-toolbar>
|
||||||
|
|
||||||
|
<v-card-text>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-card class="mb-4" :title="$t('dialog.presell_info')">
|
||||||
|
<v-card-text>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field :model-value="presellData.code" :label="$t('dialog.code')" readonly></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field :model-value="presellData.date" :label="$t('dialog.date')" readonly></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field :model-value="presellData.person?.nikename" :label="$t('dialog.person')" readonly>
|
||||||
|
</v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field :model-value="presellData.des" :label="$t('dialog.des')" readonly></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-card class="mb-4" :title="$t('dialog.financial_info')">
|
||||||
|
<v-card-text>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field :model-value="$filters.formatNumber(presellData.amount)" :label="$t('dialog.amount')"
|
||||||
|
readonly></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field :model-value="$filters.formatNumber(presellData.totalDiscount)"
|
||||||
|
:label="$t('dialog.discount')" readonly></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field :model-value="$filters.formatNumber(presellData.shippingCost)"
|
||||||
|
:label="$t('dialog.transfer_cost')" readonly></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field :model-value="$filters.formatNumber(presellData.totalAmount)"
|
||||||
|
:label="$t('dialog.total_amount')" readonly></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-card :title="$t('dialog.invoice_items')">
|
||||||
|
<v-card-text>
|
||||||
|
<EasyDataTable table-class-name="customize-table" :headers="itemsHeaders" :items="presellData.items"
|
||||||
|
theme-color="#1d90ff" header-text-direction="center" body-text-direction="center"
|
||||||
|
rowsPerPageMessage="تعداد سطر" emptyMessage="اطلاعاتی برای نمایش وجود ندارد">
|
||||||
|
<template #item-count="{ count }">
|
||||||
|
{{ $filters.formatNumber(count) }}
|
||||||
|
</template>
|
||||||
|
<template #item-price="{ price }">
|
||||||
|
{{ $filters.formatNumber(price) }}
|
||||||
|
</template>
|
||||||
|
<template #item-discountAmount="{ discountAmount }">
|
||||||
|
{{ $filters.formatNumber(discountAmount) }}
|
||||||
|
</template>
|
||||||
|
<template #item-total="{ total }">
|
||||||
|
{{ $filters.formatNumber(total) }}
|
||||||
|
</template>
|
||||||
|
</EasyDataTable>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from "axios";
|
||||||
|
import { ref, defineComponent } from "vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "PresellView",
|
||||||
|
props: {
|
||||||
|
code: {
|
||||||
|
type: [String, Number],
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialog: this.modelValue,
|
||||||
|
presellData: {},
|
||||||
|
itemsHeaders: [
|
||||||
|
{ text: "کد کالا", value: "itemCode" },
|
||||||
|
{ text: "نام کالا", value: "itemName" },
|
||||||
|
{ text: "تعداد", value: "count" },
|
||||||
|
{ text: "قیمت", value: "price" },
|
||||||
|
{ text: "مبلغ", value: "amount" },
|
||||||
|
{ text: "جمع", value: "total" }
|
||||||
|
],
|
||||||
|
printOptions: {
|
||||||
|
note: true,
|
||||||
|
bidInfo: true,
|
||||||
|
taxInfo: true,
|
||||||
|
discountInfo: true,
|
||||||
|
paper: 'A4-L'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleDialogClose(value) {
|
||||||
|
this.dialog = value;
|
||||||
|
this.$emit('update:modelValue', value);
|
||||||
|
this.$emit('close');
|
||||||
|
},
|
||||||
|
loadData() {
|
||||||
|
axios.post('/api/preinvoice/get/' + this.code)
|
||||||
|
.then((response) => {
|
||||||
|
this.presellData = response.data;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
printInvoice() {
|
||||||
|
axios.post('/api/preinvoice/print/invoice', {
|
||||||
|
'code': this.code,
|
||||||
|
'pdf': true,
|
||||||
|
'printers': true,
|
||||||
|
'printOptions': this.printOptions
|
||||||
|
}).then((response) => {
|
||||||
|
window.open(this.$API_URL + '/front/print/' + response.data.id, '_blank', 'noreferrer');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.v-card {
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue