• Есть схема БД для медицинского центра. Реализованы ли здесь первые три нормальные формы?

    (я не только корректность схемы тут рассматриваю)
    Вроде всё ок, только видно некоторое дублирование данных в пациенте и сотруднике.

    Можно (не обязательно) попробовать ввести сущность "человек" (название черновое), у которого будет информация о паспорте, имени, и прочем.
    И пусть пациент/сотрудник ссылается на него.

    Можно так достаточно интересную связь сделать, когда один и тот же человек является одновременно и сотрудником и пациентом. (И например ввести запрет на выписывание лекарств самому себе)

    В прайс-листе можно попробова выделить отдельную сущность "услуга" - тогда можно будет сделать интересное ценообразование, когда одна и та же услуга, оказываемая врачами разных категорий, имеет разную цену.

    Таблица с лекартсвами выглядит как справочник, тк никаких связей с другими таблицами не имеет.

    Возможно, есть смысл ввести ещё справочник действующих веществ, чтобы можно было быстрее искать конкретные лекарства по этому действующему веществу.

    Можно попытаться формализовать планы лечения - но это отдельная очень большая задача.

    К таблице с адресами ещё есть смысл добавить номер ФИАС/КЛАДР/ГАР (уже запутался в этих системах) - это распространённая практика в России.

    Не совсем понятно, почему связь между пациентами и адресами - это именно один-ко-многим, а не многие-ко-многим. В зависимости от оказываемых услуг и случаев может оказаться удобным указать несколько адресов.

    Не совсем понятно, почему к одному пользователю привязано несколько пациентов.
    Если это на случай, когда, например, в аккаунт родителя добавляется ещё и его ребёнок, то, возможно, есть смысл добавить возможность добавлять этого ребёнка в аккаунты обоих родителей.
    Но тут ещё нужно подумать над тем, как соблюсти врачебную тайну, если произойдёт ситуация, когда родители разведутся - это скорее вопрос к бизнес-процессу, а не к данным.

    Не совсем понятно, что скрывается за ролями, и почему у пользователя не может быть нескольких ролей.

    Также не понятно, почему позиция жёстко привязана к отделу.
    Кажется, есть смысл ввести отдельно таблицу для позиций (в оргструктуре) и должностей (специализации и грейды врачей)
    + Часто оргструктуры имеют древовидную форму с отделами/подотделами/филиалами
    + Часто есть деление на юридическую структуру (которая записывается во всяких юридически значимых документах) и ресурсную оргструктуры, которая описывает реальный бизнес-процесс.

    Вместо флага is_doctor в позиции следует всётаки какой-нибудь enum сделать, ибо потом захочется делить сотрудников на более чем две категории.
    Ответ написан
    7 комментариев
  • Gitlab CI/CD простого проекта?

    @d-stream
    Готовые решения - не подаю, но...
    ну примерно вот так:

    image: # имя докер-образа 
    
    stages:
      - build
      - tests
      - deploy
    
    build_my_project:
      stage: build
      tags: 
        - тэг раннера где запустить
      script:
        - ... # собственно действия для билда
        - ... 
        - ...
        - ...
      artifacts:
        name: как будет обзываться артефакт сборки
        paths:
        - путь до файлов в артефакт
        expire_in: 1 hour # сколько ему жить
    test1: 
      stage: tests
      tags: 
        - тэг раннера где запустить
      needs:
        - build
      scripts:
        - # действия по выполнению теста
    
    test2: 
      stage: tests
      tags: 
        - тэг раннера где запустить
      scripts:
        - # действия по выполнению теста 2
    
    deploy_to_dev:
      stage: deploy
      tags: 
        - тэг раннера где запустить
      needs:
        - tests
      rules:
        - if: $CI_COMMIT_BRANCH == "development"
      scripts:
        - # действия деплою в dev
    
    
    deploy_to_prod:
      stage: deploy
      tags: 
        - тэг раннера где запустить
      needs:
        - tests
      rules:
        - if: $CI_COMMIT_BRANCH == "master"
      scripts:
        - # действия деплою в dev


    словами: на первом шаге - build выполнится то что прописано в scripts (последовательно, по строкам)
    на втором шаге - test - параллельно выполнится два (ну или сколько надо блоков тестов)
    на третьем - deploy - выполнится или deploy_to_prod или deploy_to_dev или ничего в зависимости от того в какой ветке идет сборка ($CI_COMMIT_BRANCH)
    image: # имя докер-образа - имя соответсвующего docker-образа с подготовленной средой разработки (node:14 - для npm, mcr.microsoft.com/dotnet/sdk:6.0 - для .net6 и так далее)
    можно и любой свой

    needs: - описывает от каких шагов зависит шаг (это относительно свежее, ранее более жесткое dependencies:)
    Ответ написан
    1 комментарий
  • Как оптимизировать NOT IN (SELECT)?

    Revencu
    @Revencu
    SELECT `item_id`, ... 
    FROM `items_table` AS t1
    LEFT JOIN `shown_table` AS t2 on t1.`item_id`=t2.`shown_id`
    WHERE [сложное условие для поиска] 
    AND  t2.`user_id`=$user_id AND t2.`item_id` IS NULL
    LIMIT 1;
    Ответ написан
    Комментировать
  • Три цены, одна дефолтная, 2 зависят от чекбоксов, как все плюсовать?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    2 комментария
  • Как организовать оповещение пользователей?

    Tomio
    @Tomio
    backend developer (python, php)
    Это довольно просто можно реализовать через событийную систему. Посмотрите в сторону паттерна "Наблюдатель (Observer)". У вас будут подписчики на события (сервис уведомления по email, сервис уведомления в telegram и пр.), и когда наступит то или иное событие (в вашем случае, когда погода опустится ниже нуля) вам всего лишь нужно будет оповестить свои сервисы-подписчики и они уже оповестят пользователей.
    Ответ написан
    1 комментарий
  • Как найти ближайшую дату в массиве?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    const parseDate = (date) => Date.parse(date.split('/').reverse().join('-'));
    const findClosest = (list, date = (new Date()).toLocaleDateString('en-GB')) => {
      const findDate = parseDate(date);
      return list.reduce(
        (acc, cur) => {
          const delta = parseDate(cur.date) - findDate;
          return (delta >= 0 && delta < acc.delta) ? { delta, el: cur } : acc;
        },
        { delta: Number.MAX_SAFE_INTEGER, el: null },
      ).el;
    };
    Ответ написан
    Комментировать
  • Какая логика авторизации через соцсети на сайте c laravel jwt?

    JhaoDa
    @JhaoDa
    LaravelRUS Team
    Абисняю:
    1. Сохраняешь данные в БД — пользователя в одну таблицу, привязку к соцсети в другую.
    2. Аутентифицируешь (это не авторизация, когда вы уже поймёте разницу) пользователя по id в своей БД. Как — написано в документации.
    3. Надо запрашивать из соцсети ещё и мыло, оно и будет «объединяющим» ключом — редко кто регается в разных соцсетях с разными мылами. Ну а если и так, то ничего не поделать.
    Ответ написан
    4 комментария
  • Могут ли забанить аккаунт разработчика Google или Apple, если он публикует приложения своих клиентов с их согласия?

    alexgp13
    @alexgp13
    Руководитель ИТ-проектов
    Вряд ли забанят за такое, главное не нарушать правил магазина.

    Но могут быть другие проблемы:
    1. В случае нарушений правил магазина одним из заказчиков (или нарушений закона, и такое может быть) и Ваш аккаунт целиком забанят, и Вам самому может от органов привет прилететь.
    2. Особо упоротые заказчики могут подать жалобу на нарушение авторских прав, бан будет без предупреждения, потом замучаетесь доказывать что не верблюд и права были (реальный случай из моей практики, кстати).
    3. В случае нарушений правил одним магазином страдают все, зарегистрированные на аккаунте.
    4. Если Вы решите исчезнуть, то можете легко прихватить с собой все приложения, оставив магазины ни с чем (только на днях такая ситуация здесь же обсуждалась, когда украинский разработчик просто перестал выходить на связь). И восстановить приложения магазинам может обойтись очень дорого.

    Цена аккаунта в Android - 25 долларов, в iOS - 100 долларов в год. Вот простите, но ни за что не поверю, что эта сумма может быть критичной для любого бизнеса, решившего оплатить разработку приложения.
    Ответ написан
    1 комментарий
  • Стоит ли разделять проект?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега Веб-разработка
    В этом и заключается ваша работа - принимать такие решения на основе детального понимания проекта и планов его развития.
    Дяди и тёти из интернета за вас её сделать не могут, потому что детального понимания проекта у них нет и планов развития они не знают. Дяди и тёти из интернета могут только сказать абстрактные плюсы и минусы разделения или неразделения абстрактного проекта, но эта информация плохо транслируется на реальные проекты.
    Ответ написан
    Комментировать
  • Как добавить метки из json на все карты?

    freeExec
    @freeExec
    Участник OpenStreetMap
    Сам подход вывода кучи карт - странный.
    Метку на карту есть в примерах, это первое что надо искать

    https://yandex.ru/dev/maps/jsbox/2.1/object_manager
    Ответ написан
    1 комментарий
  • Почему не работает v-model?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Не работает потому, что работать нечему - вы не используете v-model. Документацию, судя по показанной чуши, вы вообще не читали (максимум, одним глазом глянули её пересказ каким-нибудь дегенератом на youtube'е). Это зря. Документацию читать надо. Вот прямо сейчас откройте и почитайте. Ну а пока читаете, исправим ваш говнокод.

    В родительском компоненте заменить model="global" на v-model="global".

    В дочернем, добавить:

    model: {
      prop: 'model',
    },
    computed: {
      checked() {
        return this.model === this.value;
      },
    },

    а шаблон пусть будет такой:

    <label :class="{ labelActive: checked }">
      <input type="radio" :checked="checked" @input="$emit('input', value)">
      {{ value }}
    </label>
    Ответ написан
    Комментировать
  • Знакомство нового пользователя через подсказки?

    @ksnk
    А в чем проблема посмотреть кто что смотрел?
    Таблица подсказок - {ID подсказки, страница (маска страниц, список страниц), селектор, событие, текст подсказки}.
    Таблица просмотров {ID юзера, ID подсказки, время демонстрации}
    Информация о подсказках с просмотрами left join собирается и выгружается на нужную страницу. Специальный виджет расставляет все непросмотренные подсказки по hover или клику мышки. Он же будет заботится о том, чтобы хранить информацию о показах, либо в localStore, для незарегистрированного, либо в профиле пользователя сайта. Если подсказка демонстрировалась недавно - можно не показывать...
    Удобно то, что система получится "независима" от остального сайта, в том смысле, что ее можно убрать и сайт продолжать работать. Можно поставить ее на любой существующий сайт, отдельно настраивать шаблоны сайта не придется, разве что обеспечить вменяемые селекторы для поясняемых элементов.
    Если вносится новая фича с подсказкой на сайт - никто ее пока не просмотрел - всем насильно показать.
    Придется сделать на каждой странице заметную кнопку "Расскажи мне опять все-все все про ту страницу", это для особо забывчивых. Сделать в профиле пользователя или на странице кнопку-галку "не показывать мне больше ваши всплывающие подсказки", ну чисто для полноты картины мира и ощущения справедливости...
    Ответ написан
    Комментировать
  • Как telegra.ph понимает, что я - это я?

    @psy667
    Node.js backend developer
    Там используются HttpOnly cookie. То есть сами cookie есть, но в браузере не видны, также к ним нельзя получить доступ из клиентского кода.
    В запросе /check можно увидеть, что в response headers они устанавливаются.
    Set-Cookie: tph_uuid=<token>; expires=Wed, 08 Feb 2023 05:42:55 GMT; path=/; secure; HttpOnly
    Ответ написан
    1 комментарий
  • Как правильно работать с git?

    fox_12
    @fox_12
    Расставляю биты, управляю заряженными частицами
    Какие пути есть кроме написания actions на гите

    Можно еще webhook использовать.
    На клиенте при этом можно что-то вроде этого установить:
    https://github.com/adnanh/webhook чтобы выполнять деплой по событию.
    Ответ написан
    Комментировать
  • Как очистить память Iphone перед продажей без возможности восстановления?

    С такой паранойей - только заменить чип памяти, а старый разбить
    Ответ написан
    Комментировать
  • Почему некоторые задания очереди в Laravel повторяются дважды?

    @jazzus
    Количество попыток не гарантирует. юзер может 10 раз на кнопку нажать и везде будет 1 попытка. попробуй добавить уникальность с номером инвойса https://laravel.com/docs/8.x/queues#unique-jobs
    Ответ написан
    2 комментария
  • Как быстро и надежно закрывать задачи по сайту не нанимая программиста?

    @Stalinko Куратор тега Фриланс
    PHP'шник и фрилансер до мозга костей
    Я пишу со стороны программиста. У меня есть ряд старых клиентов, которые иногда просыпаются и просят что-то доделать. Стараюсь найти для них время и помочь.

    Идеальное решение для вас было бы найти стабильного разработчика, который нормально во всём разбирается и готов периодически брать подработку.

    Тут есть один момент - разработчику обычно несложно взять подработку 5-10 часов в неделю. Но не стоит ждать, что человек всё бросит и всю неделю будет фулл-тайм колбасить ваши задачи. Если вы хотите, чтобы сделали большой объём быстро, тогда придётся каждый раз нанимать по новой. А если сможете разбить объём на маленькие части, которые можно делать, не отрываясь от основной работы, то вам должно быть по силам нанять такого человека.
    Ответ написан
    1 комментарий
  • В чем суть такой записи в reset.css?

    nowm
    @nowm
    Это специфичное для blockquote определение, которое Eric Meyer (автор reset.css) позаимствовал у Paul Chaplin. Первая строка content: "" делает так, чтобы у blockquote исчезли кавычки — на случай, если вторая строка content: none не поддерживается браузером, потому что первая строка — это CSS 2, а вторая — это CSS 2.1. В одну строку их записать нельзя, потому что по стандарту для свойства «content» нельзя комбинировать ключевые слова «normal» и «none» с другими значениями.

    Вообще, когда встречается перечисление одного и того же свойства с разными значениями, это делается для того, чтобы обеспечить совместимость с разными браузерами. То есть, если, например, браузер не поддерживает «content: none», он применит «content: ""», а другую запись проигнорирует.

    Обычно дублирующие записи располагаются в определённом порядке. Первой записью идёт самый плохой вариант, который должен сработать везде. Затем идёт вариант, который более полно описывает вашу цель. Пример:

    .some-class {
        background: #e66465;
        background: linear-gradient(#e66465, #9198e5);
    }


    В этом коде, если браузер поддерживает градиентный фон, он сначала прочитает, что нужно использовать цвет «#e66465», а потом это перезапишется записью «linear-gradient», и итоговое значение будет «linear-gradient(#e66465, #9198e5);». Если же браузер не поддерживает градиент, он сначала прочитает, что нужно использовать «#e66465», а потом увидит неподдерживаемое определение «linear-gradient», проигнорирует его, и итоговое значение будет «#e66465».
    Ответ написан
    Комментировать
  • Есть удачные примеры бота в Telegram для продажи товара (online-магазин)?

    Также интересует ваше мнение: эффективно ли в настоящее время использовать бота в Telegram в качестве online-магазина?

    Мне кажется, если это не магазин с запрещёнными веществами - нет.
    Просто из-за того что у чат-ботов слишком бедный UI и там сложно реализовать что-то адекватное.

    По тому все магазины делают через сайты и мобильные приложения.
    Ответ написан
    Комментировать
  • Стоит ли начинать свою «карьеру» с фриланса?

    @C15H22N6O5S
    Вы не совсем правильно понимаете как это работает. Во фрилансе не начинают карьеру. Её там "заканчивают". Это когда ты уже состоявшийся специалист, у тебя [коммерческая] недвижка в Москве, Сочи. Живёшь ты на рентный доход от этих и других инвестиций. А фриланс это так, "для души" сидишь на берегу кодишь исключительно что хочешь и когда хочешь, за "чаевые".
    Ответ написан
    Комментировать