Multimag  0.2.992
sborka_zap.php
См. документацию.
1 <?php
2 
3 // MultiMag v0.2 - Complex sales system
4 //
5 // Copyright (C) 2005-2018, BlackLight, TND Team, http://tndproject.org
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
16 //
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //
20 
21 include_once('include/doc.zapposeditor.php');
22 
25 
26  protected function processForm() {
27  global $tmpl, $db;
28  $tmpl->addContent("<h1>" . $this->getname() . "</h1>
29  <script type='text/javascript' src='/css/jquery/jquery.autocomplete.js'></script>
30  <form action='' method='post' enctype='multipart/form-data'>
31  <input type='hidden' name='mode' value='create'>
32  <input type='hidden' name='param' value='i'>
33  <input type='hidden' name='sn' value='sborka_zap'>
34  Склад:<br><select name='store_id'>");
35  $sres = $db->query("SELECT `id`,`name` FROM `doc_sklady` ORDER BY `id`");
36  while ($nxt = $sres->fetch_row()) {
37  $tmpl->addContent("<option value='$nxt[0]'>" . html_out($nxt[1]) . "</option>");
38  }
39  $tmpl->addContent("</select><br>Организация:<br><select name='firm_id'>");
40  $rs = $db->query("SELECT `id`, `firm_name` FROM `doc_vars` ORDER BY `firm_name`");
41  while ($nx = $rs->fetch_row()) {
42  $tmpl->addContent("<option value='$nx[0]'>" . html_out($nx[1]) . "</option>");
43  }
44  $tmpl->addContent("</select><br>
45  Агент:<br>
46  <input type='hidden' name='agent_id' id='agent_id' value=''>
47  <input type='text' id='agent_nm' style='width: 450px;' value=''><br>
48  Услуга начисления зарплаты:<br>
49  <select name='service_id'>");
50  $res=$db->query("SELECT `id`,`name` FROM `doc_base` WHERE `pos_type`=1 ORDER BY `name`");
51  while($nxt=$res->fetch_row()) {
52  $tmpl->addContent("<option value='$nxt[0]'>".html_out($nxt[1])."</option>");
53  }
54  $tmpl->addContent("</select>
55  Переместить готовый товар на склад:<br>
56  <select name='to_store_id'>
57  <option value='0' selected>--не требуется--</option>");
58  $res = $db->query("SELECT `id`,`name` FROM `doc_sklady` ORDER BY `id`");
59  while ($nxt = $res->fetch_row()) {
60  $tmpl->addContent("<option value='$nxt[0]'>" . html_out($nxt[1]) . "</option>");
61  }
62  $tmpl->addContent("</select><br>
63  Кладовщик, принимающий готовый товар на складе:<br><select name='storekeeper_id'>");
64  $res = $db->query("SELECT `user_id`, `worker_real_name` FROM `users_worker_info` WHERE `worker`='1' ORDER BY `worker_real_name`");
65  while ($nxt = $res->fetch_row()) {
66  $tmpl->addContent("<option value='$nxt[0]'>" . html_out($nxt[1]) . "</option>");
67  }
68  $tmpl->addContent("</select><br>
69  <label><input type='checkbox' name='not_a_p' value='1'>Не проводить перемещение</label><br>
70 
71  <script type=\"text/javascript\">
72  $(document).ready(function(){
73  $(\"#agent_nm\").autocomplete(\"/docs.php\", {delay:300,minChars:1,matchSubset:1,autoFill:false,selectFirst:true,matchContains:1,cacheLength:10,
74  maxItemsToShow:15,formatItem:agliFormat,onItemSelect:agselectItem,extraParams:{'l':'agent','mode':'srv','opt':'ac'}});
75  $(\"#tov\").autocomplete(\"/docs.php\", {delay:300,minChars:1,matchSubset:1,autoFill:false,selectFirst:true,matchContains:1,cacheLength:10,
76  maxItemsToShow:15,formatItem:tovliFormat,onItemSelect:tovselectItem,extraParams:{'l':'sklad','mode':'srv','opt':'ac'}});
77  });
78  function agliFormat (row, i, num) { var result = row[0] + \"<em class='qnt'>тел. \" + row[2] + \"</em> \";return result;}
79  function agselectItem(li) {if( li == null ) var sValue = \"Ничего не выбрано!\";if( !!li.extra ) var sValue = li.extra[0];else var sValue = li.selectValue;document.getElementById('agent_id').value=sValue;}
80  function tovliFormat (row, i, num) {var result = row[0] + \"<em class='qnt'>\" + row[2] + \"</em> \";return result;}
81  function tovselectItem(li) {if( li == null ) var sValue = \"Ничего не выбрано!\";if( !!li.extra ) var sValue = li.extra[0];else var sValue = li.selectValue;document.getElementById('tov_id').value=sValue;}
82  </script>
83  <button type='submit'>Выполнить</button>
84  </form>
85  ");
86  }
87 
88  protected function processCreate() {
89  $agent_id = rcvint('agent_id');
90  $store_id = rcvint('store_id');
91  $to_store_id = rcvint('to_store_id');
92  $firm_id = rcvint('firm_id');
93  $service_id = rcvint('service_id');
94  $not_a_p = rcvint('not_a_p');
95  $storekeeper_id = rcvint('storekeeper_id');
96 
97  $doc_data = array(
98  'firm_id' => $firm_id,
99  'subtype' => '',
100  'sklad' => $store_id,
101  'agent' => $agent_id
102  );
103  $dop_data = array(
104  'cena' => 1,
105  'script' => 'sborka_zap',
106  'nasklad' => $to_store_id,
107  'service_id' => $service_id,
108  'not_a_p' => $not_a_p,
109  'storekeeper_id' => $storekeeper_id,
110  );
111  $doc_obj = new doc_Sborka();
112  $doc_id = $doc_obj->create($doc_data);
113  $doc_obj->setDopDataA($dop_data);
114  redirect("/doc_sc.php?mode=edit&sn=sborka_zap&doc=$doc_id");
115  }
116 
117  protected function processReopen() {
118  $doc_id = rcvint('doc');
120  $doc_data = $doc_obj->getDocDataA();
121  $dop_data = $doc_obj->getDopDataA();
122  if ($doc_data['ok']) {
123  throw new Exception("Операция не допускается для проведённого документа");
124  }
125  if (!isset($dop_data['script'])) {
126  throw new \Exception("Этот документ создан вручную, а не через сценарий. Недостаточно информации для редактирования документа через сценарий.");
127  } elseif($dop_data['script'] != 'sborka_zap') {
128  throw new \Exception("Этот документ создан через другой сценарий. Редактирование через этот сценарий невозможно.");
129  }
130  $doc_obj->setDopData('cena', 1);
131  redirect("/doc_sc.php?mode=edit&sn=sborka_zap&doc=$doc_id");
132  }
133 
134  protected function processEdit() {
135  global $tmpl;
136  $doc_id = rcvint('doc');
138  $doc_data = $doc_obj->getDocDataA();
139  $dop_data = $doc_obj->getDopDataA();
140 
141  $zp = $this->CalcZP($doc_id);
142  $tmpl->addContent("<h1>" . $this->getname() . "</h1>
143 Необходимо выбрать товары, которые будут скомплектованы. Устанавливать цену не требуется - при проведении документа она будет выставлена автоматически исходя из стоимости затраченных ресурсов. Для того, чтобы узнать цены - обновите страницу. После выполнения сценария выбранные товары будут оприходованы на склад, а соответствующее им количество ресурсов, использованных для сборки, будет списано. Попытка провести через этот сценарий товары, не содержащие ресурсов, вызовет ошибку. Если это указано в свойствах товара, от агента-сборщика будет оприходована выбранная услуга для последующей выдачи заработной платы (на данный момент в размере $zp руб.).<br>
144 <a href='/doc_sc.php?mode=exec&amp;sn=sborka_zap&amp;doc=$doc_id'>Выполнить необходимые действия</a>
145 <script type='text/javascript' src='/css/jquery/jquery.autocomplete.js'></script>");
146 
147  $this->ReCalcPosPrices($doc_obj);
148  $poseditor = new SZapPosEditor($doc_obj);
149  $poseditor->cost_id = $dop_data['cena'];
150  $poseditor->SetEditable($doc_data['ok'] ? 0 : 1);
151  $poseditor->sklad_id = $doc_data['sklad'];
152  $poseditor->updateDocSum();
153  $tmpl->addContent($poseditor->Show());
154  }
155 
156  protected function processExec() {
157  global $db, $tmpl;
158  $doc_id = rcvint('doc');
159 
160  $db->startTransaction();
162  $this->ReCalcPosPrices($document);
163  $poseditor = new SZapPosEditor($document);
164  $poseditor->updateDocSum();
165  $document->DocApply();
166  $zp = $this->CalcZP($doc_id);
167  $store_id = $document->getDocData('sklad');
168  $to_store_id = $document->getDopData('nasklad');
169  $storekeeper_id = $document->getDopData('storekeeper_id');
170  $not_a_p = $document->getDopData('not_a_p');
171  $service_id = $document->getDopData('service_id');
172  if(!$store_id) {
173  throw new Exception('Склад сборки не задан');
174  }
175  if(!$service_id) {
176  throw new Exception('Услуга работы не задана');
177  }
178  if(!$not_a_p && !$to_store_id) {
179  throw new Exception('Склад назначения не задан');
180  }
181 
182 
183  // Проверка, создано ли уже поступление зарплаты
184  $res = $db->query("SELECT `id` FROM `doc_list` WHERE `type`='1' AND `p_doc`='$doc_id'");
185  if ($res->num_rows) {
186  list($post_doc) = $res->fetch_row();
187  $db->query("UPDATE `doc_list_pos` SET `cost`='$zp' WHERE `doc`='$post_doc'");
188  $db->query("UPDATE `doc_list` SET `sum`='$zp' WHERE `id`='$post_doc'");
189  } else {
190  $p_obj = new doc_Postuplenie();
191  $p_doc_id = $p_obj->createFrom($document);
192  $db->query("INSERT INTO `doc_list_pos` (`doc`, `tovar`, `cnt`, `cost`) VALUES ('$p_doc_id', '$service_id', '1', '$zp')");
193  $p_obj->setDocData('sum', $zp);
194  $p_obj->DocApply();
195  }
196 
197  // Проверка, создано ли уже перемещение
198  $res = $db->query("SELECT `id` FROM `doc_list` WHERE `type`='8' AND `p_doc`='$doc_id'");
199  if ($res->num_rows) {
200  list($perem_doc_num) = $res->fetch_row();
201  $r = $db->query("SELECT `value` FROM `doc_dopdata` WHERE `doc`='$perem_doc_num' AND `param`='na_sklad'");
202  list($to_store_id) = $r->fetch_row();
203  $perem_doc = new doc_Peremeshenie($perem_doc_num);
204  } else if (($store_id != $to_store_id) && $to_store_id) {
205  $perem_doc = new doc_Peremeshenie();
206  $perem_doc->createFrom($document);
207  $perem_doc->setDopData('kladovshik', $storekeeper_id);
208  $perem_doc->setDopData('na_sklad', $to_store_id);
209  $perem_doc->setDopData('mest', 1);
210  }
211 
212  if (($store_id != $to_store_id) && $to_store_id) {
213  $docnum = $perem_doc->getId();
214  $res = $db->query("SELECT `tovar`, `cnt`, `cost` FROM `doc_list_pos` WHERE `doc`='$doc_id' AND `page`='0'");
215  while ($nxt = $res->fetch_row()) {
216  $db->query("INSERT INTO `doc_list_pos` (`doc`, `tovar`, `cnt`, `cost`, `page`)
217  VALUES ('$docnum', '$nxt[0]', '$nxt[1]', '$nxt[2]', '0')");
218  }
219 
220  if (!$not_a_p) {
221  $perem_doc->DocApply();
222  }
223  }
224  $db->commit();
225  $tmpl->ajax = 0;
226  $tmpl->msg("Все операции выполнены успешно. Размер зарплаты: $zp");
227  }
228 
229  protected function processSrv() {
230  global $tmpl;
231  $peopt = request('peopt');
232  $doc = rcvint('doc');
233  $document = new doc_Sborka($doc);
234  $poseditor = new SZapPosEditor($document);
235  $dd = $document->getDopDataA();
236  $poseditor->cost_id = $dd['cena'];
237  $dd = $document->getDocDataA();
238  $poseditor->sklad_id = $dd['sklad'];
239  $tmpl->ajax = 1;
240  $tmpl->setContent('');
241 
242  // Json-вариант списка товаров
243  if ($peopt == 'jget') {
244  $doc_sum = $document->recalcSum();
245  $str = "{ response: 'loadlist', content: [" . $poseditor->GetAllContent() . "], sum: '$doc_sum' }";
246  $tmpl->addContent($str);
247  }
248  // Получение данных наименования
249  else if ($peopt == 'jgpi') {
250  $pos = rcvint('pos');
251  $tmpl->addContent($poseditor->GetPosInfo($pos));
252  } else if ($peopt == 'jgetgroups') {
253  $doc_content = $poseditor->getGroupList();
254  $tmpl->addContent($doc_content);
255  }
256  // Json вариант добавления позиции
257  else if ($peopt == 'jadd') {
258  \acl::accessGuard('doc.sborka', \acl::UPDATE);
259  $pe_pos = rcvint('pe_pos');
260  $tmpl->setContent($poseditor->AddPos($pe_pos));
261  }
262  // Json вариант удаления строки
263  else if ($peopt == 'jdel') {
264  \acl::accessGuard('doc.sborka', \acl::UPDATE);
265  $line_id = rcvint('line_id');
266  $tmpl->setContent($poseditor->Removeline($line_id));
267  }
268  // Json вариант обновления
269  else if ($peopt == 'jup') {
270  \acl::accessGuard('doc.sborka', \acl::UPDATE);
271  $line_id = rcvint('line_id');
272  $value = request('value');
273  $type = request('type');
274  $tmpl->setContent($poseditor->UpdateLine($line_id, $type, $value));
275  }
276  // Получение номенклатуры выбранной группы
277  else if ($peopt == 'jsklad') {
278  $group_id = rcvint('group_id');
279  $str = "{ response: 'sklad_list', group: '$group_id', content: [" . $poseditor->GetSkladList($group_id) . "] }";
280  $tmpl->setContent($str);
281  }
282  // Поиск по подстроке по складу
283  else if ($peopt == 'jsklads') {
284  $s = request('s');
285  $str = "{ response: 'sklad_list', content: " . $poseditor->SearchSkladList($s) . " }";
286  $tmpl->setContent($str);
287  } else {
288  throw new NotFoundException();
289  }
290  }
291 
292  function Run($mode) {
293  global $tmpl;
294  $tmpl->hideBlock('left');
295  switch ($mode) {
296  case 'view':
297  $this->processForm();
298  break;
299  case 'create':
300  $this->processCreate();
301  break;
302  case 'reopen':
303  $this->processReopen();
304  break;
305  case 'edit':
306  $this->processEdit();
307  break;
308  case 'exec':
309  $this->processExec();
310  break;
311  case 'srv':
312  $this->processSrv();
313  break;
314  default :
315  throw new \NotFoundException();
316  }
317  }
318 
319  function ReCalcPosPrices($doc_obj) {
320  global $db;
321  $doc_id = $doc_obj->getId();
322  $service_id = $doc_obj->getDopData('service_id');
323  $db->query("DELETE FROM `doc_list_pos` WHERE `doc`='$doc_id' AND `page`!='0'");
324  $res = $db->query("SELECT `id`, `tovar`, `cnt` FROM `doc_list_pos`
325  WHERE `doc`='$doc_id' AND `page`='0'");
326  while ($nxt = $res->fetch_row()) {
327  $cost = 0;
328  $rs = $db->query("SELECT `doc_base_kompl`.`kompl_id`, `doc_base_kompl`.`cnt`, `doc_base`.`cost` FROM `doc_base_kompl`
329  LEFT JOIN `doc_base` ON `doc_base`.`id`=`doc_base_kompl`.`kompl_id`
330  WHERE `doc_base_kompl`.`pos_id`='$nxt[1]'");
331  if ($rs->num_rows == 0) {
332  throw new \Exception("У товара $nxt[1] не заданы комплектующие");
333  }
334  while ($nx = $rs->fetch_row()) {
335  $acp = getInCost($nx[0], 0, true);
336  if ($acp > 0) {
337  $cost+=$nx[1] * $acp;
338  } else {
339  $cost+=$nx[1] * $nx[2];
340  }
341  $cntc = $nxt[2] * $nx[1];
342  if ($acp > 0) {
343  $db->query("INSERT INTO `doc_list_pos` (`doc`, `tovar`, `cnt`, `cost`, `page`)
344  VALUES ('$doc_id', '$nx[0]', '$cntc', '$acp', '$nxt[1]')");
345  } else {
346  $db->query("INSERT INTO `doc_list_pos` (`doc`, `tovar`, `cnt`, `cost`, `page`)
347  VALUES ('$doc_id', '$nx[0]', '$cntc', '$nx[2]', '$nxt[1]')");
348  }
349  }
350 
351  // Расчитываем зарплату
352  $r = $db->query("SELECT `doc_base_params`.`id`, `doc_base_values`.`value` FROM `doc_base_params`
353  LEFT JOIN `doc_base_values` ON `doc_base_values`.`param_id`=`doc_base_params`.`id` AND `doc_base_values`.`id`='$nxt[1]'
354  WHERE `doc_base_params`.`codename`='ZP'");
355  if ($r->num_rows) {
356  list($a, $zp) = $r->fetch_row();
357  $db->query("INSERT INTO `doc_list_pos` (`doc`, `tovar`, `cnt`, `cost`, `page`)
358  VALUES ('$doc_id', '$service_id', '$nxt[2]', '$zp', '$nxt[1]')");
359  $cost+=$zp;
360  } else {
361  $zp = 0;
362  }
363  $db->query("UPDATE `doc_list_pos` SET `cost`='$cost' WHERE `id`='$nxt[0]'");
364  }
365  }
366 
367  function CalcZP($doc) {
368  global $db;
369  $zp = 0;
370  $res = $db->query("SELECT `id`, `tovar`, `cnt` FROM `doc_list_pos` WHERE `doc`='$doc' AND `page`='0'");
371  while ($nxt = $res->fetch_row()) {
372  $rs = $db->query("SELECT `doc_base_values`.`value` FROM `doc_base_params`
373  LEFT JOIN `doc_base_values` ON `doc_base_values`.`param_id`=`doc_base_params`.`id` AND `doc_base_values`.`id`='$nxt[1]'
374  WHERE `doc_base_params`.`codename`='ZP'");
375  if (!$rs->num_rows) {
376  continue;
377  }
378  $n = $rs->fetch_row();
379  $zp+=$nxt[2] * $n[0];
380  }
381  return $zp;
382  }
383 
384  function getName() {
385  return "Сборка с выдачей заработной платы";
386  }
387 
388 }
$res
Definition: fixer.php:178
rcvint($varname, $def=0)
Безопасное получение целого значения
Definition: core.php:208
$n
Definition: images.php:31
Документ *сборка изделия*.
Definition: doc.sborka.php:21
getInCost($pos_id, $limit_date=0, $serv_mode=0)
Definition: doc.core.php:470
html_out($data)
Обёртка над htmlentities.
Definition: core.php:249
$firm_id
Definition: priceload.php:33
Сценарий автоматизации: сборка с перемещением и начислением заработной платы
Definition: sborka_zap.php:24
request($varname, $def='')
Definition: core.php:190
Документ *перемещение товара*.
$str
Definition: c_img.php:23
static getInstanceFromDb($doc_id)
Definition: document.php:146
$s
Definition: price_an.php:409
ReCalcPosPrices($doc_obj)
Definition: sborka_zap.php:319
$db
static accessGuard($object, $flags, $no_redirect=false)
То же, что и testAccess, но бросает исключение, если нет доступа
Definition: acl.php:213
$tmpl
$mode
Definition: 1c_sync.php:75
Документ *Поступление*.
$doc_id
Definition: test_doc.php:24
$doc
Definition: doc.php:28
const UPDATE
Обновление
Definition: acl.php:28
$r
Definition: keygen.php:23
Класс-исключение используется для информирования о отсутствии запрашиваемого объекта. Устанавливает заголовок 404 Not found.
Definition: core.php:633
redirect($url)
Отсылает заголовок перенаправления в броузер и завершает скрипт
Definition: core.php:118